From f3e716e1974fc5f79f2391f70b3692b1329d3de5 Mon Sep 17 00:00:00 2001 From: Antenore Gatta Date: Wed, 14 Jun 2023 18:35:06 +0000 Subject: Automatic doc build by remmina-ci --- public/rcw_8c_source.html | 16 +++++----- public/remmina__exec_8c_source.html | 8 ++--- public/remmina__file_8c.html | 22 +++++++------- public/remmina__file_8c_source.html | 24 +++++++-------- public/remmina__file_8h.html | 22 +++++++------- public/remmina__file_8h_source.html | 22 +++++++------- public/remmina__file__editor_8c_source.html | 16 +++++----- public/remmina__file__manager_8c.html | 12 ++++---- public/remmina__file__manager_8c_source.html | 16 +++++----- public/remmina__file__manager_8h.html | 10 +++---- public/remmina__file__manager_8h_source.html | 10 +++---- public/remmina__icon_8c_source.html | 2 +- public/remmina__log_8c_source.html | 2 +- public/remmina__main_8c_source.html | 20 ++++++------- public/remmina__mpchange_8c_source.html | 4 +-- public/remmina__plugin__manager_8c_source.html | 18 +++++------ public/remmina__pref_8c.html | 38 +++++++++++------------ public/remmina__pref_8c_source.html | 40 ++++++++++++------------- public/remmina__pref_8h.html | 38 +++++++++++------------ public/remmina__pref_8h_source.html | 38 +++++++++++------------ public/remmina__pref__dialog_8c_source.html | 8 ++--- public/remmina__protocol__widget_8c_source.html | 6 ++-- public/remmina__sftp__plugin_8c_source.html | 2 +- public/remmina__ssh__plugin_8c_source.html | 2 +- public/remmina__stats_8c_source.html | 4 +-- public/remmina__unlock_8c_source.html | 4 +-- 26 files changed, 202 insertions(+), 202 deletions(-) diff --git a/public/rcw_8c_source.html b/public/rcw_8c_source.html index c1c243be1..3f5c049bc 100644 --- a/public/rcw_8c_source.html +++ b/public/rcw_8c_source.html @@ -199,7 +199,7 @@ $(document).ready(function(){initNavTree('rcw_8c_source.html','');});
static GtkWidget * nb_find_page_by_cnnobj(GtkNotebook *notebook, RemminaConnectionObject *cnnobj)
Definition: rcw.c:3452
gchar * protocol
static gboolean rcw_keyboard_grab_retry(gpointer user_data)
Definition: rcw.c:484
-
void remmina_pref_add_recent(const gchar *protocol, const gchar *server)
Definition: remmina_pref.c:928
+
void remmina_pref_add_recent(const gchar *protocol, const gchar *server)
Definition: remmina_pref.c:929
static gboolean rcw_floating_toolbar_hide(RemminaConnectionWindow *cnnwin)
Definition: rcw.c:2991
static gboolean rcw_floating_toolbar_on_enter(GtkWidget *widget, GdkEventCrossing *event, RemminaConnectionWindow *cnnwin)
Definition: rcw.c:2791
static const GtkTargetEntry dnd_targets_tb[]
Definition: rcw.c:212
@@ -213,7 +213,7 @@ $(document).ready(function(){initNavTree('rcw_8c_source.html','');});
static void rco_get_desktop_size(RemminaConnectionObject *cnnobj, gint *width, gint *height)
Definition: rcw.c:906
Definition: types.h:49
int height
Definition: types.h:88
-
gchar * remmina_pref_get_value(const gchar *key)
+
gchar * remmina_pref_get_value(const gchar *key)
static RemminaConnectionObject * rcw_get_visible_cnnobj(RemminaConnectionWindow *cnnwin)
Definition: rcw.c:377
static gboolean rcw_focus_in_event(GtkWidget *widget, GdkEventWindowState *event, gpointer user_data)
Definition: rcw.c:3240
void remmina_protocol_widget_open_connection(RemminaProtocolWidget *gp)
@@ -232,7 +232,7 @@ $(document).ready(function(){initNavTree('rcw_8c_source.html','');});
static void remmina_protocol_widget_update_alignment(RemminaConnectionObject *cnnobj)
Definition: rcw.c:1148
GtkWidget * remmina_scrolled_viewport_new(void)
static gboolean rcw_on_switch_page_finalsel(gpointer user_data)
Definition: rcw.c:3624
-
void remmina_file_state_last_success(RemminaFile *remminafile)
Definition: remmina_file.c:946
+
void remmina_file_state_last_success(RemminaFile *remminafile)
Definition: remmina_file.c:948
static void print_crossing_event(GdkEventCrossing *event)
Definition: rcw.c:2762
static void rcw_toolbar_autofit(GtkToolItem *toggle, RemminaConnectionWindow *cnnwin)
Definition: rcw.c:988
General utility functions, non-GTK related.
@@ -311,7 +311,7 @@ $(document).ready(function(){initNavTree('rcw_8c_source.html','');});
int bitsPerPixel
Definition: types.h:85
gboolean remmina_protocol_widget_plugin_screenshot(RemminaProtocolWidget *gp, RemminaPluginScreenshotData *rpsd)
void remmina_applet_menu_populate(RemminaAppletMenu *menu)
-
gboolean remmina_pref_get_boolean(const gchar *key)
+
gboolean remmina_pref_get_boolean(const gchar *key)
GTKSOCKET_NOT_AVAIL_RESPONSE_TYPE
These define the response id's of the gtksocket-is-not-available-warning-dialog buttons.
Definition: rcw.c:4465
static void rcw_kp_ungrab(RemminaConnectionWindow *cnnwin)
Definition: rcw.c:429
void remmina_protocol_widget_grab_focus(RemminaProtocolWidget *gp)
@@ -371,7 +371,7 @@ $(document).ready(function(){initNavTree('rcw_8c_source.html','');});
static void rcw_update_notebook(RemminaConnectionWindow *cnnwin)
Definition: rcw.c:3603
Definition: types.h:50
-
gboolean remmina_pref_save(void)
Definition: remmina_pref.c:777
+
gboolean remmina_pref_save(void)
Definition: remmina_pref.c:778
void rcw_toolbar_switch_page_popdown(GtkWidget *widget, RemminaConnectionWindow *cnnwin)
Definition: rcw.c:1571
static gboolean rcw_floating_toolbar_make_invisible(gpointer data)
Definition: rcw.c:869
const gchar * screenshot_name
Definition: remmina_pref.h:139
@@ -394,14 +394,14 @@ $(document).ready(function(){initNavTree('rcw_8c_source.html','');});
void rco_update_toolbar_autofit_button(RemminaConnectionObject *cnnobj)
Definition: rcw.c:1633
gboolean extrahardening
Definition: remmina.c:90
void remmina_file_set_string(RemminaFile *remminafile, const gchar *setting, const gchar *value)
Definition: remmina_file.c:469
-
void remmina_file_save(RemminaFile *remminafile)
Definition: remmina_file.c:728
+
void remmina_file_save(RemminaFile *remminafile)
Definition: remmina_file.c:730
static GtkWidget * rcw_append_new_page(RemminaConnectionWindow *cnnwin, RemminaConnectionObject *cnnobj)
Definition: rcw.c:3573
void rco_get_monitor_geometry(RemminaConnectionObject *cnnobj, GdkRectangle *sz)
Definition: rcw.c:1009
Definition: remmina_pref.h:103
Definition: remmina_pref.h:79
gboolean remmina_protocol_widget_plugin_receives_keystrokes(RemminaProtocolWidget *gp)
Check if the plugin accepts keystrokes.
Definition: rcw.h:54
-
RemminaFile * remmina_file_manager_load_file(const gchar *filename)
+
RemminaFile * remmina_file_manager_load_file(const gchar *filename)
Definition: remmina_pref.h:102
gboolean rco_enter_protocol_widget(GtkWidget *widget, GdkEventCrossing *event, RemminaConnectionObject *cnnobj)
Definition: rcw.c:2884
@@ -409,7 +409,7 @@ $(document).ready(function(){initNavTree('rcw_8c_source.html','');});
static gboolean rcw_delete_event(GtkWidget *widget, GdkEvent *event, gpointer data)
Definition: rcw.c:694
static gboolean rcw_map_event(GtkWidget *widget, GdkEvent *event, gpointer data)
Definition: rcw.c:3282
gint remmina_unlock_new(GtkWindow *parent)
-
const gchar * remmina_file_get_icon_name(RemminaFile *remminafile)
Definition: remmina_file.c:883
+
const gchar * remmina_file_get_icon_name(RemminaFile *remminafile)
Definition: remmina_file.c:885
Definition: types.h:83
gint remmina_widget_pool_foreach(RemminaWidgetPoolForEachFunc callback, gpointer data)
gboolean connected
Definition: rcw.c:174
diff --git a/public/remmina__exec_8c_source.html b/public/remmina__exec_8c_source.html index 57ee93e9a..611522931 100644 --- a/public/remmina__exec_8c_source.html +++ b/public/remmina__exec_8c_source.html @@ -127,7 +127,7 @@ $(document).ready(function(){initNavTree('remmina__exec_8c_source.html','');});
Definition: remmina_exec.h:46
void remmina_exec_exitremmina()
Definition: remmina_exec.c:89
-
gboolean remmina_pref_get_boolean(const gchar *key)
+
gboolean remmina_pref_get_boolean(const gchar *key)
Definition: remmina_exec.h:54
GtkWidget * remmina_file_editor_new_from_filename(const gchar *filename)
void remmina_main_destroy()
Definition: remmina_main.c:193
@@ -150,9 +150,9 @@ $(document).ready(function(){initNavTree('remmina__exec_8c_source.html','');});
void remmina_application_condexit(RemminaCondExitType why)
Definition: remmina_exec.c:123
static gboolean disable_rcw_delete_confirm_cb(GtkWidget *widget, gpointer data)
Definition: remmina_exec.c:111
void remmina_file_set_string(RemminaFile *remminafile, const gchar *setting, const gchar *value)
Definition: remmina_file.c:469
-
void remmina_file_save(RemminaFile *remminafile)
Definition: remmina_file.c:728
+
void remmina_file_save(RemminaFile *remminafile)
Definition: remmina_file.c:730
Definition: rcw.h:54
-
RemminaFile * remmina_file_manager_load_file(const gchar *filename)
+
RemminaFile * remmina_file_manager_load_file(const gchar *filename)
static void newline_remove(char *s)
Definition: remmina_exec.c:155
gint remmina_unlock_new(GtkWindow *parent)
void remmina_plugin_manager_show_stdout()
@@ -163,7 +163,7 @@ $(document).ready(function(){initNavTree('remmina__exec_8c_source.html','');});
GtkWidget * remmina_pref_dialog_new(gint default_tab, GtkWindow *parent)
GtkWidget * remmina_pref_dialog_get_dialog()
-
gint remmina_file_manager_iterate(GFunc func, gpointer user_data)
+
gint remmina_file_manager_iterate(GFunc func, gpointer user_data)
Definition: remmina_exec.h:45
Definition: plugin.h:48
diff --git a/public/remmina__file_8c.html b/public/remmina__file_8c.html index a29149c54..e2332e884 100644 --- a/public/remmina__file_8c.html +++ b/public/remmina__file_8c.html @@ -242,7 +242,7 @@ Variables
-

Definition at line 909 of file remmina_file.c.

+

Definition at line 911 of file remmina_file.c.

@@ -262,7 +262,7 @@ Variables
-

Definition at line 863 of file remmina_file.c.

+

Definition at line 865 of file remmina_file.c.

@@ -292,7 +292,7 @@ Variables
-

Definition at line 897 of file remmina_file.c.

+

Definition at line 899 of file remmina_file.c.

@@ -397,7 +397,7 @@ Variables

This is used to return the modification date of a file and it’s used to return the modification date and time of a given Remmina file. If it fails it will return "Fri, 16 Oct 2009 07:04:46 GMT", that is just a date to don't return an empty string (challenge: what was happened that day at that time?).

Returns
A date string in the form "%d/%m/%Y %H:%M:%S".
Todo:
This should be moved to remmina_utils.c
-

Definition at line 1029 of file remmina_file.c.

+

Definition at line 1031 of file remmina_file.c.

@@ -473,7 +473,7 @@ Variables
-

Definition at line 883 of file remmina_file.c.

+

Definition at line 885 of file remmina_file.c.

@@ -625,7 +625,7 @@ Variables
-

Definition at line 923 of file remmina_file.c.

+

Definition at line 925 of file remmina_file.c.

@@ -815,7 +815,7 @@ Variables
-

Definition at line 728 of file remmina_file.c.

+

Definition at line 730 of file remmina_file.c.

@@ -1029,7 +1029,7 @@ Variables
-

Definition at line 946 of file remmina_file.c.

+

Definition at line 948 of file remmina_file.c.

@@ -1065,7 +1065,7 @@ Variables
-

Definition at line 844 of file remmina_file.c.

+

Definition at line 846 of file remmina_file.c.

@@ -1089,7 +1089,7 @@ Variables

Function used to update the atime and mtime of a given remmina file, partially taken from suckless sbase

See also
https://git.suckless.org/sbase/tree/touch.c
Todo:
This should be moved to remmina_utils.c
-

Definition at line 1103 of file remmina_file.c.

+

Definition at line 1105 of file remmina_file.c.

@@ -1109,7 +1109,7 @@ Variables
-

Definition at line 976 of file remmina_file.c.

+

Definition at line 978 of file remmina_file.c.

diff --git a/public/remmina__file_8c_source.html b/public/remmina__file_8c_source.html index 012815b5d..415e66860 100644 --- a/public/remmina__file_8c_source.html +++ b/public/remmina__file_8c_source.html @@ -86,21 +86,21 @@ $(document).ready(function(){initNavTree('remmina__file_8c_source.html','');});
remmina_file.c
-Go to the documentation of this file.
1 /*
2  * Remmina - The GTK+ Remote Desktop Client
3  * Copyright (C) 2009-2011 Vic Lee
4  * Copyright (C) 2014-2015 Antenore Gatta, Fabio Castelli, Giovanni Panozzo
5  * Copyright (C) 2016-2023 Antenore Gatta, Giovanni Panozzo
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  *
22  * In addition, as a special exception, the copyright holders give
23  * permission to link the code of portions of this program with the
24  * OpenSSL library under certain conditions as described in each
25  * individual source file, and distribute linked combinations
26  * including the two.
27  * You must obey the GNU General Public License in all respects
28  * for all of the code used other than OpenSSL. * If you modify
29  * file(s) with this exception, you may extend this exception to your
30  * version of the file(s), but you are not obligated to do so. * If you
31  * do not wish to do so, delete this exception statement from your
32  * version. * If you delete this exception statement from all source
33  * files in the program, then also delete it here.
34  *
35  */
36 
37 #include "config.h"
38 
39 
40 #include <errno.h>
41 #include <fcntl.h>
42 #include <sys/stat.h>
43 #include <locale.h>
44 #include <langinfo.h>
45 #include <stdlib.h>
46 #include <string.h>
47 #include <time.h>
48 #include <unistd.h>
49 #include <utime.h>
50 
51 #include <gtk/gtk.h>
52 #include <glib/gi18n.h>
53 #include <glib/gstdio.h>
54 
56 #include "remmina_crypt.h"
57 #include "remmina_file_manager.h"
58 #include "remmina_log.h"
59 #include "remmina_main.h"
61 #include "remmina_plugin_manager.h"
62 #include "remmina_pref.h"
63 #include "remmina_public.h"
64 #include "remmina_sodium.h"
65 #include "remmina_utils.h"
66 
67 #define MIN_WINDOW_WIDTH 10
68 #define MIN_WINDOW_HEIGHT 10
69 
70 #define KEYFILE_GROUP_REMMINA "remmina"
71 #define KEYFILE_GROUP_STATE "Remmina Connection States"
72 
73 static struct timespec times[2];
74 
75 static RemminaFile *
77 {
78  TRACE_CALL(__func__);
79  RemminaFile *remminafile;
80 
81  remminafile = g_new0(RemminaFile, 1);
82  remminafile->settings = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
83  remminafile->states = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
84  /* spsettings contains settings that are loaded from the secure_plugin.
85  * it’s used by remmina_file_store_secret_plugin_password() to know
86  * where to change */
87  remminafile->spsettings = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
88  remminafile->prevent_saving = FALSE;
89  return remminafile;
90 }
91 
94 {
95  TRACE_CALL(__func__);
96  RemminaFile *remminafile;
97 
98  /* Try to load from the preference file for default settings first */
99  remminafile = remmina_file_load(remmina_pref_file);
100 
101  if (remminafile) {
102  g_free(remminafile->filename);
103  remminafile->filename = NULL;
104  } else {
105  remminafile = remmina_file_new_empty();
106  }
107 
108  return remminafile;
109 }
110 
115 {
116  TRACE_CALL(__func__);
117 
127  gchar *invalid_chars = "\\%|/$?<>:*. \"";
128  GString *filenamestr;
129  const gchar *s;
130 
131 
132  /* functions we can use
133  * g_strstrip( string )
134  * Removes leading and trailing whitespace from a string
135  * g_strdelimit (str, invalid_chars, '-'))
136  * Convert each invalid_chars in a hyphen
137  * g_ascii_strdown(string)
138  * all lowercase
139  * To be safe we should remove control characters as well (but I'm lazy)
140  * https://rosettacode.org/wiki/Strip_control_codes_and_extended_characters_from_a_string#C
141  * g_utf8_strncpy (gchar *dest, const gchar *src, gsize n);
142  * copies a given number of characters instead of a given number of bytes. The src string must be valid UTF-8 encoded text.
143  * g_utf8_validate (const gchar *str, gssize max_len, const gchar **end);
144  * Validates UTF-8 encoded text.
145  */
146 
147  //g_free(remminafile->filename), remminafile->filename = NULL;
148 
149  filenamestr = g_string_new(g_strdup_printf("%s",
151  if ((s = remmina_file_get_string(remminafile, "name")) == NULL) s = "name";
152  if (g_strstr_len(filenamestr->str, -1, "%N") != NULL)
153  remmina_utils_string_replace_all(filenamestr, "%N", s);
154 
155  if ((s = remmina_file_get_string(remminafile, "group")) == NULL) s = "group";
156  if (g_strstr_len(filenamestr->str, -1, "%G") != NULL)
157  remmina_utils_string_replace_all(filenamestr, "%G", s);
158 
159  if ((s = remmina_file_get_string(remminafile, "protocol")) == NULL) s = "proto";
160  if (g_strstr_len(filenamestr->str, -1, "%P") != NULL)
161  remmina_utils_string_replace_all(filenamestr, "%P", s);
162 
163  if ((s = remmina_file_get_string(remminafile, "server")) == NULL) s = "host";
164  if (g_strstr_len(filenamestr->str, -1, "%h") != NULL)
165  remmina_utils_string_replace_all(filenamestr, "%h", s);
166 
167  s = NULL;
168 
169  g_autofree gchar *filename = g_strdelimit(g_ascii_strdown(g_strstrip(g_string_free(filenamestr, FALSE)), -1),
170  invalid_chars, '-');
171 
172  GDir *dir = g_dir_open(remmina_file_get_datadir(), 0, NULL);
173 
174  if (dir != NULL)
175  remminafile->filename = g_strdup_printf("%s/%s.remmina", remmina_file_get_datadir(), filename);
176  else
177  remminafile->filename = NULL;
178  g_dir_close(dir);
179 
180 }
181 
182 void remmina_file_set_filename(RemminaFile *remminafile, const gchar *filename)
183 {
184  TRACE_CALL(__func__);
185  g_free(remminafile->filename);
186  remminafile->filename = g_strdup(filename);
187 }
188 
190 {
191  TRACE_CALL(__func__);
192 
193  if (!remminafile)
194  return;
195  else
196  g_free(remminafile->statefile);
197 
198  gchar *basename = g_path_get_basename(remminafile->filename);
199  gchar *cachedir = g_build_path("/", g_get_user_cache_dir(), "remmina", NULL);
200  GString *fname = g_string_new(basename);
201 
202  remminafile->statefile = g_strdup_printf("%s/%s.state", cachedir, fname->str);
203 
204  g_free(cachedir);
205  g_string_free(fname, TRUE);
206  g_free(basename);
207 }
208 
209 const gchar *
211 {
212  TRACE_CALL(__func__);
213  return remminafile->filename;
214 }
215 
216 RemminaFile *
217 remmina_file_copy(const gchar *filename)
218 {
219  TRACE_CALL(__func__);
220  RemminaFile *remminafile;
221  gchar *buf;
222 
223  remminafile = remmina_file_load(filename);
224  buf = g_strdup_printf( "COPY %s",
225  remmina_file_get_string(remminafile, "name"));
226  remmina_file_set_string(remminafile, "name", buf);
227  g_free(buf);
228 
229  if (remminafile)
230  remmina_file_generate_filename(remminafile);
231 
232  return remminafile;
233 }
234 
235 const RemminaProtocolSetting *find_protocol_setting(const gchar *name, RemminaProtocolPlugin *protocol_plugin)
236 {
237  TRACE_CALL(__func__);
238  const RemminaProtocolSetting *setting_iter;
239 
240  if (protocol_plugin == NULL)
241  return NULL;
242 
243  setting_iter = protocol_plugin->basic_settings;
244  if (setting_iter) {
245  while (setting_iter->type != REMMINA_PROTOCOL_SETTING_TYPE_END) {
246  if (strcmp(name, remmina_plugin_manager_get_canonical_setting_name(setting_iter)) == 0)
247  return setting_iter;
248  setting_iter++;
249  }
250  }
251 
252  setting_iter = protocol_plugin->advanced_settings;
253  if (setting_iter) {
254  while (setting_iter->type != REMMINA_PROTOCOL_SETTING_TYPE_END) {
255  if (strcmp(name, remmina_plugin_manager_get_canonical_setting_name(setting_iter)) == 0)
256  return setting_iter;
257  setting_iter++;
258  }
259  }
260 
261  return NULL;
262 }
263 
264 
265 static void upgrade_sshkeys_202001_mig_common_setting(RemminaFile *remminafile, gboolean protocol_is_ssh, gboolean ssh_enabled, gchar *suffix)
266 {
267  gchar *src_key;
268  gchar *dst_key;
269  const gchar *val;
270 
271  src_key = g_strdup_printf("ssh_%s", suffix);
272  dst_key = g_strdup_printf("ssh_tunnel_%s", suffix);
273 
274  val = remmina_file_get_string(remminafile, src_key);
275  if (!val) {
276  g_free(dst_key);
277  g_free(src_key);
278  return;
279  }
280 
281  if (ssh_enabled && val && val[0] != 0)
282  remmina_file_set_string(remminafile, dst_key, val);
283 
284  if (!protocol_is_ssh)
285  remmina_file_set_string(remminafile, src_key, NULL);
286 
287  g_free(dst_key);
288  g_free(src_key);
289 }
290 
291 static void upgrade_sshkeys_202001(RemminaFile *remminafile)
292 {
293  TRACE_CALL(__func__);
294 
295  gboolean protocol_is_ssh;
296  gboolean ssh_enabled;
297  const gchar *val;
298 
299  if (remmina_file_get_string(remminafile, "ssh_enabled")) {
300  /* Upgrade ssh params from remmina pre 1.4 */
301 
302  ssh_enabled = remmina_file_get_int(remminafile, "ssh_enabled", 0);
303  val = remmina_file_get_string(remminafile, "protocol");
304  protocol_is_ssh = (strcmp(val, "SSH") == 0);
305 
306  upgrade_sshkeys_202001_mig_common_setting(remminafile, protocol_is_ssh, ssh_enabled, "stricthostkeycheck");
307  upgrade_sshkeys_202001_mig_common_setting(remminafile, protocol_is_ssh, ssh_enabled, "kex_algorithms");
308  upgrade_sshkeys_202001_mig_common_setting(remminafile, protocol_is_ssh, ssh_enabled, "hostkeytypes");
309  upgrade_sshkeys_202001_mig_common_setting(remminafile, protocol_is_ssh, ssh_enabled, "ciphers");
310  upgrade_sshkeys_202001_mig_common_setting(remminafile, protocol_is_ssh, ssh_enabled, "proxycommand");
311  upgrade_sshkeys_202001_mig_common_setting(remminafile, protocol_is_ssh, ssh_enabled, "passphrase");
312  upgrade_sshkeys_202001_mig_common_setting(remminafile, protocol_is_ssh, ssh_enabled, "auth");
313  upgrade_sshkeys_202001_mig_common_setting(remminafile, protocol_is_ssh, ssh_enabled, "privatekey");
314 
315  val = remmina_file_get_string(remminafile, "ssh_loopback");
316  if (val) {
317  remmina_file_set_string(remminafile, "ssh_tunnel_loopback", val);
318  remmina_file_set_string(remminafile, "ssh_loopback", NULL);
319  }
320 
321  val = remmina_file_get_string(remminafile, "ssh_username");
322  if (val) {
323  remmina_file_set_string(remminafile, "ssh_tunnel_username", val);
324  if (protocol_is_ssh)
325  remmina_file_set_string(remminafile, "username", val);
326  remmina_file_set_string(remminafile, "ssh_username", NULL);
327  }
328 
329  val = remmina_file_get_string(remminafile, "ssh_password");
330  if (val) {
331  remmina_file_set_string(remminafile, "ssh_tunnel_password", val);
332  if (protocol_is_ssh)
333  remmina_file_set_string(remminafile, "password", val);
334  remmina_file_set_string(remminafile, "ssh_password", NULL);
335  }
336 
337  val = remmina_file_get_string(remminafile, "ssh_server");
338  if (val) {
339  remmina_file_set_string(remminafile, "ssh_tunnel_server", val);
340  remmina_file_set_string(remminafile, "ssh_server", NULL);
341  }
342 
343  /* Real key removal will be done by remmina_file_save() */
344 
345  remmina_file_set_int(remminafile, "ssh_tunnel_enabled", ssh_enabled);
346  }
347 }
348 
349 RemminaFile *
350 remmina_file_load(const gchar *filename)
351 {
352  TRACE_CALL(__func__);
353  GKeyFile *gkeyfile;
354  RemminaFile *remminafile;
355  gchar *key;
356  gchar *s;
357  RemminaProtocolPlugin *protocol_plugin;
358  RemminaSecretPlugin *secret_plugin;
359  gboolean secret_service_available;
360  int w, h;
361 
362  gkeyfile = g_key_file_new();
363 
364  if (g_file_test(filename, G_FILE_TEST_IS_REGULAR | G_FILE_TEST_EXISTS)) {
365  if (!g_key_file_load_from_file(gkeyfile, filename, G_KEY_FILE_NONE, NULL)) {
366  g_key_file_free(gkeyfile);
367  REMMINA_DEBUG("Unable to load remmina profile file %s: g_key_file_load_from_file() returned NULL.\n", filename);
368  return NULL;
369  }
370  }
371 
372  if (!g_key_file_has_key(gkeyfile, KEYFILE_GROUP_REMMINA, "name", NULL)) {
373 
374  REMMINA_DEBUG("Unable to load remmina profile file %s: cannot find key name= in section remmina.\n", filename);
375  remminafile = NULL;
376  remmina_file_set_statefile(remminafile);
377 
378  g_key_file_free(gkeyfile);
379 
380  return remminafile;
381  }
382  remminafile = remmina_file_new_empty();
383 
384  protocol_plugin = NULL;
385 
386  /* Identify the protocol plugin and get pointers to its RemminaProtocolSetting structs */
387  gchar *proto = g_key_file_get_string(gkeyfile, KEYFILE_GROUP_REMMINA, "protocol", NULL);
388  if (proto) {
390  g_free(proto);
391  }
392 
394  secret_service_available = secret_plugin && secret_plugin->is_service_available(secret_plugin);
395 
396  remminafile->filename = g_strdup(filename);
397  gsize nkeys = 0;
398  gint keyindex;
399  GError *err = NULL;
400  gchar **keys = g_key_file_get_keys(gkeyfile, KEYFILE_GROUP_REMMINA, &nkeys, &err);
401  if (keys == NULL) {
402  g_clear_error(&err);
403  }
404  for (keyindex = 0; keyindex < nkeys; ++keyindex) {
405  key = keys[keyindex];
406  /* It may contain an encrypted password
407  * - password = . // secret_service
408  * - password = $argon2id$v=19$m=262144,t=3,p=… // libsodium
409  */
410  if (protocol_plugin && remmina_plugin_manager_is_encrypted_setting(protocol_plugin, key)) {
411  s = g_key_file_get_string(gkeyfile, KEYFILE_GROUP_REMMINA, key, NULL);
412 #if 0
413  switch (remmina_pref.enc_mode) {
417 #if SODIUM_VERSION_INT >= 90200
418 #endif
419  break;
420  case RM_ENC_MODE_GCRYPT:
421  break;
422  case RM_ENC_MODE_SECRET:
423  default:
424  break;
425  }
426 #endif
427  if ((g_strcmp0(s, ".") == 0) && (secret_service_available)) {
428  gchar *sec = secret_plugin->get_password(secret_plugin, remminafile, key);
429  remmina_file_set_string(remminafile, key, sec);
430  /* Annotate in spsettings that this value comes from secret_plugin */
431  g_hash_table_insert(remminafile->spsettings, g_strdup(key), NULL);
432  g_free(sec);
433  } else {
434  gchar *decrypted;
435  decrypted = remmina_crypt_decrypt(s);
436  remmina_file_set_string(remminafile, key, decrypted);
437  g_free(decrypted);
438  }
439  g_free(s), s = NULL;
440  } else {
441  /* If we find "resolution", then we split it in two */
442  if (strcmp(key, "resolution") == 0) {
443  gchar *resolution_str = g_key_file_get_string(gkeyfile, KEYFILE_GROUP_REMMINA, key, NULL);
444  if (remmina_public_split_resolution_string(resolution_str, &w, &h)) {
445  gchar *buf;
446  buf = g_strdup_printf("%i", w); remmina_file_set_string(remminafile, "resolution_width", buf); g_free(buf);
447  buf = g_strdup_printf("%i", h); remmina_file_set_string(remminafile, "resolution_height", buf); g_free(buf);
448  } else {
449  remmina_file_set_string(remminafile, "resolution_width", NULL);
450  remmina_file_set_string(remminafile, "resolution_height", NULL);
451  }
452  g_free(resolution_str);
453  } else {
454  gchar *value;
455  value = g_key_file_get_string(gkeyfile, KEYFILE_GROUP_REMMINA, key, NULL);
456  remmina_file_set_string(remminafile, key, value);
457  g_free(value);
458  }
459  }
460  }
461 
462  upgrade_sshkeys_202001(remminafile);
463  g_strfreev(keys);
464  remmina_file_set_statefile(remminafile);
465  g_key_file_free(gkeyfile);
466  return remminafile;
467 }
468 
469 void remmina_file_set_string(RemminaFile *remminafile, const gchar *setting, const gchar *value)
470 {
471  TRACE_CALL(__func__);
472 
473  /* Note: setting and value are copied on the heap, so it is responsibility of the caller
474  * to deallocate them when returning from remmina_file_set_string() if needed */
475 
477  /* Allow the execution of this function from a non main thread
478  * (plugins needs it to have user credentials)*/
480  d = (RemminaMTExecData *)g_malloc(sizeof(RemminaMTExecData));
481  d->func = FUNC_FILE_SET_STRING;
482  d->p.file_set_string.remminafile = remminafile;
483  d->p.file_set_string.setting = setting;
484  d->p.file_set_string.value = value;
486  g_free(d);
487  return;
488  }
489 
490  if (value) {
491  /* We refuse to accept to set the "resolution" field */
492  if (strcmp(setting, "resolution") == 0) {
493  // TRANSLATORS: This is a message that pops up when an external Remmina plugin tries to set the window resolution using a legacy parameter.
494  const gchar *message = _("Using the «resolution» parameter in the Remmina preferences file is deprecated.\n");
495  REMMINA_CRITICAL(message);
497  return;
498  }
499  g_hash_table_insert(remminafile->settings, g_strdup(setting), g_strdup(value));
500  } else {
501  g_hash_table_insert(remminafile->settings, g_strdup(setting), g_strdup(""));
502  }
503 }
504 
505 void remmina_file_set_state(RemminaFile *remminafile, const gchar *setting, const gchar *value)
506 {
507  TRACE_CALL(__func__);
508 
509  if (value && value[0] != 0)
510  g_hash_table_insert(remminafile->states, g_strdup(setting), g_strdup(value));
511  else
512  g_hash_table_insert(remminafile->states, g_strdup(setting), g_strdup(""));
513 }
514 
515 const gchar *
516 remmina_file_get_string(RemminaFile *remminafile, const gchar *setting)
517 {
518  TRACE_CALL(__func__);
519  gchar *value;
520 
521  /* Returned value is a pointer to the string stored on the hash table,
522  * please do not free it or the hash table will contain invalid pointer */
524  /* Allow the execution of this function from a non main thread
525  * (plugins needs it to have user credentials)*/
527  const gchar *retval;
528  d = (RemminaMTExecData *)g_malloc(sizeof(RemminaMTExecData));
529  d->func = FUNC_FILE_GET_STRING;
530  d->p.file_get_string.remminafile = remminafile;
531  d->p.file_get_string.setting = setting;
533  retval = d->p.file_get_string.retval;
534  g_free(d);
535  return retval;
536  }
537 
538  if (strcmp(setting, "resolution") == 0) {
539  // TRANSLATORS: This is a message that pop-up when an external Remmina plugin tries to set the windows resolution using a legacy parameter.
540  const gchar *message = _("Using the «resolution» parameter in the Remmina preferences file is deprecated.\n");
541  REMMINA_CRITICAL(message);
543  return NULL;
544  }
545 
546  value = (gchar *)g_hash_table_lookup(remminafile->settings, setting);
547  return value && value[0] ? value : NULL;
548 }
549 
550 gchar *
551 remmina_file_get_secret(RemminaFile *remminafile, const gchar *setting)
552 {
553  TRACE_CALL(__func__);
554 
555  /* This function is in the RemminaPluginService table, we cannot remove it
556  * without breaking plugin API */
557  g_warning("remmina_file_get_secret(remminafile,“%s”) is deprecated and must not be called. Use remmina_file_get_string() and do not deallocate returned memory.\n", setting);
558  return g_strdup(remmina_file_get_string(remminafile, setting));
559 }
560 
561 gchar *remmina_file_format_properties(RemminaFile *remminafile, const gchar *setting)
562 {
563  gchar *res = NULL;
564  GString *fmt_str;
565  GDateTime *now;
566  gchar *date_str = NULL;
567 
568  fmt_str = g_string_new(setting);
569  remmina_utils_string_replace_all(fmt_str, "%h", remmina_file_get_string(remminafile, "server"));
570  remmina_utils_string_replace_all(fmt_str, "%t", remmina_file_get_string(remminafile, "ssh_tunnel_server"));
571  remmina_utils_string_replace_all(fmt_str, "%u", remmina_file_get_string(remminafile, "username"));
572  remmina_utils_string_replace_all(fmt_str, "%U", remmina_file_get_string(remminafile, "ssh_tunnel_username"));
573  remmina_utils_string_replace_all(fmt_str, "%p", remmina_file_get_string(remminafile, "name"));
574  remmina_utils_string_replace_all(fmt_str, "%g", remmina_file_get_string(remminafile, "group"));
575 
576  now = g_date_time_new_now_local();
577  date_str = g_date_time_format(now, "%FT%TZ");
578  remmina_utils_string_replace_all(fmt_str, "%d", date_str);
579  g_free(date_str);
580 
581  res = g_string_free(fmt_str, FALSE);
582  return res;
583 }
584 
585 void remmina_file_set_int(RemminaFile *remminafile, const gchar *setting, gint value)
586 {
587  TRACE_CALL(__func__);
588  if (remminafile)
589  g_hash_table_insert(remminafile->settings,
590  g_strdup(setting),
591  g_strdup_printf("%i", value));
592 }
593 
594 void remmina_file_set_state_int(RemminaFile *remminafile, const gchar *setting, gint value)
595 {
596  TRACE_CALL(__func__);
597  if (remminafile)
598  g_hash_table_insert(remminafile->states,
599  g_strdup(setting),
600  g_strdup_printf("%i", value));
601 }
602 
603 gint remmina_file_get_int(RemminaFile *remminafile, const gchar *setting, gint default_value)
604 {
605  TRACE_CALL(__func__);
606  gchar *value;
607  gint r;
608 
609  value = g_hash_table_lookup(remminafile->settings, setting);
610  r = value == NULL ? default_value : (value[0] == 't' ? TRUE : atoi(value));
611  // TOO verbose: REMMINA_DEBUG ("Integer value is: %d", r);
612  return r;
613 }
614 
615 gint remmina_file_get_state_int(RemminaFile *remminafile, const gchar *setting, gint default_value)
616 {
617  TRACE_CALL(__func__);
618  gchar *value;
619  gint r;
620 
621  value = g_hash_table_lookup(remminafile->states, setting);
622  r = value == NULL ? default_value : (value[0] == 't' ? TRUE : atoi(value));
623  // TOO verbose: REMMINA_DEBUG ("Integer value is: %d", r);
624  return r;
625 }
626 
627 // sscanf uses the set language to convert the float.
628 // therefore '.' and ',' cannot be used interchangeably.
629 gdouble remmina_file_get_double(RemminaFile * remminafile,
630  const gchar * setting,
631  gdouble default_value)
632 {
633  TRACE_CALL(__func__);
634  gchar *value;
635 
636  value = g_hash_table_lookup(remminafile->settings, setting);
637  if (!value)
638  return default_value;
639 
640  // str to double.
641  // https://stackoverflow.com/questions/10075294/converting-string-to-a-double-variable-in-c
642  gdouble d;
643  gint ret = sscanf(value, "%lf", &d);
644 
645  if (ret != 1)
646  // failed.
647  d = default_value;
648 
649  // TOO VERBOSE: REMMINA_DEBUG("Double value is: %lf", d);
650  return d;
651 }
652 
653 // sscanf uses the set language to convert the float.
654 // therefore '.' and ',' cannot be used interchangeably.
656  const gchar * setting,
657  gdouble default_value)
658 {
659  TRACE_CALL(__func__);
660  gchar *value;
661 
662  value = g_hash_table_lookup(remminafile->states, setting);
663  if (!value)
664  return default_value;
665 
666  // str to double.
667  // https://stackoverflow.com/questions/10075294/converting-string-to-a-double-variable-in-c
668  gdouble d;
669  gint ret = sscanf(value, "%lf", &d);
670 
671  if (ret != 1)
672  // failed.
673  d = default_value;
674 
675  // TOO VERBOSE: REMMINA_DEBUG("Double value is: %lf", d);
676  return d;
677 }
678 
679 static GKeyFile *
681 {
682  TRACE_CALL(__func__);
683  GKeyFile *gkeyfile;
684 
685  if (remminafile->filename == NULL)
686  return NULL;
687  gkeyfile = g_key_file_new();
688  if (!g_key_file_load_from_file(gkeyfile, remminafile->filename, G_KEY_FILE_NONE, NULL)) {
689  /* it will fail if it’s a new file, but shouldn’t matter. */
690  }
691  return gkeyfile;
692 }
693 
694 static GKeyFile *
696 {
697  TRACE_CALL(__func__);
698  GKeyFile *gkeyfile;
699 
700  if (remminafile->statefile == NULL)
701  return NULL;
702  gkeyfile = g_key_file_new();
703  if (!g_key_file_load_from_file(gkeyfile, remminafile->statefile, G_KEY_FILE_NONE, NULL)) {
704  /* it will fail if it’s a new file, but shouldn’t matter. */
705  }
706  return gkeyfile;
707 }
708 
709 void remmina_file_free(RemminaFile *remminafile)
710 {
711  TRACE_CALL(__func__);
712  if (remminafile == NULL)
713  return;
714 
715  if (remminafile->filename)
716  g_free(remminafile->filename);
717  if (remminafile->statefile)
718  g_free(remminafile->statefile);
719  if (remminafile->settings)
720  g_hash_table_destroy(remminafile->settings);
721  if (remminafile->spsettings)
722  g_hash_table_destroy(remminafile->spsettings);
723 
724  g_free(remminafile);
725 }
726 
727 
728 void remmina_file_save(RemminaFile *remminafile)
729 {
730  TRACE_CALL(__func__);
731  RemminaSecretPlugin *secret_plugin;
732  gboolean secret_service_available;
733  RemminaProtocolPlugin *protocol_plugin;
734  GHashTableIter iter;
735  const gchar *key, *value;
736  gchar *s, *proto, *content;
737  gint nopasswdsave;
738  GKeyFile *gkeyfile;
739  GKeyFile *gkeystate;
740  gsize length = 0;
741  GError *err = NULL;
742 
743  if (remminafile->prevent_saving)
744  return;
745 
746  if ((gkeyfile = remmina_file_get_keyfile(remminafile)) == NULL)
747  return;
748 
749  if ((gkeystate = remmina_file_get_keystate(remminafile)) == NULL)
750  return;
751 
752  REMMINA_DEBUG("Saving profile");
753  /* get disablepasswordstoring */
754  nopasswdsave = remmina_file_get_int(remminafile, "disablepasswordstoring", 0);
755  /* Identify the protocol plugin and get pointers to its RemminaProtocolSetting structs */
756  proto = (gchar *)g_hash_table_lookup(remminafile->settings, "protocol");
757  if (proto) {
759  } else {
760  REMMINA_CRITICAL("Saving settings for unknown protocol:", proto);
761  protocol_plugin = NULL;
762  }
763 
765  secret_service_available = secret_plugin && secret_plugin->is_service_available(secret_plugin);
766 
767  g_hash_table_iter_init(&iter, remminafile->settings);
768  while (g_hash_table_iter_next(&iter, (gpointer *)&key, (gpointer *)&value)) {
769  if (remmina_plugin_manager_is_encrypted_setting(protocol_plugin, key)) {
770  if (remminafile->filename && g_strcmp0(remminafile->filename, remmina_pref_file)) {
771  if (secret_service_available && nopasswdsave == 0) {
772  REMMINA_DEBUG("We have a secret and disablepasswordstoring=0");
773  if (value && value[0]) {
774  if (g_strcmp0(value, ".") != 0)
775  secret_plugin->store_password(secret_plugin, remminafile, key, value);
776  g_key_file_set_string(gkeyfile, KEYFILE_GROUP_REMMINA, key, ".");
777  } else {
778  g_key_file_set_string(gkeyfile, KEYFILE_GROUP_REMMINA, key, "");
779  secret_plugin->delete_password(secret_plugin, remminafile, key);
780  }
781  } else {
782  REMMINA_DEBUG("We have a password and disablepasswordstoring=0");
783  if (value && value[0] && nopasswdsave == 0) {
784  s = remmina_crypt_encrypt(value);
785  g_key_file_set_string(gkeyfile, KEYFILE_GROUP_REMMINA, key, s);
786  g_free(s);
787  } else {
788  g_key_file_set_string(gkeyfile, KEYFILE_GROUP_REMMINA, key, "");
789  }
790  }
791  if (secret_service_available && nopasswdsave == 1) {
792  if (value && value[0]) {
793  if (g_strcmp0(value, ".") != 0) {
794  REMMINA_DEBUG("Deleting the secret in the keyring as disablepasswordstoring=1");
795  secret_plugin->delete_password(secret_plugin, remminafile, key);
796  g_key_file_set_string(gkeyfile, KEYFILE_GROUP_REMMINA, key, ".");
797  }
798  }
799  }
800  }
801  } else {
802  g_key_file_set_string(gkeyfile, KEYFILE_GROUP_REMMINA, key, value);
803  }
804  }
805 
806  /* Avoid storing redundant and deprecated "resolution" field */
807  g_key_file_remove_key(gkeyfile, KEYFILE_GROUP_REMMINA, "resolution", NULL);
808 
809  /* Delete old pre-1.4 ssh keys */
810  g_key_file_remove_key(gkeyfile, KEYFILE_GROUP_REMMINA, "ssh_enabled", NULL);
811  g_key_file_remove_key(gkeyfile, KEYFILE_GROUP_REMMINA, "save_ssh_server", NULL);
812  g_key_file_remove_key(gkeyfile, KEYFILE_GROUP_REMMINA, "save_ssh_username", NULL);
813 
814  /* Store gkeyfile to disk (password are already sent to keyring) */
815  content = g_key_file_to_data(gkeyfile, &length, NULL);
816 
817  if (g_file_set_contents(remminafile->filename, content, length, &err))
818  REMMINA_DEBUG("Profile saved");
819  else
820  REMMINA_WARNING("Remmina connection profile cannot be saved, with error %d (%s)", err->code, err->message);
821  if (err != NULL)
822  g_error_free(err);
823 
824  g_free(content), content = NULL;
825  /* Saving states */
826  g_hash_table_iter_init(&iter, remminafile->states);
827  while (g_hash_table_iter_next(&iter, (gpointer *)&key, (gpointer *)&value))
828  g_key_file_set_string(gkeyfile, KEYFILE_GROUP_STATE, key, value);
829  content = g_key_file_to_data(gkeystate, &length, NULL);
830  if (g_file_set_contents(remminafile->statefile, content, length, &err))
831  REMMINA_DEBUG("Connection profile states saved");
832  else
833  REMMINA_WARNING("Remmina connection profile cannot be saved, with error %d (%s)", err->code, err->message);
834  if (err != NULL)
835  g_error_free(err);
836  g_free(content), content = NULL;
837  g_key_file_free(gkeyfile);
838  g_key_file_free(gkeystate);
839 
842 }
843 
844 void remmina_file_store_secret_plugin_password(RemminaFile *remminafile, const gchar *key, const gchar *value)
845 {
846  TRACE_CALL(__func__);
847 
848  /* Only change the password in the keyring. This function
849  * is a shortcut which avoids updating of date/time of .pref file
850  * when possible, and is used by the mpchanger */
851  RemminaSecretPlugin *plugin;
852 
853  if (g_hash_table_lookup_extended(remminafile->spsettings, g_strdup(key), NULL, NULL)) {
855  plugin->store_password(plugin, remminafile, key, value);
856  } else {
857  remmina_file_set_string(remminafile, key, value);
858  remmina_file_save(remminafile);
859  }
860 }
861 
862 RemminaFile *
864 {
865  TRACE_CALL(__func__);
866  RemminaFile *dupfile;
867  GHashTableIter iter;
868  const gchar *key, *value;
869 
870  dupfile = remmina_file_new_empty();
871  dupfile->filename = g_strdup(remminafile->filename);
872 
873  g_hash_table_iter_init(&iter, remminafile->settings);
874  while (g_hash_table_iter_next(&iter, (gpointer *)&key, (gpointer *)&value))
875  remmina_file_set_string(dupfile, key, value);
876 
878  remmina_file_touch(dupfile);
879  return dupfile;
880 }
881 
882 const gchar *
884 {
885  TRACE_CALL(__func__);
886  RemminaProtocolPlugin *plugin;
887 
889  remmina_file_get_string(remminafile, "protocol"));
890  if (!plugin)
891  return g_strconcat(REMMINA_APP_ID, "-symbolic", NULL);
892 
893  return remmina_file_get_int(remminafile, "ssh_tunnel_enabled", FALSE) ? plugin->icon_name_ssh : plugin->icon_name;
894 }
895 
896 RemminaFile *
897 remmina_file_dup_temp_protocol(RemminaFile *remminafile, const gchar *new_protocol)
898 {
899  TRACE_CALL(__func__);
900  RemminaFile *tmp;
901 
902  tmp = remmina_file_dup(remminafile);
903  g_free(tmp->filename);
904  tmp->filename = NULL;
905  remmina_file_set_string(tmp, "protocol", new_protocol);
906  return tmp;
907 }
908 
909 void remmina_file_delete(const gchar *filename)
910 {
911  TRACE_CALL(__func__);
912  RemminaFile *remminafile;
913 
914  remminafile = remmina_file_load(filename);
915  if (remminafile) {
916  remmina_file_unsave_passwords(remminafile);
917  remmina_file_free(remminafile);
918  }
919  g_unlink(filename);
920 }
921 
922 const gchar *
923 remmina_file_get_state(RemminaFile *remminafile, const gchar *setting)
924 {
925  TRACE_CALL(__func__);
926  g_autoptr(GError) error = NULL;
927  g_autoptr(GKeyFile) key_file = g_key_file_new();
928 
929  if (!g_key_file_load_from_file(key_file, remminafile->statefile, G_KEY_FILE_NONE, &error)) {
930  if (!g_error_matches(error, G_FILE_ERROR, G_FILE_ERROR_NOENT))
931  REMMINA_CRITICAL("Could not load the state file. %s", error->message);
932  return NULL;
933  }
934 
935  g_autofree gchar *val = g_key_file_get_string(key_file, KEYFILE_GROUP_STATE, setting, &error);
936 
937  if (val == NULL &&
938  !g_error_matches(error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_KEY_NOT_FOUND)) {
939  REMMINA_CRITICAL("Could not find \"%s\" in the \"%s\" state file. %s",
940  setting, remminafile->statefile, error->message);
941  return NULL;
942  }
943  return val && val[0] ? val : NULL;
944 }
945 
947 {
948  TRACE_CALL(__func__);
949 
950  g_autoptr(GKeyFile) key_statefile = g_key_file_new();
951  g_autoptr(GKeyFile) key_remminafile = g_key_file_new();
952  GError *error = NULL;
953 
954  const gchar *date = NULL;
955  GDateTime *d = g_date_time_new_now_utc();
956 
957  date = g_strdup_printf("%d%02d%02d",
958  g_date_time_get_year(d),
959  g_date_time_get_month(d),
960  g_date_time_get_day_of_month(d));
961 
962  g_key_file_set_string(key_statefile, KEYFILE_GROUP_STATE, "last_success", date);
963 
964  REMMINA_DEBUG("State file %s.", remminafile->statefile);
965  if (!g_key_file_save_to_file(key_statefile, remminafile->statefile, &error)) {
966  REMMINA_CRITICAL("Could not save the key file. %s", error->message);
967  g_error_free(error);
968  error = NULL;
969  return;
970  }
971  /* Delete old pre-1.5 keys */
972  g_key_file_remove_key(key_remminafile, KEYFILE_GROUP_REMMINA, "last_success", NULL);
973  REMMINA_DEBUG("Last connection made on %s.", date);
974 }
975 
977 {
978  /* Delete all saved secrets for this profile */
979 
980  TRACE_CALL(__func__);
981  const RemminaProtocolSetting *setting_iter;
982  RemminaProtocolPlugin *protocol_plugin;
983  gchar *proto;
984 
985  protocol_plugin = NULL;
986 
987  remmina_file_set_string(remminafile, "password", NULL);
988 
989  proto = (gchar *)g_hash_table_lookup(remminafile->settings, "protocol");
990  if (proto) {
992  if (protocol_plugin) {
993  setting_iter = protocol_plugin->basic_settings;
994  if (setting_iter) {
995  while (setting_iter->type != REMMINA_PROTOCOL_SETTING_TYPE_END) {
996  // TOO VERBOSE: g_debug("setting name: %s", setting_iter->name);
997  if (setting_iter->name == NULL)
998  g_error("Internal error: a setting name in protocol plugin %s is null. Please fix RemminaProtocolSetting struct content.", proto);
999  else
1000  if (remmina_plugin_manager_is_encrypted_setting(protocol_plugin, setting_iter->name))
1002  setting_iter++;
1003  }
1004  }
1005  setting_iter = protocol_plugin->advanced_settings;
1006  if (setting_iter) {
1007  while (setting_iter->type != REMMINA_PROTOCOL_SETTING_TYPE_END) {
1008  if (remmina_plugin_manager_is_encrypted_setting(protocol_plugin, setting_iter->name))
1010  setting_iter++;
1011  }
1012  }
1013  remmina_file_save(remminafile);
1014  }
1015  }
1016 }
1017 
1028 gchar *
1030 {
1031  TRACE_CALL(__func__);
1032 
1033  GFile *file;
1034  GFileInfo *info;
1035 
1036  struct timeval tv;
1037  struct tm *ptm;
1038  char time_string[256];
1039  gchar *tmps;
1040 
1041  guint64 mtime;
1042 
1043  if (remminafile->statefile)
1044  //REMMINA_DEBUG ("remminafile->statefile: %s", remminafile->statefile);
1045  file = g_file_new_for_path(remminafile->statefile);
1046  else
1047  file = g_file_new_for_path(remminafile->filename);
1048 
1049  info = g_file_query_info(file,
1050  G_FILE_ATTRIBUTE_TIME_MODIFIED,
1051  G_FILE_QUERY_INFO_NONE,
1052  NULL,
1053  NULL);
1054 
1055  g_object_unref(file);
1056 
1057  if (info == NULL) {
1058  //REMMINA_DEBUG("could not get time info");
1059 
1060  // The BDAY "Fri, 16 Oct 2009 07:04:46 GMT"
1061  mtime = 1255676686;
1062  const gchar *last_success = remmina_file_get_string(remminafile, "last_success");
1063  if (last_success) {
1064  //REMMINA_DEBUG ("Last success is %s", last_success);
1065  GDateTime *dt;
1066  tmps = g_strconcat(last_success, "T00:00:00Z", NULL);
1067  dt = g_date_time_new_from_iso8601(tmps, NULL);
1068  g_free(tmps);
1069  if (dt) {
1070  //REMMINA_DEBUG("Converting last_success");
1071  tmps = g_date_time_format(dt, "%s");
1072  mtime = g_ascii_strtoull(tmps, NULL, 10);
1073  g_free(tmps);
1074  g_date_time_unref(dt);
1075  } else {
1076  //REMMINA_DEBUG("dt was null");
1077  mtime = 191543400;
1078  }
1079  }
1080  } else {
1081  mtime = g_file_info_get_attribute_uint64(info, G_FILE_ATTRIBUTE_TIME_MODIFIED);
1082  g_object_unref(info);
1083  }
1084 
1085  tv.tv_sec = mtime;
1086 
1087  ptm = localtime(&tv.tv_sec);
1088  strftime(time_string, sizeof(time_string), "%F - %T", ptm);
1089 
1090  gchar *modtime_string = g_locale_to_utf8(time_string, -1, NULL, NULL, NULL);
1091 
1092  return modtime_string;
1093 }
1094 
1102 void
1104 {
1105  TRACE_CALL(__func__);
1106  int fd;
1107  struct stat st;
1108  int r;
1109 
1110  if ((r = stat(remminafile->statefile, &st)) < 0) {
1111  if (errno != ENOENT)
1112  REMMINA_DEBUG("stat %s:", remminafile->statefile);
1113  } else if (!r) {
1114 #ifdef __APPLE__
1115  times[0] = st.st_atimespec;
1116  times[1] = st.st_mtimespec;
1117 #else
1118  times[0] = st.st_atim;
1119  times[1] = st.st_mtim;
1120 #endif
1121  if (utimensat(AT_FDCWD, remminafile->statefile, times, 0) < 0)
1122  REMMINA_DEBUG("utimensat %s:", remminafile->statefile);
1123  return;
1124  }
1125 
1126  if ((fd = open(remminafile->statefile, O_CREAT | O_EXCL, 0644)) < 0)
1127  REMMINA_DEBUG("open %s:", remminafile->statefile);
1128  close(fd);
1129 
1130  remmina_file_touch(remminafile);
1131 }
RemminaFile * remmina_file_load(const gchar *filename)
Definition: remmina_file.c:350
+Go to the documentation of this file.
1 /*
2  * Remmina - The GTK+ Remote Desktop Client
3  * Copyright (C) 2009-2011 Vic Lee
4  * Copyright (C) 2014-2015 Antenore Gatta, Fabio Castelli, Giovanni Panozzo
5  * Copyright (C) 2016-2023 Antenore Gatta, Giovanni Panozzo
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  *
22  * In addition, as a special exception, the copyright holders give
23  * permission to link the code of portions of this program with the
24  * OpenSSL library under certain conditions as described in each
25  * individual source file, and distribute linked combinations
26  * including the two.
27  * You must obey the GNU General Public License in all respects
28  * for all of the code used other than OpenSSL. * If you modify
29  * file(s) with this exception, you may extend this exception to your
30  * version of the file(s), but you are not obligated to do so. * If you
31  * do not wish to do so, delete this exception statement from your
32  * version. * If you delete this exception statement from all source
33  * files in the program, then also delete it here.
34  *
35  */
36 
37 #include "config.h"
38 
39 
40 #include <errno.h>
41 #include <fcntl.h>
42 #include <sys/stat.h>
43 #include <locale.h>
44 #include <langinfo.h>
45 #include <stdlib.h>
46 #include <string.h>
47 #include <time.h>
48 #include <unistd.h>
49 #include <utime.h>
50 
51 #include <gtk/gtk.h>
52 #include <glib/gi18n.h>
53 #include <glib/gstdio.h>
54 
56 #include "remmina_crypt.h"
57 #include "remmina_file_manager.h"
58 #include "remmina_log.h"
59 #include "remmina_main.h"
61 #include "remmina_plugin_manager.h"
62 #include "remmina_pref.h"
63 #include "remmina_public.h"
64 #include "remmina_sodium.h"
65 #include "remmina_utils.h"
66 
67 #define MIN_WINDOW_WIDTH 10
68 #define MIN_WINDOW_HEIGHT 10
69 
70 #define KEYFILE_GROUP_REMMINA "remmina"
71 #define KEYFILE_GROUP_STATE "Remmina Connection States"
72 
73 static struct timespec times[2];
74 
75 static RemminaFile *
77 {
78  TRACE_CALL(__func__);
79  RemminaFile *remminafile;
80 
81  remminafile = g_new0(RemminaFile, 1);
82  remminafile->settings = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
83  remminafile->states = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
84  /* spsettings contains settings that are loaded from the secure_plugin.
85  * it’s used by remmina_file_store_secret_plugin_password() to know
86  * where to change */
87  remminafile->spsettings = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
88  remminafile->prevent_saving = FALSE;
89  return remminafile;
90 }
91 
94 {
95  TRACE_CALL(__func__);
96  RemminaFile *remminafile;
97 
98  /* Try to load from the preference file for default settings first */
99  remminafile = remmina_file_load(remmina_pref_file);
100 
101  if (remminafile) {
102  g_free(remminafile->filename);
103  remminafile->filename = NULL;
104  } else {
105  remminafile = remmina_file_new_empty();
106  }
107 
108  return remminafile;
109 }
110 
115 {
116  TRACE_CALL(__func__);
117 
127  gchar *invalid_chars = "\\%|/$?<>:*. \"";
128  GString *filenamestr;
129  const gchar *s;
130 
131 
132  /* functions we can use
133  * g_strstrip( string )
134  * Removes leading and trailing whitespace from a string
135  * g_strdelimit (str, invalid_chars, '-'))
136  * Convert each invalid_chars in a hyphen
137  * g_ascii_strdown(string)
138  * all lowercase
139  * To be safe we should remove control characters as well (but I'm lazy)
140  * https://rosettacode.org/wiki/Strip_control_codes_and_extended_characters_from_a_string#C
141  * g_utf8_strncpy (gchar *dest, const gchar *src, gsize n);
142  * copies a given number of characters instead of a given number of bytes. The src string must be valid UTF-8 encoded text.
143  * g_utf8_validate (const gchar *str, gssize max_len, const gchar **end);
144  * Validates UTF-8 encoded text.
145  */
146 
147  //g_free(remminafile->filename), remminafile->filename = NULL;
148 
149  filenamestr = g_string_new(g_strdup_printf("%s",
151  if ((s = remmina_file_get_string(remminafile, "name")) == NULL) s = "name";
152  if (g_strstr_len(filenamestr->str, -1, "%N") != NULL)
153  remmina_utils_string_replace_all(filenamestr, "%N", s);
154 
155  if ((s = remmina_file_get_string(remminafile, "group")) == NULL) s = "group";
156  if (g_strstr_len(filenamestr->str, -1, "%G") != NULL)
157  remmina_utils_string_replace_all(filenamestr, "%G", s);
158 
159  if ((s = remmina_file_get_string(remminafile, "protocol")) == NULL) s = "proto";
160  if (g_strstr_len(filenamestr->str, -1, "%P") != NULL)
161  remmina_utils_string_replace_all(filenamestr, "%P", s);
162 
163  if ((s = remmina_file_get_string(remminafile, "server")) == NULL) s = "host";
164  if (g_strstr_len(filenamestr->str, -1, "%h") != NULL)
165  remmina_utils_string_replace_all(filenamestr, "%h", s);
166 
167  s = NULL;
168 
169  g_autofree gchar *filename = g_strdelimit(g_ascii_strdown(g_strstrip(g_string_free(filenamestr, FALSE)), -1),
170  invalid_chars, '-');
171 
172  GDir *dir = g_dir_open(remmina_file_get_datadir(), 0, NULL);
173 
174  if (dir != NULL)
175  remminafile->filename = g_strdup_printf("%s/%s.remmina", remmina_file_get_datadir(), filename);
176  else
177  remminafile->filename = NULL;
178  g_dir_close(dir);
179 
180 }
181 
182 void remmina_file_set_filename(RemminaFile *remminafile, const gchar *filename)
183 {
184  TRACE_CALL(__func__);
185  g_free(remminafile->filename);
186  remminafile->filename = g_strdup(filename);
187 }
188 
190 {
191  TRACE_CALL(__func__);
192 
193  if (!remminafile)
194  return;
195  else
196  g_free(remminafile->statefile);
197 
198  gchar *basename = g_path_get_basename(remminafile->filename);
199  gchar *cachedir = g_build_path("/", g_get_user_cache_dir(), "remmina", NULL);
200  GString *fname = g_string_new(basename);
201 
202  remminafile->statefile = g_strdup_printf("%s/%s.state", cachedir, fname->str);
203 
204  g_free(cachedir);
205  g_string_free(fname, TRUE);
206  g_free(basename);
207 }
208 
209 const gchar *
211 {
212  TRACE_CALL(__func__);
213  return remminafile->filename;
214 }
215 
216 RemminaFile *
217 remmina_file_copy(const gchar *filename)
218 {
219  TRACE_CALL(__func__);
220  RemminaFile *remminafile;
221  gchar *buf;
222 
223  remminafile = remmina_file_load(filename);
224  buf = g_strdup_printf( "COPY %s",
225  remmina_file_get_string(remminafile, "name"));
226  remmina_file_set_string(remminafile, "name", buf);
227  g_free(buf);
228 
229  if (remminafile)
230  remmina_file_generate_filename(remminafile);
231 
232  return remminafile;
233 }
234 
235 const RemminaProtocolSetting *find_protocol_setting(const gchar *name, RemminaProtocolPlugin *protocol_plugin)
236 {
237  TRACE_CALL(__func__);
238  const RemminaProtocolSetting *setting_iter;
239 
240  if (protocol_plugin == NULL)
241  return NULL;
242 
243  setting_iter = protocol_plugin->basic_settings;
244  if (setting_iter) {
245  while (setting_iter->type != REMMINA_PROTOCOL_SETTING_TYPE_END) {
246  if (strcmp(name, remmina_plugin_manager_get_canonical_setting_name(setting_iter)) == 0)
247  return setting_iter;
248  setting_iter++;
249  }
250  }
251 
252  setting_iter = protocol_plugin->advanced_settings;
253  if (setting_iter) {
254  while (setting_iter->type != REMMINA_PROTOCOL_SETTING_TYPE_END) {
255  if (strcmp(name, remmina_plugin_manager_get_canonical_setting_name(setting_iter)) == 0)
256  return setting_iter;
257  setting_iter++;
258  }
259  }
260 
261  return NULL;
262 }
263 
264 
265 static void upgrade_sshkeys_202001_mig_common_setting(RemminaFile *remminafile, gboolean protocol_is_ssh, gboolean ssh_enabled, gchar *suffix)
266 {
267  gchar *src_key;
268  gchar *dst_key;
269  const gchar *val;
270 
271  src_key = g_strdup_printf("ssh_%s", suffix);
272  dst_key = g_strdup_printf("ssh_tunnel_%s", suffix);
273 
274  val = remmina_file_get_string(remminafile, src_key);
275  if (!val) {
276  g_free(dst_key);
277  g_free(src_key);
278  return;
279  }
280 
281  if (ssh_enabled && val && val[0] != 0)
282  remmina_file_set_string(remminafile, dst_key, val);
283 
284  if (!protocol_is_ssh)
285  remmina_file_set_string(remminafile, src_key, NULL);
286 
287  g_free(dst_key);
288  g_free(src_key);
289 }
290 
291 static void upgrade_sshkeys_202001(RemminaFile *remminafile)
292 {
293  TRACE_CALL(__func__);
294 
295  gboolean protocol_is_ssh;
296  gboolean ssh_enabled;
297  const gchar *val;
298 
299  if (remmina_file_get_string(remminafile, "ssh_enabled")) {
300  /* Upgrade ssh params from remmina pre 1.4 */
301 
302  ssh_enabled = remmina_file_get_int(remminafile, "ssh_enabled", 0);
303  val = remmina_file_get_string(remminafile, "protocol");
304  protocol_is_ssh = (strcmp(val, "SSH") == 0);
305 
306  upgrade_sshkeys_202001_mig_common_setting(remminafile, protocol_is_ssh, ssh_enabled, "stricthostkeycheck");
307  upgrade_sshkeys_202001_mig_common_setting(remminafile, protocol_is_ssh, ssh_enabled, "kex_algorithms");
308  upgrade_sshkeys_202001_mig_common_setting(remminafile, protocol_is_ssh, ssh_enabled, "hostkeytypes");
309  upgrade_sshkeys_202001_mig_common_setting(remminafile, protocol_is_ssh, ssh_enabled, "ciphers");
310  upgrade_sshkeys_202001_mig_common_setting(remminafile, protocol_is_ssh, ssh_enabled, "proxycommand");
311  upgrade_sshkeys_202001_mig_common_setting(remminafile, protocol_is_ssh, ssh_enabled, "passphrase");
312  upgrade_sshkeys_202001_mig_common_setting(remminafile, protocol_is_ssh, ssh_enabled, "auth");
313  upgrade_sshkeys_202001_mig_common_setting(remminafile, protocol_is_ssh, ssh_enabled, "privatekey");
314 
315  val = remmina_file_get_string(remminafile, "ssh_loopback");
316  if (val) {
317  remmina_file_set_string(remminafile, "ssh_tunnel_loopback", val);
318  remmina_file_set_string(remminafile, "ssh_loopback", NULL);
319  }
320 
321  val = remmina_file_get_string(remminafile, "ssh_username");
322  if (val) {
323  remmina_file_set_string(remminafile, "ssh_tunnel_username", val);
324  if (protocol_is_ssh)
325  remmina_file_set_string(remminafile, "username", val);
326  remmina_file_set_string(remminafile, "ssh_username", NULL);
327  }
328 
329  val = remmina_file_get_string(remminafile, "ssh_password");
330  if (val) {
331  remmina_file_set_string(remminafile, "ssh_tunnel_password", val);
332  if (protocol_is_ssh)
333  remmina_file_set_string(remminafile, "password", val);
334  remmina_file_set_string(remminafile, "ssh_password", NULL);
335  }
336 
337  val = remmina_file_get_string(remminafile, "ssh_server");
338  if (val) {
339  remmina_file_set_string(remminafile, "ssh_tunnel_server", val);
340  remmina_file_set_string(remminafile, "ssh_server", NULL);
341  }
342 
343  /* Real key removal will be done by remmina_file_save() */
344 
345  remmina_file_set_int(remminafile, "ssh_tunnel_enabled", ssh_enabled);
346  }
347 }
348 
349 RemminaFile *
350 remmina_file_load(const gchar *filename)
351 {
352  TRACE_CALL(__func__);
353  GKeyFile *gkeyfile;
354  RemminaFile *remminafile;
355  gchar *key;
356  gchar *s;
357  RemminaProtocolPlugin *protocol_plugin;
358  RemminaSecretPlugin *secret_plugin;
359  gboolean secret_service_available;
360  int w, h;
361 
362  gkeyfile = g_key_file_new();
363 
364  if (g_file_test(filename, G_FILE_TEST_IS_REGULAR | G_FILE_TEST_EXISTS)) {
365  if (!g_key_file_load_from_file(gkeyfile, filename, G_KEY_FILE_NONE, NULL)) {
366  g_key_file_free(gkeyfile);
367  REMMINA_DEBUG("Unable to load remmina profile file %s: g_key_file_load_from_file() returned NULL.\n", filename);
368  return NULL;
369  }
370  }
371 
372  if (!g_key_file_has_key(gkeyfile, KEYFILE_GROUP_REMMINA, "name", NULL)) {
373 
374  REMMINA_DEBUG("Unable to load remmina profile file %s: cannot find key name= in section remmina.\n", filename);
375  remminafile = NULL;
376  remmina_file_set_statefile(remminafile);
377 
378  g_key_file_free(gkeyfile);
379 
380  return remminafile;
381  }
382  remminafile = remmina_file_new_empty();
383 
384  protocol_plugin = NULL;
385 
386  /* Identify the protocol plugin and get pointers to its RemminaProtocolSetting structs */
387  gchar *proto = g_key_file_get_string(gkeyfile, KEYFILE_GROUP_REMMINA, "protocol", NULL);
388  if (proto) {
390  g_free(proto);
391  }
392 
394  secret_service_available = secret_plugin && secret_plugin->is_service_available(secret_plugin);
395 
396  remminafile->filename = g_strdup(filename);
397  gsize nkeys = 0;
398  gint keyindex;
399  GError *err = NULL;
400  gchar **keys = g_key_file_get_keys(gkeyfile, KEYFILE_GROUP_REMMINA, &nkeys, &err);
401  if (keys == NULL) {
402  g_clear_error(&err);
403  }
404  for (keyindex = 0; keyindex < nkeys; ++keyindex) {
405  key = keys[keyindex];
406  /* It may contain an encrypted password
407  * - password = . // secret_service
408  * - password = $argon2id$v=19$m=262144,t=3,p=… // libsodium
409  */
410  if (protocol_plugin && remmina_plugin_manager_is_encrypted_setting(protocol_plugin, key)) {
411  s = g_key_file_get_string(gkeyfile, KEYFILE_GROUP_REMMINA, key, NULL);
412 #if 0
413  switch (remmina_pref.enc_mode) {
417 #if SODIUM_VERSION_INT >= 90200
418 #endif
419  break;
420  case RM_ENC_MODE_GCRYPT:
421  break;
422  case RM_ENC_MODE_SECRET:
423  default:
424  break;
425  }
426 #endif
427  if ((g_strcmp0(s, ".") == 0) && (secret_service_available)) {
428  gchar *sec = secret_plugin->get_password(secret_plugin, remminafile, key);
429  remmina_file_set_string(remminafile, key, sec);
430  /* Annotate in spsettings that this value comes from secret_plugin */
431  g_hash_table_insert(remminafile->spsettings, g_strdup(key), NULL);
432  g_free(sec);
433  } else {
434  gchar *decrypted;
435  decrypted = remmina_crypt_decrypt(s);
436  remmina_file_set_string(remminafile, key, decrypted);
437  g_free(decrypted);
438  }
439  g_free(s), s = NULL;
440  } else {
441  /* If we find "resolution", then we split it in two */
442  if (strcmp(key, "resolution") == 0) {
443  gchar *resolution_str = g_key_file_get_string(gkeyfile, KEYFILE_GROUP_REMMINA, key, NULL);
444  if (remmina_public_split_resolution_string(resolution_str, &w, &h)) {
445  gchar *buf;
446  buf = g_strdup_printf("%i", w); remmina_file_set_string(remminafile, "resolution_width", buf); g_free(buf);
447  buf = g_strdup_printf("%i", h); remmina_file_set_string(remminafile, "resolution_height", buf); g_free(buf);
448  } else {
449  remmina_file_set_string(remminafile, "resolution_width", NULL);
450  remmina_file_set_string(remminafile, "resolution_height", NULL);
451  }
452  g_free(resolution_str);
453  } else {
454  gchar *value;
455  value = g_key_file_get_string(gkeyfile, KEYFILE_GROUP_REMMINA, key, NULL);
456  remmina_file_set_string(remminafile, key, value);
457  g_free(value);
458  }
459  }
460  }
461 
462  upgrade_sshkeys_202001(remminafile);
463  g_strfreev(keys);
464  remmina_file_set_statefile(remminafile);
465  g_key_file_free(gkeyfile);
466  return remminafile;
467 }
468 
469 void remmina_file_set_string(RemminaFile *remminafile, const gchar *setting, const gchar *value)
470 {
471  TRACE_CALL(__func__);
472 
473  /* Note: setting and value are copied on the heap, so it is responsibility of the caller
474  * to deallocate them when returning from remmina_file_set_string() if needed */
475 
477  /* Allow the execution of this function from a non main thread
478  * (plugins needs it to have user credentials)*/
480  d = (RemminaMTExecData *)g_malloc(sizeof(RemminaMTExecData));
481  d->func = FUNC_FILE_SET_STRING;
482  d->p.file_set_string.remminafile = remminafile;
483  d->p.file_set_string.setting = setting;
484  d->p.file_set_string.value = value;
486  g_free(d);
487  return;
488  }
489 
490  if (value) {
491  /* We refuse to accept to set the "resolution" field */
492  if (strcmp(setting, "resolution") == 0) {
493  // TRANSLATORS: This is a message that pops up when an external Remmina plugin tries to set the window resolution using a legacy parameter.
494  const gchar *message = _("Using the «resolution» parameter in the Remmina preferences file is deprecated.\n");
495  REMMINA_CRITICAL(message);
497  return;
498  }
499  g_hash_table_insert(remminafile->settings, g_strdup(setting), g_strdup(value));
500  } else {
501  g_hash_table_insert(remminafile->settings, g_strdup(setting), g_strdup(""));
502  }
503 }
504 
505 void remmina_file_set_state(RemminaFile *remminafile, const gchar *setting, const gchar *value)
506 {
507  TRACE_CALL(__func__);
508 
509  if (value && value[0] != 0)
510  g_hash_table_insert(remminafile->states, g_strdup(setting), g_strdup(value));
511  else
512  g_hash_table_insert(remminafile->states, g_strdup(setting), g_strdup(""));
513 }
514 
515 const gchar *
516 remmina_file_get_string(RemminaFile *remminafile, const gchar *setting)
517 {
518  TRACE_CALL(__func__);
519  gchar *value;
520 
521  /* Returned value is a pointer to the string stored on the hash table,
522  * please do not free it or the hash table will contain invalid pointer */
524  /* Allow the execution of this function from a non main thread
525  * (plugins needs it to have user credentials)*/
527  const gchar *retval;
528  d = (RemminaMTExecData *)g_malloc(sizeof(RemminaMTExecData));
529  d->func = FUNC_FILE_GET_STRING;
530  d->p.file_get_string.remminafile = remminafile;
531  d->p.file_get_string.setting = setting;
533  retval = d->p.file_get_string.retval;
534  g_free(d);
535  return retval;
536  }
537 
538  if (strcmp(setting, "resolution") == 0) {
539  // TRANSLATORS: This is a message that pop-up when an external Remmina plugin tries to set the windows resolution using a legacy parameter.
540  const gchar *message = _("Using the «resolution» parameter in the Remmina preferences file is deprecated.\n");
541  REMMINA_CRITICAL(message);
543  return NULL;
544  }
545 
546  value = (gchar *)g_hash_table_lookup(remminafile->settings, setting);
547  return value && value[0] ? value : NULL;
548 }
549 
550 gchar *
551 remmina_file_get_secret(RemminaFile *remminafile, const gchar *setting)
552 {
553  TRACE_CALL(__func__);
554 
555  /* This function is in the RemminaPluginService table, we cannot remove it
556  * without breaking plugin API */
557  g_warning("remmina_file_get_secret(remminafile,“%s”) is deprecated and must not be called. Use remmina_file_get_string() and do not deallocate returned memory.\n", setting);
558  return g_strdup(remmina_file_get_string(remminafile, setting));
559 }
560 
561 gchar *remmina_file_format_properties(RemminaFile *remminafile, const gchar *setting)
562 {
563  gchar *res = NULL;
564  GString *fmt_str;
565  GDateTime *now;
566  gchar *date_str = NULL;
567 
568  fmt_str = g_string_new(setting);
569  remmina_utils_string_replace_all(fmt_str, "%h", remmina_file_get_string(remminafile, "server"));
570  remmina_utils_string_replace_all(fmt_str, "%t", remmina_file_get_string(remminafile, "ssh_tunnel_server"));
571  remmina_utils_string_replace_all(fmt_str, "%u", remmina_file_get_string(remminafile, "username"));
572  remmina_utils_string_replace_all(fmt_str, "%U", remmina_file_get_string(remminafile, "ssh_tunnel_username"));
573  remmina_utils_string_replace_all(fmt_str, "%p", remmina_file_get_string(remminafile, "name"));
574  remmina_utils_string_replace_all(fmt_str, "%g", remmina_file_get_string(remminafile, "group"));
575 
576  now = g_date_time_new_now_local();
577  date_str = g_date_time_format(now, "%FT%TZ");
578  remmina_utils_string_replace_all(fmt_str, "%d", date_str);
579  g_free(date_str);
580 
581  res = g_string_free(fmt_str, FALSE);
582  return res;
583 }
584 
585 void remmina_file_set_int(RemminaFile *remminafile, const gchar *setting, gint value)
586 {
587  TRACE_CALL(__func__);
588  if (remminafile)
589  g_hash_table_insert(remminafile->settings,
590  g_strdup(setting),
591  g_strdup_printf("%i", value));
592 }
593 
594 void remmina_file_set_state_int(RemminaFile *remminafile, const gchar *setting, gint value)
595 {
596  TRACE_CALL(__func__);
597  if (remminafile)
598  g_hash_table_insert(remminafile->states,
599  g_strdup(setting),
600  g_strdup_printf("%i", value));
601 }
602 
603 gint remmina_file_get_int(RemminaFile *remminafile, const gchar *setting, gint default_value)
604 {
605  TRACE_CALL(__func__);
606  gchar *value;
607  gint r;
608 
609  value = g_hash_table_lookup(remminafile->settings, setting);
610  r = value == NULL ? default_value : (value[0] == 't' ? TRUE : atoi(value));
611  // TOO verbose: REMMINA_DEBUG ("Integer value is: %d", r);
612  return r;
613 }
614 
615 gint remmina_file_get_state_int(RemminaFile *remminafile, const gchar *setting, gint default_value)
616 {
617  TRACE_CALL(__func__);
618  gchar *value;
619  gint r;
620 
621  value = g_hash_table_lookup(remminafile->states, setting);
622  r = value == NULL ? default_value : (value[0] == 't' ? TRUE : atoi(value));
623  // TOO verbose: REMMINA_DEBUG ("Integer value is: %d", r);
624  return r;
625 }
626 
627 // sscanf uses the set language to convert the float.
628 // therefore '.' and ',' cannot be used interchangeably.
629 gdouble remmina_file_get_double(RemminaFile * remminafile,
630  const gchar * setting,
631  gdouble default_value)
632 {
633  TRACE_CALL(__func__);
634  gchar *value;
635 
636  value = g_hash_table_lookup(remminafile->settings, setting);
637  if (!value)
638  return default_value;
639 
640  // str to double.
641  // https://stackoverflow.com/questions/10075294/converting-string-to-a-double-variable-in-c
642  gdouble d;
643  gint ret = sscanf(value, "%lf", &d);
644 
645  if (ret != 1)
646  // failed.
647  d = default_value;
648 
649  // TOO VERBOSE: REMMINA_DEBUG("Double value is: %lf", d);
650  return d;
651 }
652 
653 // sscanf uses the set language to convert the float.
654 // therefore '.' and ',' cannot be used interchangeably.
656  const gchar * setting,
657  gdouble default_value)
658 {
659  TRACE_CALL(__func__);
660  gchar *value;
661 
662  value = g_hash_table_lookup(remminafile->states, setting);
663  if (!value)
664  return default_value;
665 
666  // str to double.
667  // https://stackoverflow.com/questions/10075294/converting-string-to-a-double-variable-in-c
668  gdouble d;
669  gint ret = sscanf(value, "%lf", &d);
670 
671  if (ret != 1)
672  // failed.
673  d = default_value;
674 
675  // TOO VERBOSE: REMMINA_DEBUG("Double value is: %lf", d);
676  return d;
677 }
678 
679 static GKeyFile *
681 {
682  TRACE_CALL(__func__);
683  GKeyFile *gkeyfile;
684 
685  if (remminafile->filename == NULL)
686  return NULL;
687  gkeyfile = g_key_file_new();
688  if (!g_key_file_load_from_file(gkeyfile, remminafile->filename, G_KEY_FILE_NONE, NULL)) {
689  /* it will fail if it’s a new file, but shouldn’t matter. */
690  }
691  return gkeyfile;
692 }
693 
694 static GKeyFile *
696 {
697  TRACE_CALL(__func__);
698  GKeyFile *gkeyfile;
699 
700  if (remminafile->statefile == NULL)
701  return NULL;
702  gkeyfile = g_key_file_new();
703  if (!g_key_file_load_from_file(gkeyfile, remminafile->statefile, G_KEY_FILE_NONE, NULL)) {
704  /* it will fail if it’s a new file, but shouldn’t matter. */
705  }
706  return gkeyfile;
707 }
708 
709 void remmina_file_free(RemminaFile *remminafile)
710 {
711  TRACE_CALL(__func__);
712  if (remminafile == NULL)
713  return;
714 
715  if (remminafile->filename)
716  g_free(remminafile->filename);
717  if (remminafile->statefile)
718  g_free(remminafile->statefile);
719  if (remminafile->settings)
720  g_hash_table_destroy(remminafile->settings);
721  if (remminafile->spsettings)
722  g_hash_table_destroy(remminafile->spsettings);
723  if (remminafile->states)
724  g_hash_table_destroy(remminafile->states);
725 
726  g_free(remminafile);
727 }
728 
729 
730 void remmina_file_save(RemminaFile *remminafile)
731 {
732  TRACE_CALL(__func__);
733  RemminaSecretPlugin *secret_plugin;
734  gboolean secret_service_available;
735  RemminaProtocolPlugin *protocol_plugin;
736  GHashTableIter iter;
737  const gchar *key, *value;
738  gchar *s, *proto, *content;
739  gint nopasswdsave;
740  GKeyFile *gkeyfile;
741  GKeyFile *gkeystate;
742  gsize length = 0;
743  GError *err = NULL;
744 
745  if (remminafile->prevent_saving)
746  return;
747 
748  if ((gkeyfile = remmina_file_get_keyfile(remminafile)) == NULL)
749  return;
750 
751  if ((gkeystate = remmina_file_get_keystate(remminafile)) == NULL)
752  return;
753 
754  REMMINA_DEBUG("Saving profile");
755  /* get disablepasswordstoring */
756  nopasswdsave = remmina_file_get_int(remminafile, "disablepasswordstoring", 0);
757  /* Identify the protocol plugin and get pointers to its RemminaProtocolSetting structs */
758  proto = (gchar *)g_hash_table_lookup(remminafile->settings, "protocol");
759  if (proto) {
761  } else {
762  REMMINA_CRITICAL("Saving settings for unknown protocol:", proto);
763  protocol_plugin = NULL;
764  }
765 
767  secret_service_available = secret_plugin && secret_plugin->is_service_available(secret_plugin);
768 
769  g_hash_table_iter_init(&iter, remminafile->settings);
770  while (g_hash_table_iter_next(&iter, (gpointer *)&key, (gpointer *)&value)) {
771  if (remmina_plugin_manager_is_encrypted_setting(protocol_plugin, key)) {
772  if (remminafile->filename && g_strcmp0(remminafile->filename, remmina_pref_file)) {
773  if (secret_service_available && nopasswdsave == 0) {
774  REMMINA_DEBUG("We have a secret and disablepasswordstoring=0");
775  if (value && value[0]) {
776  if (g_strcmp0(value, ".") != 0)
777  secret_plugin->store_password(secret_plugin, remminafile, key, value);
778  g_key_file_set_string(gkeyfile, KEYFILE_GROUP_REMMINA, key, ".");
779  } else {
780  g_key_file_set_string(gkeyfile, KEYFILE_GROUP_REMMINA, key, "");
781  secret_plugin->delete_password(secret_plugin, remminafile, key);
782  }
783  } else {
784  REMMINA_DEBUG("We have a password and disablepasswordstoring=0");
785  if (value && value[0] && nopasswdsave == 0) {
786  s = remmina_crypt_encrypt(value);
787  g_key_file_set_string(gkeyfile, KEYFILE_GROUP_REMMINA, key, s);
788  g_free(s);
789  } else {
790  g_key_file_set_string(gkeyfile, KEYFILE_GROUP_REMMINA, key, "");
791  }
792  }
793  if (secret_service_available && nopasswdsave == 1) {
794  if (value && value[0]) {
795  if (g_strcmp0(value, ".") != 0) {
796  REMMINA_DEBUG("Deleting the secret in the keyring as disablepasswordstoring=1");
797  secret_plugin->delete_password(secret_plugin, remminafile, key);
798  g_key_file_set_string(gkeyfile, KEYFILE_GROUP_REMMINA, key, ".");
799  }
800  }
801  }
802  }
803  } else {
804  g_key_file_set_string(gkeyfile, KEYFILE_GROUP_REMMINA, key, value);
805  }
806  }
807 
808  /* Avoid storing redundant and deprecated "resolution" field */
809  g_key_file_remove_key(gkeyfile, KEYFILE_GROUP_REMMINA, "resolution", NULL);
810 
811  /* Delete old pre-1.4 ssh keys */
812  g_key_file_remove_key(gkeyfile, KEYFILE_GROUP_REMMINA, "ssh_enabled", NULL);
813  g_key_file_remove_key(gkeyfile, KEYFILE_GROUP_REMMINA, "save_ssh_server", NULL);
814  g_key_file_remove_key(gkeyfile, KEYFILE_GROUP_REMMINA, "save_ssh_username", NULL);
815 
816  /* Store gkeyfile to disk (password are already sent to keyring) */
817  content = g_key_file_to_data(gkeyfile, &length, NULL);
818 
819  if (g_file_set_contents(remminafile->filename, content, length, &err))
820  REMMINA_DEBUG("Profile saved");
821  else
822  REMMINA_WARNING("Remmina connection profile cannot be saved, with error %d (%s)", err->code, err->message);
823  if (err != NULL)
824  g_error_free(err);
825 
826  g_free(content), content = NULL;
827  /* Saving states */
828  g_hash_table_iter_init(&iter, remminafile->states);
829  while (g_hash_table_iter_next(&iter, (gpointer *)&key, (gpointer *)&value))
830  g_key_file_set_string(gkeyfile, KEYFILE_GROUP_STATE, key, value);
831  content = g_key_file_to_data(gkeystate, &length, NULL);
832  if (g_file_set_contents(remminafile->statefile, content, length, &err))
833  REMMINA_DEBUG("Connection profile states saved");
834  else
835  REMMINA_WARNING("Remmina connection profile cannot be saved, with error %d (%s)", err->code, err->message);
836  if (err != NULL)
837  g_error_free(err);
838  g_free(content), content = NULL;
839  g_key_file_free(gkeyfile);
840  g_key_file_free(gkeystate);
841 
844 }
845 
846 void remmina_file_store_secret_plugin_password(RemminaFile *remminafile, const gchar *key, const gchar *value)
847 {
848  TRACE_CALL(__func__);
849 
850  /* Only change the password in the keyring. This function
851  * is a shortcut which avoids updating of date/time of .pref file
852  * when possible, and is used by the mpchanger */
853  RemminaSecretPlugin *plugin;
854 
855  if (g_hash_table_lookup_extended(remminafile->spsettings, g_strdup(key), NULL, NULL)) {
857  plugin->store_password(plugin, remminafile, key, value);
858  } else {
859  remmina_file_set_string(remminafile, key, value);
860  remmina_file_save(remminafile);
861  }
862 }
863 
864 RemminaFile *
866 {
867  TRACE_CALL(__func__);
868  RemminaFile *dupfile;
869  GHashTableIter iter;
870  const gchar *key, *value;
871 
872  dupfile = remmina_file_new_empty();
873  dupfile->filename = g_strdup(remminafile->filename);
874 
875  g_hash_table_iter_init(&iter, remminafile->settings);
876  while (g_hash_table_iter_next(&iter, (gpointer *)&key, (gpointer *)&value))
877  remmina_file_set_string(dupfile, key, value);
878 
880  remmina_file_touch(dupfile);
881  return dupfile;
882 }
883 
884 const gchar *
886 {
887  TRACE_CALL(__func__);
888  RemminaProtocolPlugin *plugin;
889 
891  remmina_file_get_string(remminafile, "protocol"));
892  if (!plugin)
893  return g_strconcat(REMMINA_APP_ID, "-symbolic", NULL);
894 
895  return remmina_file_get_int(remminafile, "ssh_tunnel_enabled", FALSE) ? plugin->icon_name_ssh : plugin->icon_name;
896 }
897 
898 RemminaFile *
899 remmina_file_dup_temp_protocol(RemminaFile *remminafile, const gchar *new_protocol)
900 {
901  TRACE_CALL(__func__);
902  RemminaFile *tmp;
903 
904  tmp = remmina_file_dup(remminafile);
905  g_free(tmp->filename);
906  tmp->filename = NULL;
907  remmina_file_set_string(tmp, "protocol", new_protocol);
908  return tmp;
909 }
910 
911 void remmina_file_delete(const gchar *filename)
912 {
913  TRACE_CALL(__func__);
914  RemminaFile *remminafile;
915 
916  remminafile = remmina_file_load(filename);
917  if (remminafile) {
918  remmina_file_unsave_passwords(remminafile);
919  remmina_file_free(remminafile);
920  }
921  g_unlink(filename);
922 }
923 
924 const gchar *
925 remmina_file_get_state(RemminaFile *remminafile, const gchar *setting)
926 {
927  TRACE_CALL(__func__);
928  g_autoptr(GError) error = NULL;
929  g_autoptr(GKeyFile) key_file = g_key_file_new();
930 
931  if (!g_key_file_load_from_file(key_file, remminafile->statefile, G_KEY_FILE_NONE, &error)) {
932  if (!g_error_matches(error, G_FILE_ERROR, G_FILE_ERROR_NOENT))
933  REMMINA_CRITICAL("Could not load the state file. %s", error->message);
934  return NULL;
935  }
936 
937  g_autofree gchar *val = g_key_file_get_string(key_file, KEYFILE_GROUP_STATE, setting, &error);
938 
939  if (val == NULL &&
940  !g_error_matches(error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_KEY_NOT_FOUND)) {
941  REMMINA_CRITICAL("Could not find \"%s\" in the \"%s\" state file. %s",
942  setting, remminafile->statefile, error->message);
943  return NULL;
944  }
945  return val && val[0] ? val : NULL;
946 }
947 
949 {
950  TRACE_CALL(__func__);
951 
952  g_autoptr(GKeyFile) key_statefile = g_key_file_new();
953  g_autoptr(GKeyFile) key_remminafile = g_key_file_new();
954  GError *error = NULL;
955 
956  const gchar *date = NULL;
957  GDateTime *d = g_date_time_new_now_utc();
958 
959  date = g_strdup_printf("%d%02d%02d",
960  g_date_time_get_year(d),
961  g_date_time_get_month(d),
962  g_date_time_get_day_of_month(d));
963 
964  g_key_file_set_string(key_statefile, KEYFILE_GROUP_STATE, "last_success", date);
965 
966  REMMINA_DEBUG("State file %s.", remminafile->statefile);
967  if (!g_key_file_save_to_file(key_statefile, remminafile->statefile, &error)) {
968  REMMINA_CRITICAL("Could not save the key file. %s", error->message);
969  g_error_free(error);
970  error = NULL;
971  return;
972  }
973  /* Delete old pre-1.5 keys */
974  g_key_file_remove_key(key_remminafile, KEYFILE_GROUP_REMMINA, "last_success", NULL);
975  REMMINA_DEBUG("Last connection made on %s.", date);
976 }
977 
979 {
980  /* Delete all saved secrets for this profile */
981 
982  TRACE_CALL(__func__);
983  const RemminaProtocolSetting *setting_iter;
984  RemminaProtocolPlugin *protocol_plugin;
985  gchar *proto;
986 
987  protocol_plugin = NULL;
988 
989  remmina_file_set_string(remminafile, "password", NULL);
990 
991  proto = (gchar *)g_hash_table_lookup(remminafile->settings, "protocol");
992  if (proto) {
994  if (protocol_plugin) {
995  setting_iter = protocol_plugin->basic_settings;
996  if (setting_iter) {
997  while (setting_iter->type != REMMINA_PROTOCOL_SETTING_TYPE_END) {
998  // TOO VERBOSE: g_debug("setting name: %s", setting_iter->name);
999  if (setting_iter->name == NULL)
1000  g_error("Internal error: a setting name in protocol plugin %s is null. Please fix RemminaProtocolSetting struct content.", proto);
1001  else
1002  if (remmina_plugin_manager_is_encrypted_setting(protocol_plugin, setting_iter->name))
1004  setting_iter++;
1005  }
1006  }
1007  setting_iter = protocol_plugin->advanced_settings;
1008  if (setting_iter) {
1009  while (setting_iter->type != REMMINA_PROTOCOL_SETTING_TYPE_END) {
1010  if (remmina_plugin_manager_is_encrypted_setting(protocol_plugin, setting_iter->name))
1012  setting_iter++;
1013  }
1014  }
1015  remmina_file_save(remminafile);
1016  }
1017  }
1018 }
1019 
1030 gchar *
1032 {
1033  TRACE_CALL(__func__);
1034 
1035  GFile *file;
1036  GFileInfo *info;
1037 
1038  struct timeval tv;
1039  struct tm *ptm;
1040  char time_string[256];
1041  gchar *tmps;
1042 
1043  guint64 mtime;
1044 
1045  if (remminafile->statefile)
1046  //REMMINA_DEBUG ("remminafile->statefile: %s", remminafile->statefile);
1047  file = g_file_new_for_path(remminafile->statefile);
1048  else
1049  file = g_file_new_for_path(remminafile->filename);
1050 
1051  info = g_file_query_info(file,
1052  G_FILE_ATTRIBUTE_TIME_MODIFIED,
1053  G_FILE_QUERY_INFO_NONE,
1054  NULL,
1055  NULL);
1056 
1057  g_object_unref(file);
1058 
1059  if (info == NULL) {
1060  //REMMINA_DEBUG("could not get time info");
1061 
1062  // The BDAY "Fri, 16 Oct 2009 07:04:46 GMT"
1063  mtime = 1255676686;
1064  const gchar *last_success = remmina_file_get_string(remminafile, "last_success");
1065  if (last_success) {
1066  //REMMINA_DEBUG ("Last success is %s", last_success);
1067  GDateTime *dt;
1068  tmps = g_strconcat(last_success, "T00:00:00Z", NULL);
1069  dt = g_date_time_new_from_iso8601(tmps, NULL);
1070  g_free(tmps);
1071  if (dt) {
1072  //REMMINA_DEBUG("Converting last_success");
1073  tmps = g_date_time_format(dt, "%s");
1074  mtime = g_ascii_strtoull(tmps, NULL, 10);
1075  g_free(tmps);
1076  g_date_time_unref(dt);
1077  } else {
1078  //REMMINA_DEBUG("dt was null");
1079  mtime = 191543400;
1080  }
1081  }
1082  } else {
1083  mtime = g_file_info_get_attribute_uint64(info, G_FILE_ATTRIBUTE_TIME_MODIFIED);
1084  g_object_unref(info);
1085  }
1086 
1087  tv.tv_sec = mtime;
1088 
1089  ptm = localtime(&tv.tv_sec);
1090  strftime(time_string, sizeof(time_string), "%F - %T", ptm);
1091 
1092  gchar *modtime_string = g_locale_to_utf8(time_string, -1, NULL, NULL, NULL);
1093 
1094  return modtime_string;
1095 }
1096 
1104 void
1106 {
1107  TRACE_CALL(__func__);
1108  int fd;
1109  struct stat st;
1110  int r;
1111 
1112  if ((r = stat(remminafile->statefile, &st)) < 0) {
1113  if (errno != ENOENT)
1114  REMMINA_DEBUG("stat %s:", remminafile->statefile);
1115  } else if (!r) {
1116 #ifdef __APPLE__
1117  times[0] = st.st_atimespec;
1118  times[1] = st.st_mtimespec;
1119 #else
1120  times[0] = st.st_atim;
1121  times[1] = st.st_mtim;
1122 #endif
1123  if (utimensat(AT_FDCWD, remminafile->statefile, times, 0) < 0)
1124  REMMINA_DEBUG("utimensat %s:", remminafile->statefile);
1125  return;
1126  }
1127 
1128  if ((fd = open(remminafile->statefile, O_CREAT | O_EXCL, 0644)) < 0)
1129  REMMINA_DEBUG("open %s:", remminafile->statefile);
1130  close(fd);
1131 
1132  remmina_file_touch(remminafile);
1133 }
RemminaFile * remmina_file_load(const gchar *filename)
Definition: remmina_file.c:350
const gchar * remmina_plugin_manager_get_canonical_setting_name(const RemminaProtocolSetting *setting)
void remmina_file_free(RemminaFile *remminafile)
Definition: remmina_file.c:709
gboolean remmina_plugin_manager_is_encrypted_setting(RemminaProtocolPlugin *pp, const char *setting)
const gchar * remmina_file_get_string(RemminaFile *remminafile, const gchar *setting)
Definition: remmina_file.c:516
-
RemminaFile * remmina_file_dup(RemminaFile *remminafile)
Definition: remmina_file.c:863
+
RemminaFile * remmina_file_dup(RemminaFile *remminafile)
Definition: remmina_file.c:865
gchar * remmina_pref_file
Definition: rcw.c:78
const gchar * remmina_file_get_filename(RemminaFile *remminafile)
Definition: remmina_file.c:210
gchar * remmina_crypt_decrypt(const gchar *str)
typedefG_BEGIN_DECLS struct _RemminaFile RemminaFile
Definition: types.h:44
static struct timespec times[2]
Definition: remmina_file.c:73
-
RemminaFile * remmina_file_dup_temp_protocol(RemminaFile *remminafile, const gchar *new_protocol)
Definition: remmina_file.c:897
+
RemminaFile * remmina_file_dup_temp_protocol(RemminaFile *remminafile, const gchar *new_protocol)
Definition: remmina_file.c:899
static GKeyFile * remmina_file_get_keystate(RemminaFile *remminafile)
Definition: remmina_file.c:695
gchar * remmina_file_get_secret(RemminaFile *remminafile, const gchar *setting)
Definition: remmina_file.c:551
@@ -110,12 +110,12 @@ $(document).ready(function(){initNavTree('remmina__file_8c_source.html','');});
RemminaSecretPlugin * remmina_plugin_manager_get_secret_plugin(void)
gboolean(* is_service_available)(struct _RemminaSecretPlugin *instance)
Definition: plugin.h:144
void(* delete_password)(struct _RemminaSecretPlugin *instance, RemminaFile *remminafile, const gchar *key)
Definition: plugin.h:147
-
gchar * remmina_file_get_datetime(RemminaFile *remminafile)
Return the string date of the last time a Remmina state file has been modified.
+
gchar * remmina_file_get_datetime(RemminaFile *remminafile)
Return the string date of the last time a Remmina state file has been modified.
static void upgrade_sshkeys_202001(RemminaFile *remminafile)
Definition: remmina_file.c:291
gdouble remmina_file_get_double(RemminaFile *remminafile, const gchar *setting, gdouble default_value)
Definition: remmina_file.c:629
void remmina_file_generate_filename(RemminaFile *remminafile)
Generate a new Remmina connection profile file name.
Definition: remmina_file.c:114
-
const gchar * remmina_file_get_state(RemminaFile *remminafile, const gchar *setting)
Definition: remmina_file.c:923
+
const gchar * remmina_file_get_state(RemminaFile *remminafile, const gchar *setting)
Definition: remmina_file.c:925
int remmina_public_split_resolution_string(const char *resolution_string, int *w, int *h)
@@ -125,7 +125,7 @@ $(document).ready(function(){initNavTree('remmina__file_8c_source.html','');});
void remmina_main_update_file_datetime(RemminaFile *file)
const gchar * icon_name_ssh
Definition: plugin.h:73
gint remmina_file_get_state_int(RemminaFile *remminafile, const gchar *setting, gint default_value)
Definition: remmina_file.c:615
-
void remmina_file_state_last_success(RemminaFile *remminafile)
Definition: remmina_file.c:946
+
void remmina_file_state_last_success(RemminaFile *remminafile)
Definition: remmina_file.c:948
General utility functions, non-GTK related.
void remmina_file_set_statefile(RemminaFile *remminafile)
Definition: remmina_file.c:189
void remmina_file_set_filename(RemminaFile *remminafile, const gchar *filename)
Definition: remmina_file.c:182
@@ -139,12 +139,12 @@ $(document).ready(function(){initNavTree('remmina__file_8c_source.html','');});
void remmina_file_set_int(RemminaFile *remminafile, const gchar *setting, gint value)
Definition: remmina_file.c:585
static GKeyFile * remmina_file_get_keyfile(RemminaFile *remminafile)
Definition: remmina_file.c:680
-
void remmina_file_delete(const gchar *filename)
Definition: remmina_file.c:909
+
void remmina_file_delete(const gchar *filename)
Definition: remmina_file.c:911
const RemminaProtocolSetting * basic_settings
Definition: plugin.h:74
struct remmina_masterthread_exec_data::@12::@17 file_set_string
struct remmina_masterthread_exec_data::@12::@16 file_get_string
gchar * remmina_file_get_datadir(void)
Return datadir_path from pref or first found data dir as per XDG specs.
-
void remmina_file_touch(RemminaFile *remminafile)
Update the atime and mtime of a given filename.
+
void remmina_file_touch(RemminaFile *remminafile)
Update the atime and mtime of a given filename.
static gchar * cachedir
gboolean list_refresh_workaround
Definition: remmina_pref.h:150
RemminaProtocolSettingType type
Definition: types.h:117
@@ -158,7 +158,7 @@ $(document).ready(function(){initNavTree('remmina__file_8c_source.html','');});
gint remmina_file_get_int(RemminaFile *remminafile, const gchar *setting, gint default_value)
Definition: remmina_file.c:603
guint remmina_utils_string_replace_all(GString *haystack, const gchar *needle, const gchar *replace)
Replaces all occurrences of needle in haystack with replace.
-
void remmina_file_store_secret_plugin_password(RemminaFile *remminafile, const gchar *key, const gchar *value)
Definition: remmina_file.c:844
+
void remmina_file_store_secret_plugin_password(RemminaFile *remminafile, const gchar *key, const gchar *value)
Definition: remmina_file.c:846
RemminaPlugin * remmina_plugin_manager_get_plugin(RemminaPluginType type, const gchar *name)
@@ -167,14 +167,14 @@ $(document).ready(function(){initNavTree('remmina__file_8c_source.html','');});
gchar *(* get_password)(struct _RemminaSecretPlugin *instance, RemminaFile *remminafile, const gchar *key)
Definition: plugin.h:146
void(* store_password)(struct _RemminaSecretPlugin *instance, RemminaFile *remminafile, const gchar *key, const gchar *password)
Definition: plugin.h:145
void remmina_file_set_string(RemminaFile *remminafile, const gchar *setting, const gchar *value)
Definition: remmina_file.c:469
-
void remmina_file_save(RemminaFile *remminafile)
Definition: remmina_file.c:728
+
void remmina_file_save(RemminaFile *remminafile)
Definition: remmina_file.c:730
RemminaFile * remmina_file_copy(const gchar *filename)
Definition: remmina_file.c:217
static void upgrade_sshkeys_202001_mig_common_setting(RemminaFile *remminafile, gboolean protocol_is_ssh, gboolean ssh_enabled, gchar *suffix)
Definition: remmina_file.c:265
const gchar * icon_name
Definition: plugin.h:72
-
void remmina_file_unsave_passwords(RemminaFile *remminafile)
Definition: remmina_file.c:976
+
void remmina_file_unsave_passwords(RemminaFile *remminafile)
Definition: remmina_file.c:978
void remmina_file_set_state_int(RemminaFile *remminafile, const gchar *setting, gint value)
Definition: remmina_file.c:594
-
const gchar * remmina_file_get_icon_name(RemminaFile *remminafile)
Definition: remmina_file.c:883
+
const gchar * remmina_file_get_icon_name(RemminaFile *remminafile)
Definition: remmina_file.c:885
static RemminaFile * remmina_file_new_empty(void)
Definition: remmina_file.c:76
enum remmina_masterthread_exec_data::@11 func
diff --git a/public/remmina__file_8h.html b/public/remmina__file_8h.html index 39cd2cd44..a593c654e 100644 --- a/public/remmina__file_8h.html +++ b/public/remmina__file_8h.html @@ -246,7 +246,7 @@ Functions
-

Definition at line 909 of file remmina_file.c.

+

Definition at line 911 of file remmina_file.c.

@@ -266,7 +266,7 @@ Functions
-

Definition at line 863 of file remmina_file.c.

+

Definition at line 865 of file remmina_file.c.

@@ -296,7 +296,7 @@ Functions
-

Definition at line 897 of file remmina_file.c.

+

Definition at line 899 of file remmina_file.c.

@@ -401,7 +401,7 @@ Functions

This is used to return the modification date of a file and it’s used to return the modification date and time of a given Remmina file. If it fails it will return "Fri, 16 Oct 2009 07:04:46 GMT", that is just a date to don't return an empty string (challenge: what was happened that day at that time?).

Returns
A date string in the form "%d/%m/%Y %H:%M:%S".
Todo:
This should be moved to remmina_utils.c
-

Definition at line 1029 of file remmina_file.c.

+

Definition at line 1031 of file remmina_file.c.

@@ -441,7 +441,7 @@ Functions
-

Definition at line 883 of file remmina_file.c.

+

Definition at line 885 of file remmina_file.c.

@@ -537,7 +537,7 @@ Functions
-

Definition at line 923 of file remmina_file.c.

+

Definition at line 925 of file remmina_file.c.

@@ -745,7 +745,7 @@ Functions
-

Definition at line 728 of file remmina_file.c.

+

Definition at line 730 of file remmina_file.c.

@@ -959,7 +959,7 @@ Functions
-

Definition at line 946 of file remmina_file.c.

+

Definition at line 948 of file remmina_file.c.

@@ -995,7 +995,7 @@ Functions
-

Definition at line 844 of file remmina_file.c.

+

Definition at line 846 of file remmina_file.c.

@@ -1019,7 +1019,7 @@ Functions

Function used to update the atime and mtime of a given remmina file, partially taken from suckless sbase

See also
https://git.suckless.org/sbase/tree/touch.c
Todo:
This should be moved to remmina_utils.c
-

Definition at line 1103 of file remmina_file.c.

+

Definition at line 1105 of file remmina_file.c.

@@ -1039,7 +1039,7 @@ Functions
-

Definition at line 976 of file remmina_file.c.

+

Definition at line 978 of file remmina_file.c.

diff --git a/public/remmina__file_8h_source.html b/public/remmina__file_8h_source.html index 293cc9420..ad966ff07 100644 --- a/public/remmina__file_8h_source.html +++ b/public/remmina__file_8h_source.html @@ -91,39 +91,39 @@ $(document).ready(function(){initNavTree('remmina__file_8h_source.html','');});
Definition: remmina_file.h:71
typedefG_BEGIN_DECLS struct _RemminaFile RemminaFile
Definition: types.h:44
-
void remmina_file_delete(const gchar *filename)
Definition: remmina_file.c:909
+
void remmina_file_delete(const gchar *filename)
Definition: remmina_file.c:911
Definition: remmina_file.h:73
-
void remmina_file_touch(RemminaFile *remminafile)
Update the atime and mtime of a given filename.
+
void remmina_file_touch(RemminaFile *remminafile)
Update the atime and mtime of a given filename.
gchar * statefile
Definition: remmina_file.h:49
GHashTable * states
Definition: remmina_file.h:51
RemminaFile * remmina_file_new(void)
Definition: remmina_file.c:93
gboolean remmina_file_remove_key(RemminaFile *remminafile, const gchar *setting)
RemminaFile * remmina_file_copy(const gchar *filename)
Definition: remmina_file.c:217
gdouble remmina_file_get_state_double(RemminaFile *remminafile, const gchar *setting, gdouble default_value)
Definition: remmina_file.c:655
-
RemminaFile * remmina_file_dup_temp_protocol(RemminaFile *remminafile, const gchar *new_protocol)
Definition: remmina_file.c:897
+
RemminaFile * remmina_file_dup_temp_protocol(RemminaFile *remminafile, const gchar *new_protocol)
Definition: remmina_file.c:899
void remmina_file_set_statefile(RemminaFile *remminafile)
Definition: remmina_file.c:189
-
const gchar * remmina_file_get_state(RemminaFile *remminafile, const gchar *setting)
Definition: remmina_file.c:923
-
void remmina_file_state_last_success(RemminaFile *remminafile)
Definition: remmina_file.c:946
+
const gchar * remmina_file_get_state(RemminaFile *remminafile, const gchar *setting)
Definition: remmina_file.c:925
+
void remmina_file_state_last_success(RemminaFile *remminafile)
Definition: remmina_file.c:948
void remmina_file_set_state_int(RemminaFile *remminafile, const gchar *setting, gint value)
Definition: remmina_file.c:594
-
gchar * remmina_file_get_datetime(RemminaFile *remminafile)
Return the string date of the last time a Remmina state file has been modified.
-
void remmina_file_store_secret_plugin_password(RemminaFile *remminafile, const gchar *key, const gchar *value)
Definition: remmina_file.c:844
+
gchar * remmina_file_get_datetime(RemminaFile *remminafile)
Return the string date of the last time a Remmina state file has been modified.
+
void remmina_file_store_secret_plugin_password(RemminaFile *remminafile, const gchar *key, const gchar *value)
Definition: remmina_file.c:846
gboolean prevent_saving
Definition: remmina_file.h:53
gint remmina_file_get_state_int(RemminaFile *remminafile, const gchar *setting, gint default_value)
Definition: remmina_file.c:615
void remmina_file_set_filename(RemminaFile *remminafile, const gchar *filename)
Definition: remmina_file.c:182
Definition: remmina_file.h:69
void remmina_file_set_state(RemminaFile *remminafile, const gchar *setting, const gchar *value)
Definition: remmina_file.c:505
Definition: remmina_file.h:72
-
RemminaFile * remmina_file_dup(RemminaFile *remminafile)
Definition: remmina_file.c:863
+
RemminaFile * remmina_file_dup(RemminaFile *remminafile)
Definition: remmina_file.c:865
gint remmina_file_get_int(RemminaFile *remminafile, const gchar *setting, gint default_value)
Definition: remmina_file.c:603
void remmina_file_generate_filename(RemminaFile *remminafile)
Generate a new Remmina connection profile file name.
Definition: remmina_file.c:114
void remmina_file_set_int(RemminaFile *remminafile, const gchar *setting, gint value)
Definition: remmina_file.c:585
Definition: remmina_file.h:68
void remmina_file_free(RemminaFile *remminafile)
Definition: remmina_file.c:709
gchar * remmina_file_format_properties(RemminaFile *remminafile, const gchar *setting)
Definition: remmina_file.c:561
-
void remmina_file_save(RemminaFile *remminafile)
Definition: remmina_file.c:728
+
void remmina_file_save(RemminaFile *remminafile)
Definition: remmina_file.c:730
const gchar * remmina_file_get_string(RemminaFile *remminafile, const gchar *setting)
Definition: remmina_file.c:516
-
void remmina_file_unsave_passwords(RemminaFile *remminafile)
Definition: remmina_file.c:976
-
const gchar * remmina_file_get_icon_name(RemminaFile *remminafile)
Definition: remmina_file.c:883
+
void remmina_file_unsave_passwords(RemminaFile *remminafile)
Definition: remmina_file.c:978
+
const gchar * remmina_file_get_icon_name(RemminaFile *remminafile)
Definition: remmina_file.c:885
RemminaFile * remmina_file_load(const gchar *filename)
Definition: remmina_file.c:350
gchar * filename
Definition: remmina_file.h:47
Definition: remmina_file.h:46
diff --git a/public/remmina__file__editor_8c_source.html b/public/remmina__file__editor_8c_source.html index 7a334ebe7..1848a5bbe 100644 --- a/public/remmina__file__editor_8c_source.html +++ b/public/remmina__file__editor_8c_source.html @@ -94,14 +94,14 @@ $(document).ready(function(){initNavTree('remmina__file__editor_8c_source.html',
Definition: plugin.h:56
const gchar * remmina_file_get_string(RemminaFile *remminafile, const gchar *setting)
Definition: remmina_file.c:516
-
gchar ** remmina_pref_keymap_groups(void)
+
gchar ** remmina_pref_keymap_groups(void)
static void remmina_file_editor_create_resolution(RemminaFileEditor *gfe, const RemminaProtocolSetting *setting, GtkWidget *grid, gint row)
Definition: types.h:106
static GtkWidget * remmina_file_editor_create_combo(RemminaFileEditor *gfe, GtkWidget *grid, gint row, gint col, const gchar *label, const gchar *list, const gchar *value, gchar *setting_name)
Definition: remmina_file.h:71
Definition: types.h:112
-
RemminaFile * remmina_file_dup(RemminaFile *remminafile)
Definition: remmina_file.c:863
+
RemminaFile * remmina_file_dup(RemminaFile *remminafile)
Definition: remmina_file.c:865
GtkWidget * remmina_public_create_combo_entry(const gchar *text, const gchar *def, gboolean descending)
static void remmina_file_editor_on_connect(GtkWidget *button, RemminaFileEditor *gfe)
Definition: types.h:109
@@ -129,7 +129,7 @@ $(document).ready(function(){initNavTree('remmina__file__editor_8c_source.html',
gboolean remmina_public_resolution_validation_func(const gchar *new_str, gchar **error)
const gchar * domain
Definition: plugin.h:60
-
gchar * remmina_pref_get_recent(const gchar *protocol)
Definition: remmina_pref.c:966
+
gchar * remmina_pref_get_recent(const gchar *protocol)
Definition: remmina_pref.c:967
static void remmina_file_toggle_password_view(GtkWidget *widget, gpointer data)
static void remmina_file_editor_create_server(RemminaFileEditor *gfe, const RemminaProtocolSetting *setting, GtkWidget *grid, gint row)
@@ -169,7 +169,7 @@ $(document).ready(function(){initNavTree('remmina__file__editor_8c_source.html',
RemminaProtocolSSHSetting
Definition: types.h:127
void remmina_file_set_int(RemminaFile *remminafile, const gchar *setting, gint value)
Definition: remmina_file.c:585
Definition: types.h:107
-
void remmina_file_delete(const gchar *filename)
Definition: remmina_file.c:909
+
void remmina_file_delete(const gchar *filename)
Definition: remmina_file.c:911
static void remmina_file_editor_entry_on_changed(GtkEditable *editable, RemminaFileEditor *gfe)
static GtkWidget * remmina_file_editor_create_text2(RemminaFileEditor *gfe, GtkWidget *grid, gint row, gint col, const gchar *label, const gchar *value, gint left, gint right, gchar *setting_name)
Definition: remmina_file.h:69
@@ -181,7 +181,7 @@ $(document).ready(function(){initNavTree('remmina__file__editor_8c_source.html',
GtkWidget * remmina_file_editor_new_from_file(RemminaFile *remminafile)
gpointer validator_data
Definition: types.h:123
Definition: types.h:132
-
gboolean remmina_pref_get_boolean(const gchar *key)
+
gboolean remmina_pref_get_boolean(const gchar *key)
void remmina_file_editor_int_setting_filter(GtkEditable *editable, const gchar *text, gint length, gint *position, gpointer data)
Definition: types.h:113
void remmina_string_list_set_text(const gchar *text, const gboolean clear_data)
@@ -217,19 +217,19 @@ $(document).ready(function(){initNavTree('remmina__file__editor_8c_source.html',
const gchar * name
Definition: plugin.h:67
void remmina_file_editor_double_setting_filter(GtkEditable *editable, const gchar *text, gint length, gint *position, gpointer data)
Definition: remmina_file.h:68
-
gchar * remmina_file_manager_get_groups(void)
+
gchar * remmina_file_manager_get_groups(void)
Definition: types.h:110
static GtkWidget * remmina_file_editor_create_text(RemminaFileEditor *gfe, GtkWidget *grid, gint row, gint col, const gchar *label, const gchar *value, gchar *setting_name)
void remmina_file_set_string(RemminaFile *remminafile, const gchar *setting, const gchar *value)
Definition: remmina_file.c:469
static void remmina_file_editor_save_behavior_tab(RemminaFileEditor *gfe)
static void remmina_file_editor_create_behavior_tab(RemminaFileEditor *gfe)
-
void remmina_file_save(RemminaFile *remminafile)
Definition: remmina_file.c:728
+
void remmina_file_save(RemminaFile *remminafile)
Definition: remmina_file.c:730
static void remmina_file_editor_browse_resolution(GtkWidget *button, RemminaFileEditor *gfe)
static gboolean remmina_file_editor_validate_settings(RemminaFileEditor *gfe, gchar *setting_name_to_validate, gconstpointer value, GError **err)
static void remmina_file_editor_ssh_tunnel_server_custom_radio_on_toggled(GtkToggleButton *togglebutton, RemminaFileEditor *gfe)
RemminaFile * remmina_file_copy(const gchar *filename)
Definition: remmina_file.c:217
Definition: types.h:131
-
RemminaFile * remmina_file_manager_load_file(const gchar *filename)
+
RemminaFile * remmina_file_manager_load_file(const gchar *filename)
static gboolean remmina_file_editor_iterate_protocol(gchar *protocol, RemminaPlugin *plugin, gpointer data)
static GError * remmina_file_editor_update(RemminaFileEditor *gfe, GtkWidget **failed_widget)
Definition: types.h:98
diff --git a/public/remmina__file__manager_8c.html b/public/remmina__file__manager_8c.html index 9b2016ffe..1aa553053 100644 --- a/public/remmina__file__manager_8c.html +++ b/public/remmina__file__manager_8c.html @@ -180,7 +180,7 @@ Variables
-

Definition at line 248 of file remmina_file_manager.c.

+

Definition at line 249 of file remmina_file_manager.c.

@@ -239,7 +239,7 @@ Variables
-

Definition at line 335 of file remmina_file_manager.c.

+

Definition at line 336 of file remmina_file_manager.c.

@@ -259,7 +259,7 @@ Variables
-

Definition at line 302 of file remmina_file_manager.c.

+

Definition at line 303 of file remmina_file_manager.c.

@@ -279,7 +279,7 @@ Variables
-

Definition at line 209 of file remmina_file_manager.c.

+

Definition at line 210 of file remmina_file_manager.c.

@@ -333,7 +333,7 @@ Variables
-

Definition at line 177 of file remmina_file_manager.c.

+

Definition at line 178 of file remmina_file_manager.c.

@@ -353,7 +353,7 @@ Variables
-

Definition at line 355 of file remmina_file_manager.c.

+

Definition at line 356 of file remmina_file_manager.c.

diff --git a/public/remmina__file__manager_8c_source.html b/public/remmina__file__manager_8c_source.html index 501086567..deedcd799 100644 --- a/public/remmina__file__manager_8c_source.html +++ b/public/remmina__file__manager_8c_source.html @@ -86,7 +86,7 @@ $(document).ready(function(){initNavTree('remmina__file__manager_8c_source.html'
remmina_file_manager.c
-Go to the documentation of this file.
1 /*
2  * Remmina - The GTK+ Remote Desktop Client
3  * Copyright (C) 2009-2010 Vic Lee
4  * Copyright (C) 2014-2015 Antenore Gatta, Fabio Castelli, Giovanni Panozzo
5  * Copyright (C) 2016-2023 Antenore Gatta, Giovanni Panozzo
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  *
22  * In addition, as a special exception, the copyright holders give
23  * permission to link the code of portions of this program with the
24  * OpenSSL library under certain conditions as described in each
25  * individual source file, and distribute linked combinations
26  * including the two.
27  * You must obey the GNU General Public License in all respects
28  * for all of the code used other than OpenSSL. * If you modify
29  * file(s) with this exception, you may extend this exception to your
30  * version of the file(s), but you are not obligated to do so. * If you
31  * do not wish to do so, delete this exception statement from your
32  * version. * If you delete this exception statement from all source
33  * files in the program, then also delete it here.
34  *
35  */
36 
37 #include "config.h"
38 
39 #include <errno.h>
40 #include <gtk/gtk.h>
41 #include <string.h>
42 
43 #include "remmina_log.h"
44 #include "remmina_public.h"
45 #include "remmina_pref.h"
46 #include "remmina_string_array.h"
47 #include "remmina_plugin_manager.h"
48 #include "remmina_file_manager.h"
50 
51 static gchar *remminadir;
52 static gchar *cachedir;
53 
60 {
61  TRACE_CALL(__func__);
62  const gchar *dir = ".remmina";
63  int i;
64 
65  /* From preferences, datadir_path */
66  remminadir = remmina_pref_get_value("datadir_path");
67  if (remminadir != NULL && strlen(remminadir) > 0)
68  if (g_file_test(remminadir, G_FILE_TEST_IS_DIR))
69  return remminadir;
70  g_free(remminadir), remminadir = NULL;
71  /* Legacy ~/.remmina */
72  remminadir = g_build_path("/", g_get_home_dir(), dir, NULL);
73  if (g_file_test(remminadir, G_FILE_TEST_IS_DIR))
74  return remminadir;
75  g_free(remminadir), remminadir = NULL;
76  /* ~/.local/share/remmina */
77  remminadir = g_build_path("/", g_get_user_data_dir(), "remmina", NULL);
78  if (g_file_test(remminadir, G_FILE_TEST_IS_DIR))
79  return remminadir;
80  g_free(remminadir), remminadir = NULL;
81  /* /usr/local/share/remmina */
82  const gchar *const *dirs = g_get_system_data_dirs();
83 
84  g_free(remminadir), remminadir = NULL;
85  for (i = 0; dirs[i] != NULL; ++i) {
86  remminadir = g_build_path("/", dirs[i], "remmina", NULL);
87  if (g_file_test(remminadir, G_FILE_TEST_IS_DIR))
88  return remminadir;
89  g_free(remminadir), remminadir = NULL;
90  }
91  /* The last case we use the home ~/.local/share/remmina */
92  remminadir = g_build_path("/", g_get_user_data_dir(), "remmina", NULL);
93  return remminadir;
94 }
95 
97 static gboolean remmina_file_manager_do_copy(const char *src_path, const char *dst_path)
98 {
99  GFile *src = g_file_new_for_path(src_path), *dst = g_file_new_for_path(dst_path);
100  /* We don’t overwrite the target if it exists */
101  const gboolean ok = g_file_copy(src, dst, G_FILE_COPY_NONE, NULL, NULL, NULL, NULL);
102 
103  g_object_unref(dst);
104  g_object_unref(src);
105 
106  return ok;
107 }
108 
117 {
118  TRACE_CALL(__func__);
119  GDir *dir;
120  const gchar *legacy = ".remmina";
121  const gchar *filename;
122  int i;
123 
124  /* Get and create the XDG_DATA_HOME directory */
125  remminadir = remmina_pref_get_value("datadir_path");
126  if (g_mkdir_with_parents(remminadir, 0750) == 0) {
127  REMMINA_DEBUG("Initialized the \"%s\" data folder", remminadir);
128  g_free(remminadir), remminadir = NULL;
129  } else {
130  g_free(remminadir), remminadir = NULL;
131  /* Get and create the XDG_DATA_HOME directory */
132  remminadir = g_build_path("/", g_get_user_data_dir(), "remmina", NULL);
133  if (g_mkdir_with_parents(remminadir, 0750) == 0)
134  REMMINA_DEBUG("Initialized the \"%s\" data folder", remminadir);
135  else
136  REMMINA_CRITICAL("Cannot create the \"%s\" data folder", remminadir);
137  g_free(remminadir), remminadir = NULL;
138  }
139  /* Create the XDG_CACHE_HOME directory */
140  cachedir = g_build_path("/", g_get_user_cache_dir(), "remmina", NULL);
141  g_mkdir_with_parents(cachedir, 0750);
142  g_free(cachedir), cachedir = NULL;
143  /* Empty legacy ~/.remmina */
144  remminadir = g_build_path("/", g_get_home_dir(), legacy, NULL);
145  if (g_file_test(remminadir, G_FILE_TEST_IS_DIR)) {
146  dir = g_dir_open(remminadir, 0, NULL);
147  while ((filename = g_dir_read_name(dir)) != NULL) {
149  g_build_path("/", remminadir, filename, NULL),
150  g_build_path("/", g_get_user_data_dir(),
151  "remmina", filename, NULL));
152  }
153  }
154 
155  /* XDG_DATA_DIRS, i.e. /usr/local/share/remmina */
156  const gchar *const *dirs = g_get_system_data_dirs();
157 
158  g_free(remminadir), remminadir = NULL;
159  for (i = 0; dirs[i] != NULL; ++i) {
160  remminadir = g_build_path("/", dirs[i], "remmina", NULL);
161  if (g_file_test(remminadir, G_FILE_TEST_IS_DIR)) {
162  dir = g_dir_open(remminadir, 0, NULL);
163  while ((filename = g_dir_read_name(dir)) != NULL) {
165  g_build_path("/", remminadir, filename, NULL),
166  g_build_path("/", g_get_user_data_dir(),
167  "remmina", filename, NULL));
168  }
169  }
170  g_free(remminadir), remminadir = NULL;
171  }
172  /* At last we make sure we use XDG_USER_DATA */
173  if (remminadir != NULL)
174  g_free(remminadir), remminadir = NULL;
175 }
176 
177 gint remmina_file_manager_iterate(GFunc func, gpointer user_data)
178 {
179  TRACE_CALL(__func__);
180  gchar filename[MAX_PATH_LEN];
181  GDir *dir;
182  const gchar *name;
183  RemminaFile *remminafile;
184  gint items_count = 0;
185  gchar *remmina_data_dir;
186 
187  remmina_data_dir = remmina_file_get_datadir();
188  dir = g_dir_open(remmina_data_dir, 0, NULL);
189 
190  if (dir) {
191  while ((name = g_dir_read_name(dir)) != NULL) {
192  if (!g_str_has_suffix(name, ".remmina"))
193  continue;
194  g_snprintf(filename, MAX_PATH_LEN, "%s/%s",
195  remmina_data_dir, name);
196  remminafile = remmina_file_load(filename);
197  if (remminafile) {
198  (*func)(remminafile, user_data);
199  remmina_file_free(remminafile);
200  items_count++;
201  }
202  }
203  g_dir_close(dir);
204  }
205  g_free(remmina_data_dir);
206  return items_count;
207 }
208 
210 {
211  TRACE_CALL(__func__);
212  gchar filename[MAX_PATH_LEN];
213  GDir *dir;
214  const gchar *name;
215  RemminaFile *remminafile;
216  RemminaStringArray *array;
217  const gchar *group;
218  gchar *groups;
219  gchar *remmina_data_dir;
220 
221  remmina_data_dir = remmina_file_get_datadir();
222  array = remmina_string_array_new();
223 
224  dir = g_dir_open(remmina_data_dir, 0, NULL);
225 
226  if (dir == NULL)
227  return 0;
228  while ((name = g_dir_read_name(dir)) != NULL) {
229  if (!g_str_has_suffix(name, ".remmina"))
230  continue;
231  g_snprintf(filename, MAX_PATH_LEN, "%s/%s", remmina_data_dir, name);
232  remminafile = remmina_file_load(filename);
233  if (remminafile) {
234  group = remmina_file_get_string(remminafile, "group");
235  if (group && remmina_string_array_find(array, group) < 0)
236  remmina_string_array_add(array, group);
237  remmina_file_free(remminafile);
238  }
239  }
240  g_dir_close(dir);
242  groups = remmina_string_array_to_string(array);
244  g_free(remmina_data_dir);
245  return groups;
246 }
247 
248 static void remmina_file_manager_add_group(GNode *node, const gchar *group)
249 {
250  TRACE_CALL(__func__);
251  gint cmp;
252  gchar *p1;
253  gchar *p2;
254  GNode *child;
255  gboolean found;
256  RemminaGroupData *data;
257 
258  if (node == NULL)
259  return;
260 
261  if (group == NULL || group[0] == '\0')
262  return;
263 
264  p1 = g_strdup(group);
265  p2 = strchr(p1, '/');
266 
267  if (p2)
268  *p2++ = '\0';
269 
270  found = FALSE;
271 
272  for (child = g_node_first_child(node); child; child = g_node_next_sibling(child)) {
273  cmp = g_strcmp0(((RemminaGroupData *)child->data)->name, p1);
274 
275  if (cmp == 0) {
276  found = TRUE;
277  break;
278  }
279 
280  if (cmp > 0)
281  break;
282  }
283 
284  if (!found) {
285  data = g_new0(RemminaGroupData, 1);
286  data->name = p1;
287  if (node->data)
288  data->group = g_strdup_printf("%s/%s", ((RemminaGroupData *)node->data)->group, p1);
289  else
290  data->group = g_strdup(p1);
291  if (child)
292  child = g_node_insert_data_before(node, child, data);
293  else
294  child = g_node_append_data(node, data);
295  }
297 
298  if (found)
299  g_free(p1);
300 }
301 
303 {
304  TRACE_CALL(__func__);
305  gchar filename[MAX_PATH_LEN];
306  GDir *dir;
307  g_autofree gchar *datadir = NULL;
308  const gchar *name;
309  RemminaFile *remminafile;
310  const gchar *group;
311  GNode *root;
312 
313  root = g_node_new(NULL);
314 
315  datadir = g_strdup(remmina_file_get_datadir());
316  dir = g_dir_open(datadir, 0, NULL);
317 
318  if (dir == NULL)
319  return root;
320  while ((name = g_dir_read_name(dir)) != NULL) {
321  if (!g_str_has_suffix(name, ".remmina"))
322  continue;
323  g_snprintf(filename, MAX_PATH_LEN, "%s/%s", datadir, name);
324  remminafile = remmina_file_load(filename);
325  if (remminafile) {
326  group = remmina_file_get_string(remminafile, "group");
327  remmina_file_manager_add_group(root, group);
328  remmina_file_free(remminafile);
329  }
330  }
331  g_dir_close(dir);
332  return root;
333 }
334 
336 {
337  TRACE_CALL(__func__);
338  RemminaGroupData *data;
339  GNode *child;
340 
341  if (!node)
342  return;
343  data = (RemminaGroupData *)node->data;
344  if (data) {
345  g_free(data->name);
346  g_free(data->group);
347  g_free(data);
348  node->data = NULL;
349  }
350  for (child = g_node_first_child(node); child; child = g_node_next_sibling(child))
352  g_node_unlink(node);
353 }
354 
356 {
357  TRACE_CALL(__func__);
358  RemminaFile *remminafile = NULL;
359  RemminaFilePlugin *plugin;
360  gchar *p;
361 
362  if ((p = strrchr(filename, '.')) != NULL && g_strcmp0(p + 1, "remmina") == 0) {
363  remminafile = remmina_file_load(filename);
364  } else {
366  if (plugin)
367  remminafile = plugin->import_func(plugin, filename);
368  }
369  return remminafile;
370 }
G_BEGIN_DECLS struct _RemminaGroupData RemminaGroupData
+Go to the documentation of this file.
1 /*
2  * Remmina - The GTK+ Remote Desktop Client
3  * Copyright (C) 2009-2010 Vic Lee
4  * Copyright (C) 2014-2015 Antenore Gatta, Fabio Castelli, Giovanni Panozzo
5  * Copyright (C) 2016-2023 Antenore Gatta, Giovanni Panozzo
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  *
22  * In addition, as a special exception, the copyright holders give
23  * permission to link the code of portions of this program with the
24  * OpenSSL library under certain conditions as described in each
25  * individual source file, and distribute linked combinations
26  * including the two.
27  * You must obey the GNU General Public License in all respects
28  * for all of the code used other than OpenSSL. * If you modify
29  * file(s) with this exception, you may extend this exception to your
30  * version of the file(s), but you are not obligated to do so. * If you
31  * do not wish to do so, delete this exception statement from your
32  * version. * If you delete this exception statement from all source
33  * files in the program, then also delete it here.
34  *
35  */
36 
37 #include "config.h"
38 
39 #include <errno.h>
40 #include <gtk/gtk.h>
41 #include <string.h>
42 
43 #include "remmina_log.h"
44 #include "remmina_public.h"
45 #include "remmina_pref.h"
46 #include "remmina_string_array.h"
47 #include "remmina_plugin_manager.h"
48 #include "remmina_file_manager.h"
50 
51 static gchar *remminadir;
52 static gchar *cachedir;
53 
60 {
61  TRACE_CALL(__func__);
62  const gchar *dir = ".remmina";
63  int i;
64 
65  /* From preferences, datadir_path */
66  remminadir = remmina_pref_get_value("datadir_path");
67  if (remminadir != NULL && strlen(remminadir) > 0)
68  if (g_file_test(remminadir, G_FILE_TEST_IS_DIR))
69  return remminadir;
70  g_free(remminadir), remminadir = NULL;
71  /* Legacy ~/.remmina */
72  remminadir = g_build_path("/", g_get_home_dir(), dir, NULL);
73  if (g_file_test(remminadir, G_FILE_TEST_IS_DIR))
74  return remminadir;
75  g_free(remminadir), remminadir = NULL;
76  /* ~/.local/share/remmina */
77  remminadir = g_build_path("/", g_get_user_data_dir(), "remmina", NULL);
78  if (g_file_test(remminadir, G_FILE_TEST_IS_DIR))
79  return remminadir;
80  g_free(remminadir), remminadir = NULL;
81  /* /usr/local/share/remmina */
82  const gchar *const *dirs = g_get_system_data_dirs();
83 
84  g_free(remminadir), remminadir = NULL;
85  for (i = 0; dirs[i] != NULL; ++i) {
86  remminadir = g_build_path("/", dirs[i], "remmina", NULL);
87  if (g_file_test(remminadir, G_FILE_TEST_IS_DIR))
88  return remminadir;
89  g_free(remminadir), remminadir = NULL;
90  }
91  /* The last case we use the home ~/.local/share/remmina */
92  remminadir = g_build_path("/", g_get_user_data_dir(), "remmina", NULL);
93  return remminadir;
94 }
95 
97 static gboolean remmina_file_manager_do_copy(const char *src_path, const char *dst_path)
98 {
99  GFile *src = g_file_new_for_path(src_path), *dst = g_file_new_for_path(dst_path);
100  /* We don’t overwrite the target if it exists */
101  const gboolean ok = g_file_copy(src, dst, G_FILE_COPY_NONE, NULL, NULL, NULL, NULL);
102 
103  g_object_unref(dst);
104  g_object_unref(src);
105 
106  return ok;
107 }
108 
117 {
118  TRACE_CALL(__func__);
119  GDir *dir;
120  const gchar *legacy = ".remmina";
121  const gchar *filename;
122  int i;
123 
124  /* Get and create the XDG_DATA_HOME directory */
125  remminadir = remmina_pref_get_value("datadir_path");
126  if (g_mkdir_with_parents(remminadir, 0750) == 0) {
127  REMMINA_DEBUG("Initialized the \"%s\" data folder", remminadir);
128  g_free(remminadir), remminadir = NULL;
129  } else {
130  g_free(remminadir), remminadir = NULL;
131  /* Get and create the XDG_DATA_HOME directory */
132  remminadir = g_build_path("/", g_get_user_data_dir(), "remmina", NULL);
133  if (g_mkdir_with_parents(remminadir, 0750) == 0)
134  REMMINA_DEBUG("Initialized the \"%s\" data folder", remminadir);
135  else
136  REMMINA_CRITICAL("Cannot create the \"%s\" data folder", remminadir);
137  g_free(remminadir), remminadir = NULL;
138  }
139  /* Create the XDG_CACHE_HOME directory */
140  cachedir = g_build_path("/", g_get_user_cache_dir(), "remmina", NULL);
141  g_mkdir_with_parents(cachedir, 0750);
142  g_free(cachedir), cachedir = NULL;
143  /* Empty legacy ~/.remmina */
144  remminadir = g_build_path("/", g_get_home_dir(), legacy, NULL);
145  if (g_file_test(remminadir, G_FILE_TEST_IS_DIR)) {
146  dir = g_dir_open(remminadir, 0, NULL);
147  while ((filename = g_dir_read_name(dir)) != NULL) {
149  g_build_path("/", remminadir, filename, NULL),
150  g_build_path("/", g_get_user_data_dir(),
151  "remmina", filename, NULL));
152  }
153  g_dir_close(dir);
154  }
155 
156  /* XDG_DATA_DIRS, i.e. /usr/local/share/remmina */
157  const gchar *const *dirs = g_get_system_data_dirs();
158 
159  g_free(remminadir), remminadir = NULL;
160  for (i = 0; dirs[i] != NULL; ++i) {
161  remminadir = g_build_path("/", dirs[i], "remmina", NULL);
162  if (g_file_test(remminadir, G_FILE_TEST_IS_DIR)) {
163  dir = g_dir_open(remminadir, 0, NULL);
164  while ((filename = g_dir_read_name(dir)) != NULL) {
166  g_build_path("/", remminadir, filename, NULL),
167  g_build_path("/", g_get_user_data_dir(),
168  "remmina", filename, NULL));
169  }
170  }
171  g_free(remminadir), remminadir = NULL;
172  }
173  /* At last we make sure we use XDG_USER_DATA */
174  if (remminadir != NULL)
175  g_free(remminadir), remminadir = NULL;
176 }
177 
178 gint remmina_file_manager_iterate(GFunc func, gpointer user_data)
179 {
180  TRACE_CALL(__func__);
181  gchar filename[MAX_PATH_LEN];
182  GDir *dir;
183  const gchar *name;
184  RemminaFile *remminafile;
185  gint items_count = 0;
186  gchar *remmina_data_dir;
187 
188  remmina_data_dir = remmina_file_get_datadir();
189  dir = g_dir_open(remmina_data_dir, 0, NULL);
190 
191  if (dir) {
192  while ((name = g_dir_read_name(dir)) != NULL) {
193  if (!g_str_has_suffix(name, ".remmina"))
194  continue;
195  g_snprintf(filename, MAX_PATH_LEN, "%s/%s",
196  remmina_data_dir, name);
197  remminafile = remmina_file_load(filename);
198  if (remminafile) {
199  (*func)(remminafile, user_data);
200  remmina_file_free(remminafile);
201  items_count++;
202  }
203  }
204  g_dir_close(dir);
205  }
206  g_free(remmina_data_dir);
207  return items_count;
208 }
209 
211 {
212  TRACE_CALL(__func__);
213  gchar filename[MAX_PATH_LEN];
214  GDir *dir;
215  const gchar *name;
216  RemminaFile *remminafile;
217  RemminaStringArray *array;
218  const gchar *group;
219  gchar *groups;
220  gchar *remmina_data_dir;
221 
222  remmina_data_dir = remmina_file_get_datadir();
223  array = remmina_string_array_new();
224 
225  dir = g_dir_open(remmina_data_dir, 0, NULL);
226 
227  if (dir == NULL)
228  return 0;
229  while ((name = g_dir_read_name(dir)) != NULL) {
230  if (!g_str_has_suffix(name, ".remmina"))
231  continue;
232  g_snprintf(filename, MAX_PATH_LEN, "%s/%s", remmina_data_dir, name);
233  remminafile = remmina_file_load(filename);
234  if (remminafile) {
235  group = remmina_file_get_string(remminafile, "group");
236  if (group && remmina_string_array_find(array, group) < 0)
237  remmina_string_array_add(array, group);
238  remmina_file_free(remminafile);
239  }
240  }
241  g_dir_close(dir);
243  groups = remmina_string_array_to_string(array);
245  g_free(remmina_data_dir);
246  return groups;
247 }
248 
249 static void remmina_file_manager_add_group(GNode *node, const gchar *group)
250 {
251  TRACE_CALL(__func__);
252  gint cmp;
253  gchar *p1;
254  gchar *p2;
255  GNode *child;
256  gboolean found;
257  RemminaGroupData *data;
258 
259  if (node == NULL)
260  return;
261 
262  if (group == NULL || group[0] == '\0')
263  return;
264 
265  p1 = g_strdup(group);
266  p2 = strchr(p1, '/');
267 
268  if (p2)
269  *p2++ = '\0';
270 
271  found = FALSE;
272 
273  for (child = g_node_first_child(node); child; child = g_node_next_sibling(child)) {
274  cmp = g_strcmp0(((RemminaGroupData *)child->data)->name, p1);
275 
276  if (cmp == 0) {
277  found = TRUE;
278  break;
279  }
280 
281  if (cmp > 0)
282  break;
283  }
284 
285  if (!found) {
286  data = g_new0(RemminaGroupData, 1);
287  data->name = p1;
288  if (node->data)
289  data->group = g_strdup_printf("%s/%s", ((RemminaGroupData *)node->data)->group, p1);
290  else
291  data->group = g_strdup(p1);
292  if (child)
293  child = g_node_insert_data_before(node, child, data);
294  else
295  child = g_node_append_data(node, data);
296  }
298 
299  if (found)
300  g_free(p1);
301 }
302 
304 {
305  TRACE_CALL(__func__);
306  gchar filename[MAX_PATH_LEN];
307  GDir *dir;
308  g_autofree gchar *datadir = NULL;
309  const gchar *name;
310  RemminaFile *remminafile;
311  const gchar *group;
312  GNode *root;
313 
314  root = g_node_new(NULL);
315 
316  datadir = g_strdup(remmina_file_get_datadir());
317  dir = g_dir_open(datadir, 0, NULL);
318 
319  if (dir == NULL)
320  return root;
321  while ((name = g_dir_read_name(dir)) != NULL) {
322  if (!g_str_has_suffix(name, ".remmina"))
323  continue;
324  g_snprintf(filename, MAX_PATH_LEN, "%s/%s", datadir, name);
325  remminafile = remmina_file_load(filename);
326  if (remminafile) {
327  group = remmina_file_get_string(remminafile, "group");
328  remmina_file_manager_add_group(root, group);
329  remmina_file_free(remminafile);
330  }
331  }
332  g_dir_close(dir);
333  return root;
334 }
335 
337 {
338  TRACE_CALL(__func__);
339  RemminaGroupData *data;
340  GNode *child;
341 
342  if (!node)
343  return;
344  data = (RemminaGroupData *)node->data;
345  if (data) {
346  g_free(data->name);
347  g_free(data->group);
348  g_free(data);
349  node->data = NULL;
350  }
351  for (child = g_node_first_child(node); child; child = g_node_next_sibling(child))
353  g_node_unlink(node);
354 }
355 
357 {
358  TRACE_CALL(__func__);
359  RemminaFile *remminafile = NULL;
360  RemminaFilePlugin *plugin;
361  gchar *p;
362 
363  if ((p = strrchr(filename, '.')) != NULL && g_strcmp0(p + 1, "remmina") == 0) {
364  remminafile = remmina_file_load(filename);
365  } else {
367  if (plugin)
368  remminafile = plugin->import_func(plugin, filename);
369  }
370  return remminafile;
371 }
G_BEGIN_DECLS struct _RemminaGroupData RemminaGroupData
RemminaFile * remmina_file_load(const gchar *filename)
Definition: remmina_file.c:350
void remmina_file_free(RemminaFile *remminafile)
Definition: remmina_file.c:709
@@ -98,29 +98,29 @@ $(document).ready(function(){initNavTree('remmina__file__manager_8c_source.html'
typedefG_BEGIN_DECLS struct _RemminaFile RemminaFile
Definition: types.h:44
RemminaFile *(* import_func)(struct _RemminaFilePlugin *instance, const gchar *from_file)
Definition: plugin.h:108
-
void remmina_file_manager_free_group_tree(GNode *node)
+
void remmina_file_manager_free_group_tree(GNode *node)
RemminaFilePlugin * remmina_plugin_manager_get_import_file_handler(const gchar *file)
gint remmina_string_array_find(RemminaStringArray *array, const gchar *str)
gchar * remmina_string_array_to_string(RemminaStringArray *array)
node_t * node
Definition: remmina_ssh.c:142
static gboolean remmina_file_manager_do_copy(const char *src_path, const char *dst_path)
-
gchar * remmina_pref_get_value(const gchar *key)
+
gchar * remmina_pref_get_value(const gchar *key)
void remmina_file_manager_init(void)
It creates the Remmina data and cache folders.
void remmina_string_array_sort(RemminaStringArray *array)
-
static void remmina_file_manager_add_group(GNode *node, const gchar *group)
+
static void remmina_file_manager_add_group(GNode *node, const gchar *group)
void remmina_string_array_free(RemminaStringArray *array)
gchar * remmina_file_get_datadir(void)
Return datadir_path from pref or first found data dir as per XDG specs.
RemminaStringArray * remmina_string_array_new(void)
static gchar * cachedir
-
gchar * remmina_file_manager_get_groups(void)
-
RemminaFile * remmina_file_manager_load_file(const gchar *filename)
+
gchar * remmina_file_manager_get_groups(void)
+
RemminaFile * remmina_file_manager_load_file(const gchar *filename)
void remmina_string_array_add(RemminaStringArray *array, const gchar *str)
-
GNode * remmina_file_manager_get_group_tree(void)
-
gint remmina_file_manager_iterate(GFunc func, gpointer user_data)
+
GNode * remmina_file_manager_get_group_tree(void)
+
gint remmina_file_manager_iterate(GFunc func, gpointer user_data)
diff --git a/public/remmina__file__manager_8h.html b/public/remmina__file__manager_8h.html index d422b3f5b..38de5faa1 100644 --- a/public/remmina__file__manager_8h.html +++ b/public/remmina__file__manager_8h.html @@ -177,7 +177,7 @@ Functions
-

Definition at line 335 of file remmina_file_manager.c.

+

Definition at line 336 of file remmina_file_manager.c.

@@ -197,7 +197,7 @@ Functions
-

Definition at line 302 of file remmina_file_manager.c.

+

Definition at line 303 of file remmina_file_manager.c.

@@ -217,7 +217,7 @@ Functions
-

Definition at line 209 of file remmina_file_manager.c.

+

Definition at line 210 of file remmina_file_manager.c.

@@ -271,7 +271,7 @@ Functions
-

Definition at line 177 of file remmina_file_manager.c.

+

Definition at line 178 of file remmina_file_manager.c.

@@ -291,7 +291,7 @@ Functions
-

Definition at line 355 of file remmina_file_manager.c.

+

Definition at line 356 of file remmina_file_manager.c.

diff --git a/public/remmina__file__manager_8h_source.html b/public/remmina__file__manager_8h_source.html index be5e633e9..b5346ec9f 100644 --- a/public/remmina__file__manager_8h_source.html +++ b/public/remmina__file__manager_8h_source.html @@ -92,14 +92,14 @@ $(document).ready(function(){initNavTree('remmina__file__manager_8h_source.html'
gchar * labels
node_t * node
Definition: remmina_ssh.c:142
void remmina_file_manager_init(void)
It creates the Remmina data and cache folders.
-
void remmina_file_manager_free_group_tree(GNode *node)
-
RemminaFile * remmina_file_manager_load_file(const gchar *filename)
+
void remmina_file_manager_free_group_tree(GNode *node)
+
RemminaFile * remmina_file_manager_load_file(const gchar *filename)
gchar * remmina_file_get_datadir(void)
Return datadir_path from pref or first found data dir as per XDG specs.
-
gint remmina_file_manager_iterate(GFunc func, gpointer user_data)
+
gint remmina_file_manager_iterate(GFunc func, gpointer user_data)
-
gchar * remmina_file_manager_get_groups(void)
+
gchar * remmina_file_manager_get_groups(void)
gchar * name
-
GNode * remmina_file_manager_get_group_tree(void)
+
GNode * remmina_file_manager_get_group_tree(void)
gchar * group
diff --git a/public/remmina__icon_8c_source.html b/public/remmina__icon_8c_source.html index e678b7e9e..b086561f9 100644 --- a/public/remmina__icon_8c_source.html +++ b/public/remmina__icon_8c_source.html @@ -142,7 +142,7 @@ $(document).ready(function(){initNavTree('remmina__icon_8c_source.html','');});
-
gboolean remmina_pref_save(void)
Definition: remmina_pref.c:777
+
gboolean remmina_pref_save(void)
Definition: remmina_pref.c:778
gboolean remmina_sysinfo_is_appindicator_available()
gboolean applet_new_ontop
Definition: remmina_pref.h:162
static void remmina_icon_about(void)
Definition: remmina_icon.c:106
diff --git a/public/remmina__log_8c_source.html b/public/remmina__log_8c_source.html index 00f26b787..79d14ca21 100644 --- a/public/remmina__log_8c_source.html +++ b/public/remmina__log_8c_source.html @@ -106,7 +106,7 @@ $(document).ready(function(){initNavTree('remmina__log_8c_source.html','');});
Definition: remmina_log.c:62
-
gboolean remmina_pref_get_boolean(const gchar *key)
+
gboolean remmina_pref_get_boolean(const gchar *key)
static void remmina_log_window_init(RemminaLogWindow *logwin)
Definition: remmina_log.c:445
void _remmina_info(const gchar *fmt,...)
Definition: remmina_log.c:206
static gboolean remmina_log_on_keypress(GtkWidget *widget, GdkEvent *event, gpointer user_data)
Definition: remmina_log.c:426
diff --git a/public/remmina__main_8c_source.html b/public/remmina__main_8c_source.html index faa948a8b..0de01fd5a 100644 --- a/public/remmina__main_8c_source.html +++ b/public/remmina__main_8c_source.html @@ -134,7 +134,7 @@ $(document).ready(function(){initNavTree('remmina__main_8c_source.html','');});
gboolean remmina_network_monitor_status(RemminaMonitor *rm_monitor)
RemminaFilePlugin * remmina_plugin_manager_get_export_file_handler(RemminaFile *remminafile)
-
void remmina_file_manager_free_group_tree(GNode *node)
+
void remmina_file_manager_free_group_tree(GNode *node)
RemminaFilePlugin * remmina_plugin_manager_get_import_file_handler(const gchar *file)
static gboolean remmina_main_search_key_event(GtkWidget *search_entry, GdkEventKey *event, gpointer user_data)
Definition: remmina_main.c:870
@@ -155,7 +155,7 @@ $(document).ready(function(){initNavTree('remmina__main_8c_source.html','');});
void remmina_icon_populate_menu(void)
Definition: remmina_icon.c:250
void remmina_main_on_action_connection_delete_multiple(GSimpleAction *action, GVariant *param, gpointer data)
-
gchar * remmina_file_get_datetime(RemminaFile *remminafile)
Return the string date of the last time a Remmina state file has been modified.
+
gchar * remmina_file_get_datetime(RemminaFile *remminafile)
Return the string date of the last time a Remmina state file has been modified.
static void remmina_main_file_model_on_sort(GtkTreeSortable *sortable, gpointer user_data)
Definition: remmina_main.c:515
gint main_width
Definition: remmina_pref.h:217
GtkWidget * remmina_main_new(void)
@@ -212,7 +212,7 @@ $(document).ready(function(){initNavTree('remmina__main_8c_source.html','');});
void remmina_main_show_warning_dialog(const gchar *message)
void remmina_main_on_action_connection_new(GSimpleAction *action, GVariant *param, gpointer data)
Definition: remmina_main.c:851
void remmina_main_quick_search_enter(GtkWidget *widget, gpointer user_data)
-
void remmina_file_delete(const gchar *filename)
Definition: remmina_file.c:909
+
void remmina_file_delete(const gchar *filename)
Definition: remmina_file.c:911
GtkButton * button_new
Definition: remmina_main.h:60
GtkMenu * menu_popup_full
Definition: remmina_main.h:54
Definition: remmina_main.c:82
@@ -230,10 +230,10 @@ $(document).ready(function(){initNavTree('remmina__main_8c_source.html','');});
void remmina_main_on_action_connection_delete(GSimpleAction *action, GVariant *param, gpointer data)
Definition: remmina_main.c:977
static gboolean is_empty(const gchar *s)
RemminaStringArray * remmina_string_array_new_from_string(const gchar *strs)
-
gboolean remmina_pref_get_boolean(const gchar *key)
+
gboolean remmina_pref_get_boolean(const gchar *key)
gint view_file_mode
Definition: remmina_pref.h:213
RemminaStringArray * remmina_string_array_new(void)
-
void remmina_file_touch(RemminaFile *remminafile)
Update the atime and mtime of a given filename.
+
void remmina_file_touch(RemminaFile *remminafile)
Update the atime and mtime of a given filename.
GtkWidget * remmina_file_editor_new_from_filename(const gchar *filename)
Definition: remmina_main.c:79
static void remmina_main_save_expanded_group_func(GtkTreeView *tree_view, GtkTreePath *path, gpointer user_data)
Definition: remmina_main.c:150
@@ -269,7 +269,7 @@ $(document).ready(function(){initNavTree('remmina__main_8c_source.html','');});
Definition: remmina_main.c:77
gboolean connected
-
gboolean remmina_pref_save(void)
Definition: remmina_pref.c:777
+
gboolean remmina_pref_save(void)
Definition: remmina_pref.c:778
Definition: remmina_main.c:74
void remmina_main_on_action_connection_edit(GSimpleAction *action, GVariant *param, gpointer data)
Definition: remmina_main.c:946
GtkTreeModel * file_model_sort
Definition: remmina_main.h:92
@@ -283,7 +283,7 @@ $(document).ready(function(){initNavTree('remmina__main_8c_source.html','');});
void remmina_application_condexit(RemminaCondExitType why)
Definition: remmina_exec.c:123
void remmina_file_set_string(RemminaFile *remminafile, const gchar *setting, const gchar *value)
Definition: remmina_file.c:469
static char * quick_connect_plugin_list[]
Definition: remmina_main.c:131
-
void remmina_file_save(RemminaFile *remminafile)
Definition: remmina_file.c:728
+
void remmina_file_save(RemminaFile *remminafile)
Definition: remmina_file.c:730
GtkTreeViewColumn * column_files_list_notes
Definition: remmina_main.h:80
static gboolean remmina_main_quickconnect(void)
gboolean always_show_notes
Definition: remmina_pref.h:153
@@ -295,19 +295,19 @@ $(document).ready(function(){initNavTree('remmina__main_8c_source.html','');});
void remmina_main_on_action_application_quit(GSimpleAction *action, GVariant *param, gpointer data)
GtkEntry * entry_quick_connect_server
Definition: remmina_main.h:71
gint remmina_unlock_new(GtkWindow *parent)
-
const gchar * remmina_file_get_icon_name(RemminaFile *remminafile)
Definition: remmina_file.c:883
+
const gchar * remmina_file_get_icon_name(RemminaFile *remminafile)
Definition: remmina_file.c:885
void remmina_mpchange_schedule(gboolean has_domain, const gchar *group, const gchar *domain, const gchar *username, const gchar *password, const gchar *gatewayusername, const gchar *gatewaydomain, const gchar *gatewaypassword)
gint main_height
Definition: remmina_pref.h:218
GtkWidget * remmina_pref_dialog_new(gint default_tab, GtkWindow *parent)
-
GNode * remmina_file_manager_get_group_tree(void)
+
GNode * remmina_file_manager_get_group_tree(void)
void remmina_main_on_action_search_toggle(GSimpleAction *action, GVariant *param, gpointer data)
gboolean override_view_file_mode_to_list
Definition: remmina_main.h:98
void remmina_main_on_action_tools_export(GSimpleAction *action, GVariant *param, gpointer data)
static void remmina_main_file_editor_destroy(GtkWidget *widget, gpointer user_data)
Definition: remmina_main.c:805
-
gint remmina_file_manager_iterate(GFunc func, gpointer user_data)
+
gint remmina_file_manager_iterate(GFunc func, gpointer user_data)
gboolean dark_theme
Definition: remmina_pref.h:149
Definition: remmina_pref.h:60
static void remmina_main_expand_group(void)
Definition: remmina_main.c:446
diff --git a/public/remmina__mpchange_8c_source.html b/public/remmina__mpchange_8c_source.html index 9f34cd8a4..5d47cb401 100644 --- a/public/remmina__mpchange_8c_source.html +++ b/public/remmina__mpchange_8c_source.html @@ -132,7 +132,7 @@ $(document).ready(function(){initNavTree('remmina__mpchange_8c_source.html','');
gchar * group
gchar * gatewaydomain
-
void remmina_file_store_secret_plugin_password(RemminaFile *remminafile, const gchar *key, const gchar *value)
Definition: remmina_file.c:844
+
void remmina_file_store_secret_plugin_password(RemminaFile *remminafile, const gchar *key, const gchar *value)
Definition: remmina_file.c:846
GtkListStore * store
static void remmina_mpchange_dochange_clicked(GtkButton *btn, gpointer user_data)
@@ -148,7 +148,7 @@ $(document).ready(function(){initNavTree('remmina__mpchange_8c_source.html','');
static gboolean changenext(gpointer user_data)
GtkEntry * ePassword2
-
gint remmina_file_manager_iterate(GFunc func, gpointer user_data)
+
gint remmina_file_manager_iterate(GFunc func, gpointer user_data)
diff --git a/public/remmina__plugin__manager_8c_source.html b/public/remmina__plugin__manager_8c_source.html index d08b9a7f0..1eed65f04 100644 --- a/public/remmina__plugin__manager_8c_source.html +++ b/public/remmina__plugin__manager_8c_source.html @@ -94,7 +94,7 @@ $(document).ready(function(){initNavTree('remmina__plugin__manager_8c_source.htm
void remmina_protocol_widget_set_error(RemminaProtocolWidget *gp, const gchar *fmt,...)
Definition: plugin.h:56
gboolean remmina_plugin_manager_is_encrypted_setting(RemminaProtocolPlugin *pp, const char *setting)
-
gint remmina_pref_get_scale_quality(void)
+
gint remmina_pref_get_scale_quality(void)
const gchar * remmina_file_get_string(RemminaFile *remminafile, const gchar *setting)
Definition: remmina_file.c:516
void remmina_protocol_widget_panel_hide(RemminaProtocolWidget *gp)
@@ -107,7 +107,7 @@ $(document).ready(function(){initNavTree('remmina__plugin__manager_8c_source.htm
gboolean remmina_plugin_native_load(RemminaPluginService *service, const char *name)
gboolean remmina_plugin_manager_loader_supported(const char *filetype)
gint remmina_protocol_widget_get_profile_remote_width(RemminaProtocolWidget *gp)
-
gint remmina_pref_get_sshtunnel_port(void)
+
gint remmina_pref_get_sshtunnel_port(void)
gint remmina_protocol_widget_panel_auth(RemminaProtocolWidget *gp, RemminaMessagePanelFlags pflags, const gchar *title, const gchar *default_username, const gchar *default_password, const gchar *default_domain, const gchar *password_prompt)
Definition: plugin.h:53
@@ -134,7 +134,7 @@ $(document).ready(function(){initNavTree('remmina__plugin__manager_8c_source.htm
int init_order
Definition: plugin.h:141
gchar * remmina_file_get_secret(RemminaFile *remminafile, const gchar *setting)
Definition: remmina_file.c:551
-
gint remmina_pref_get_ssh_loglevel(void)
+
gint remmina_pref_get_ssh_loglevel(void)
Definition: plugin.h:47
const RemminaProtocolFeature * features
Definition: plugin.h:77
RemminaFilePlugin * remmina_plugin_manager_get_export_file_handler(RemminaFile *remminafile)
@@ -150,7 +150,7 @@ $(document).ready(function(){initNavTree('remmina__plugin__manager_8c_source.htm
RemminaScaleMode remmina_protocol_widget_get_current_scale_mode(RemminaProtocolWidget *gp)
void remmina_protocol_widget_update_align(RemminaProtocolWidget *gp)
gint remmina_protocol_widget_panel_authx509(RemminaProtocolWidget *gp)
-
void remmina_pref_set_value(const gchar *key, const gchar *value)
+
void remmina_pref_set_value(const gchar *key, const gchar *value)
Definition: plugin.h:65
const gchar * description
Definition: plugin.h:59
const gchar * version
Definition: plugin.h:61
@@ -160,16 +160,16 @@ $(document).ready(function(){initNavTree('remmina__plugin__manager_8c_source.htm
void remmina_protocol_widget_set_display(RemminaProtocolWidget *gp, gint display)
void remmina_protocol_widget_set_width(RemminaProtocolWidget *gp, gint width)
static gboolean remmina_plugin_manager_show_for_each(RemminaPlugin *plugin, GtkListStore *store)
-
gchar * remmina_pref_get_value(const gchar *key)
+
gchar * remmina_pref_get_value(const gchar *key)
Definition: plugin.h:135
-
gboolean remmina_pref_get_ssh_parseconfig(void)
+
gboolean remmina_pref_get_ssh_parseconfig(void)
const gchar * remmina_protocol_widget_get_name(RemminaProtocolWidget *gp)
const char * get_filename_ext(const char *filename)
void remmina_protocol_widget_panel_show_listen(RemminaProtocolWidget *gp, gint port)
void remmina_plugin_manager_show(GtkWindow *parent)
gboolean remmina_masterthread_exec_is_main_thread()
-
guint * remmina_pref_keymap_get_table(const gchar *keymap)
+
guint * remmina_pref_keymap_get_table(const gchar *keymap)
void remmina_protocol_widget_signal_connection_closed(RemminaProtocolWidget *gp)
RemminaPluginService remmina_plugin_manager_service
static const gchar * remmina_plugin_type_name[]
@@ -202,7 +202,7 @@ $(document).ready(function(){initNavTree('remmina__plugin__manager_8c_source.htm
Definition: types.h:116
Definition: types.h:102
RemminaFile * remmina_file_new(void)
Definition: remmina_file.c:93
-
guint remmina_pref_keymap_get_keyval(const gchar *keymap, guint keyval)
+
guint remmina_pref_keymap_get_keyval(const gchar *keymap, guint keyval)
gboolean remmina_protocol_widget_is_closed(RemminaProtocolWidget *gp)
gchar * remmina_protocol_widget_get_clientkey(RemminaProtocolWidget *gp)
@@ -231,7 +231,7 @@ $(document).ready(function(){initNavTree('remmina__plugin__manager_8c_source.htm
void remmina_log_print(const gchar *text)
Definition: remmina_log.c:197
void _remmina_message(const gchar *fmt,...)
Definition: remmina_log.c:230
Definition: types.h:98
-
void remmina_file_unsave_passwords(RemminaFile *remminafile)
Definition: remmina_file.c:976
+
void remmina_file_unsave_passwords(RemminaFile *remminafile)
Definition: remmina_file.c:978
void remmina_protocol_widget_chat_close(RemminaProtocolWidget *gp)
void remmina_public_get_server_port(const gchar *server, gint defaultport, gchar **host, gint *port)
diff --git a/public/remmina__pref_8c.html b/public/remmina__pref_8c.html index 0b187650f..1f869d5ba 100644 --- a/public/remmina__pref_8c.html +++ b/public/remmina__pref_8c.html @@ -185,7 +185,7 @@ Variables
-

Definition at line 928 of file remmina_pref.c.

+

Definition at line 929 of file remmina_pref.c.

@@ -205,7 +205,7 @@ Variables
-

Definition at line 985 of file remmina_pref.c.

+

Definition at line 986 of file remmina_pref.c.

@@ -322,7 +322,7 @@ Variables
-

Definition at line 1150 of file remmina_pref.c.

+

Definition at line 1151 of file remmina_pref.c.

@@ -370,7 +370,7 @@ Variables
-

Definition at line 966 of file remmina_pref.c.

+

Definition at line 967 of file remmina_pref.c.

@@ -390,7 +390,7 @@ Variables
-

Definition at line 1063 of file remmina_pref.c.

+

Definition at line 1064 of file remmina_pref.c.

@@ -410,7 +410,7 @@ Variables
-

Definition at line 1072 of file remmina_pref.c.

+

Definition at line 1073 of file remmina_pref.c.

@@ -430,7 +430,7 @@ Variables
-

Definition at line 1078 of file remmina_pref.c.

+

Definition at line 1079 of file remmina_pref.c.

@@ -450,7 +450,7 @@ Variables
-

Definition at line 1102 of file remmina_pref.c.

+

Definition at line 1103 of file remmina_pref.c.

@@ -470,7 +470,7 @@ Variables
-

Definition at line 1090 of file remmina_pref.c.

+

Definition at line 1091 of file remmina_pref.c.

@@ -490,7 +490,7 @@ Variables
-

Definition at line 1096 of file remmina_pref.c.

+

Definition at line 1097 of file remmina_pref.c.

@@ -510,7 +510,7 @@ Variables
-

Definition at line 1108 of file remmina_pref.c.

+

Definition at line 1109 of file remmina_pref.c.

@@ -530,7 +530,7 @@ Variables
-

Definition at line 1084 of file remmina_pref.c.

+

Definition at line 1085 of file remmina_pref.c.

@@ -550,7 +550,7 @@ Variables
-

Definition at line 1136 of file remmina_pref.c.

+

Definition at line 1137 of file remmina_pref.c.

@@ -618,7 +618,7 @@ Variables
-

Definition at line 767 of file remmina_pref.c.

+

Definition at line 768 of file remmina_pref.c.

@@ -648,7 +648,7 @@ Variables
-

Definition at line 1021 of file remmina_pref.c.

+

Definition at line 1022 of file remmina_pref.c.

@@ -668,7 +668,7 @@ Variables
-

Definition at line 1011 of file remmina_pref.c.

+

Definition at line 1012 of file remmina_pref.c.

@@ -688,7 +688,7 @@ Variables
-

Definition at line 1040 of file remmina_pref.c.

+

Definition at line 1041 of file remmina_pref.c.

@@ -708,7 +708,7 @@ Variables
-

Definition at line 777 of file remmina_pref.c.

+

Definition at line 778 of file remmina_pref.c.

@@ -738,7 +738,7 @@ Variables
-

Definition at line 1114 of file remmina_pref.c.

+

Definition at line 1115 of file remmina_pref.c.

diff --git a/public/remmina__pref_8c_source.html b/public/remmina__pref_8c_source.html index 92d76808d..4d23cbd4e 100644 --- a/public/remmina__pref_8c_source.html +++ b/public/remmina__pref_8c_source.html @@ -86,17 +86,17 @@ $(document).ready(function(){initNavTree('remmina__pref_8c_source.html','');});
remmina_pref.c
-Go to the documentation of this file.
1 /*
2  * Remmina - The GTK+ Remote Desktop Client
3  * Copyright (C) 2009-2011 Vic Lee
4  * Copyright (C) 2014-2015 Antenore Gatta, Fabio Castelli, Giovanni Panozzo
5  * Copyright (C) 2016-2022 Antenore Gatta, Giovanni Panozzo
6  * Copyright (C) 2022-2023 Antenore Gatta, Giovanni Panozzo, Hiroyuki Tanaka
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor,
21  * Boston, MA 02110-1301, USA.
22  *
23  * In addition, as a special exception, the copyright holders give
24  * permission to link the code of portions of this program with the
25  * OpenSSL library under certain conditions as described in each
26  * individual source file, and distribute linked combinations
27  * including the two.
28  * You must obey the GNU General Public License in all respects
29  * for all of the code used other than OpenSSL. * If you modify
30  * file(s) with this exception, you may extend this exception to your
31  * version of the file(s), but you are not obligated to do so. * If you
32  * do not wish to do so, delete this exception statement from your
33  * version. * If you delete this exception statement from all source
34  * files in the program, then also delete it here.
35  *
36  */
37 
38 #include "config.h"
39 
40 #include <stdlib.h>
41 #include <string.h>
42 #include <unistd.h>
43 #include <sys/time.h>
44 #include <sys/utsname.h>
45 
46 #include <glib/gstdio.h>
47 #include <gdk/gdkkeysyms.h>
48 #include <gtk/gtk.h>
49 
50 #include "remmina_sodium.h"
51 
52 #include "remmina_public.h"
53 #include "remmina_string_array.h"
54 #include "remmina_pref.h"
55 #include "remmina_log.h"
57 
58 const gchar *default_resolutions = "640x480,800x600,1024x768,1152x864,1280x960,1400x1050,1920x1080";
59 const gchar *default_keystrokes = "Send hello world§hello world\\n";
60 
62 static GHashTable *remmina_keymap_table = NULL;
63 
64 /* We could customize this further if there are more requirements */
65 static const gchar *default_keymap_data = "# Please check gdk/gdkkeysyms.h for a full list of all key names or hex key values\n"
66  "\n"
67  "[Map Meta Keys]\n"
68  "Super_L = Meta_L\n"
69  "Super_R = Meta_R\n"
70  "Meta_L = Super_L\n"
71  "Meta_R = Super_R\n";
72 
73 static void remmina_pref_gen_secret(void)
74 {
75  TRACE_CALL(__func__);
76  guchar s[32];
77  gint i;
78  GKeyFile *gkeyfile;
79  g_autofree gchar *content = NULL;
80  gsize length;
81 
82  for (i = 0; i < 32; i++)
83  s[i] = (guchar)(randombytes_uniform(257));
84  remmina_pref.secret = g_base64_encode(s, 32);
85 
86  gkeyfile = g_key_file_new();
87  g_key_file_load_from_file(gkeyfile, remmina_pref_file, G_KEY_FILE_NONE, NULL);
88  g_key_file_set_string(gkeyfile, "remmina_pref", "secret", remmina_pref.secret);
89  content = g_key_file_to_data(gkeyfile, &length, NULL);
90  g_file_set_contents(remmina_pref_file, content, length, NULL);
91 
92  g_key_file_free(gkeyfile);
93 }
94 
95 static guint remmina_pref_get_keyval_from_str(const gchar *str)
96 {
97  TRACE_CALL(__func__);
98  guint k;
99 
100  if (!str)
101  return 0;
102 
103  k = gdk_keyval_from_name(str);
104  if (!k)
105  if (sscanf(str, "%x", &k) < 1)
106  k = 0;
107  return k;
108 }
109 
110 static void remmina_pref_init_keymap(void)
111 {
112  TRACE_CALL(__func__);
113  GKeyFile *gkeyfile;
114  gchar **groups;
115  gchar **gptr;
116  gchar **keys;
117  gchar **kptr;
118  gsize nkeys;
119  g_autofree gchar *value = NULL;
120  guint *table;
121  guint *tableptr;
122  guint k1, k2;
123 
125  g_hash_table_destroy(remmina_keymap_table);
126  remmina_keymap_table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
127 
128  gkeyfile = g_key_file_new();
129  if (!g_key_file_load_from_file(gkeyfile, remmina_keymap_file, G_KEY_FILE_NONE, NULL)) {
130  if (!g_key_file_load_from_data(gkeyfile, default_keymap_data, strlen(default_keymap_data), G_KEY_FILE_NONE,
131  NULL)) {
132  g_print("Failed to initialize keymap table\n");
133  g_key_file_free(gkeyfile);
134  return;
135  }
136  }
137 
138  groups = g_key_file_get_groups(gkeyfile, NULL);
139  gptr = groups;
140  while (*gptr) {
141  keys = g_key_file_get_keys(gkeyfile, *gptr, &nkeys, NULL);
142  table = g_new0(guint, nkeys * 2 + 1);
143  g_hash_table_insert(remmina_keymap_table, g_strdup(*gptr), table);
144 
145  kptr = keys;
146  tableptr = table;
147  while (*kptr) {
149  if (k1) {
150  value = g_key_file_get_string(gkeyfile, *gptr, *kptr, NULL);
152  *tableptr++ = k1;
153  *tableptr++ = k2;
154  }
155  kptr++;
156  }
157  g_strfreev(keys);
158  gptr++;
159  }
160  g_strfreev(groups);
161  g_key_file_free(gkeyfile);
162 }
163 
165 static gboolean remmina_pref_file_do_copy(const char *src_path, const char *dst_path)
166 {
167  GFile *src = g_file_new_for_path(src_path), *dst = g_file_new_for_path(dst_path);
168  /* We don’t overwrite the target if it exists, because overwrite is not set */
169  const gboolean ok = g_file_copy(src, dst, G_FILE_COPY_NONE, NULL, NULL, NULL, NULL);
170 
171  g_object_unref(dst);
172  g_object_unref(src);
173 
174  return ok;
175 }
176 
177 void remmina_pref_file_load_colors(GKeyFile *gkeyfile, RemminaColorPref *color_pref)
178 {
179  const struct {
180  const char * name;
181  char ** setting;
182  char * fallback;
183  } colors[] = {
184  { "background", &color_pref->background, "#d5ccba" },
185  { "cursor", &color_pref->cursor, "#45373c" },
186  { "cursor_foreground", &color_pref->cursor_foreground, "#d5ccba" },
187  { "highlight", &color_pref->highlight, "#45373c" },
188  { "highlight_foreground", &color_pref->highlight_foreground, "#d5ccba" },
189  { "colorBD", &color_pref->colorBD, "#45373c" },
190  { "foreground", &color_pref->foreground, "#45373c" },
191  { "color0", &color_pref->color0, "#20111b" },
192  { "color1", &color_pref->color1, "#be100e" },
193  { "color2", &color_pref->color2, "#858162" },
194  { "color3", &color_pref->color3, "#eaa549" },
195  { "color4", &color_pref->color4, "#426a79" },
196  { "color5", &color_pref->color5, "#97522c" },
197  { "color6", &color_pref->color6, "#989a9c" },
198  { "color7", &color_pref->color7, "#968c83" },
199  { "color8", &color_pref->color8, "#5e5252" },
200  { "color9", &color_pref->color9, "#be100e" },
201  { "color10", &color_pref->color10, "#858162" },
202  { "color11", &color_pref->color11, "#eaa549" },
203  { "color12", &color_pref->color12, "#426a79" },
204  { "color13", &color_pref->color13, "#97522c" },
205  { "color14", &color_pref->color14, "#989a9c" },
206  { "color15", &color_pref->color15, "#d5ccba" },
207  };
208 
209  int i;
210 
211  for (i = 0; i < (sizeof(colors) / sizeof(colors[0])); i++) {
212  if (g_key_file_has_key(gkeyfile, "ssh_colors", colors[i].name, NULL))
213  *colors[i].setting = g_key_file_get_string(gkeyfile, "ssh_colors", colors[i].name,
214  NULL);
215  else
216  *colors[i].setting = colors[i].fallback;
217  }
218 }
219 
221 {
222  TRACE_CALL(__func__);
223  GKeyFile *gkeyfile;
224  gchar *remmina_dir;
225  const gchar *filename = "remmina.pref";
226  const gchar *colors_filename = "remmina.colors";
227  g_autofree gchar *remmina_colors_file = NULL;
228  GDir *dir;
229  const gchar *legacy = ".remmina";
230  int i;
231 
232  remmina_dir = g_build_path("/", g_get_user_config_dir(), "remmina", NULL);
233  /* Create the XDG_CONFIG_HOME directory */
234  g_mkdir_with_parents(remmina_dir, 0750);
235 
236  g_free(remmina_dir), remmina_dir = NULL;
237  /* Legacy ~/.remmina we copy the existing remmina.pref file inside
238  * XDG_CONFIG_HOME */
239  remmina_dir = g_build_path("/", g_get_home_dir(), legacy, NULL);
240  if (g_file_test(remmina_dir, G_FILE_TEST_IS_DIR)) {
241  dir = g_dir_open(remmina_dir, 0, NULL);
243  g_build_path("/", remmina_dir, filename, NULL),
244  g_build_path("/", g_get_user_config_dir(),
245  "remmina", filename, NULL));
246  }
247 
248  /* /usr/local/etc/remmina */
249  const gchar *const *dirs = g_get_system_config_dirs();
250 
251  g_free(remmina_dir), remmina_dir = NULL;
252  for (i = 0; dirs[i] != NULL; ++i) {
253  remmina_dir = g_build_path("/", dirs[i], "remmina", NULL);
254  if (g_file_test(remmina_dir, G_FILE_TEST_IS_DIR)) {
255  dir = g_dir_open(remmina_dir, 0, NULL);
256  while ((filename = g_dir_read_name(dir)) != NULL) {
258  g_build_path("/", remmina_dir, filename, NULL),
259  g_build_path("/", g_get_user_config_dir(),
260  "remmina", filename, NULL));
261  }
262  g_free(remmina_dir), remmina_dir = NULL;
263  }
264  }
265 
266  /* The last case we use the home ~/.config/remmina */
267  if (remmina_dir != NULL)
268  g_free(remmina_dir), remmina_dir = NULL;
269  remmina_dir = g_build_path("/", g_get_user_config_dir(),
270  "remmina", NULL);
271 
272  remmina_pref_file = g_strdup_printf("%s/remmina.pref", remmina_dir);
273  /* remmina.colors */
274  remmina_colors_file = g_strdup_printf("%s/%s", remmina_dir, colors_filename);
275 
276  remmina_keymap_file = g_strdup_printf("%s/remmina.keymap", remmina_dir);
277 
278  gkeyfile = g_key_file_new();
279 
280  g_key_file_load_from_file(gkeyfile, remmina_pref_file, G_KEY_FILE_NONE, NULL);
281 
282  if (g_key_file_has_key(gkeyfile, "remmina_pref", "save_view_mode", NULL))
283  remmina_pref.save_view_mode = g_key_file_get_boolean(gkeyfile, "remmina_pref", "save_view_mode", NULL);
284  else
286 
287  if (g_key_file_has_key(gkeyfile, "remmina_pref", "confirm_close", NULL))
288  remmina_pref.confirm_close = g_key_file_get_boolean(gkeyfile, "remmina_pref", "confirm_close", NULL);
289  else
291 
292  if (extrahardening)
293  remmina_pref.confirm_close = FALSE;
294 
295  if (g_key_file_has_key(gkeyfile, "remmina_pref", "use_master_password", NULL)) {
296  remmina_pref.use_primary_password = g_key_file_get_boolean(gkeyfile, "remmina_pref", "use_master_password", NULL);
297  } else if (g_key_file_has_key(gkeyfile, "remmina_pref", "use_primary_password", NULL))
298  remmina_pref.use_primary_password = g_key_file_get_boolean(gkeyfile, "remmina_pref", "use_primary_password", NULL);
299  else
301 
302  if (g_key_file_has_key(gkeyfile, "remmina_pref", "unlock_timeout", NULL))
303  remmina_pref.unlock_timeout = g_key_file_get_integer(gkeyfile, "remmina_pref", "unlock_timeout", NULL);
304  else
306 
307  if (g_key_file_has_key(gkeyfile, "remmina_pref", "unlock_password", NULL))
308  remmina_pref.unlock_password = g_key_file_get_string(gkeyfile, "remmina_pref", "unlock_password", NULL);
309  else
310  remmina_pref.unlock_password = g_strdup("");
311 
312  if (g_key_file_has_key(gkeyfile, "remmina_pref", "lock_connect", NULL))
313  remmina_pref.lock_connect = g_key_file_get_boolean(gkeyfile, "remmina_pref", "lock_connect", NULL);
314  else
315  remmina_pref.lock_connect = FALSE;
316 
317  if (g_key_file_has_key(gkeyfile, "remmina_pref", "lock_edit", NULL))
318  remmina_pref.lock_edit = g_key_file_get_boolean(gkeyfile, "remmina_pref", "lock_edit", NULL);
319  else
320  remmina_pref.lock_edit = FALSE;
321 
322 
323  if (g_key_file_has_key(gkeyfile, "remmina_pref", "lock_view_passwords", NULL))
324  remmina_pref.lock_view_passwords = g_key_file_get_boolean(gkeyfile, "remmina_pref", "lock_view_passwords", NULL);
325  else
327 
328  if (g_key_file_has_key(gkeyfile, "remmina_pref", "enc_mode", NULL))
329  remmina_pref.enc_mode = g_key_file_get_integer(gkeyfile, "remmina_pref", "enc_mode", NULL);
330  else
332 
333  if (g_key_file_has_key(gkeyfile, "remmina_pref", "audit", NULL))
334  remmina_pref.audit = g_key_file_get_boolean(gkeyfile, "remmina_pref", "audit", NULL);
335  else
336  remmina_pref.audit = FALSE;
337 
338  if (g_key_file_has_key(gkeyfile, "remmina_pref", "trust_all", NULL))
339  remmina_pref.trust_all = g_key_file_get_boolean(gkeyfile, "remmina_pref", "trust_all", NULL);
340  else
341  remmina_pref.trust_all = FALSE;
342 
343  if (g_key_file_has_key(gkeyfile, "remmina_pref", "fullscreen_on_auto", NULL))
344  remmina_pref.fullscreen_on_auto = g_key_file_get_boolean(gkeyfile, "remmina_pref", "fullscreen_on_auto", NULL);
345  else
347 
348  if (g_key_file_has_key(gkeyfile, "remmina_pref", "floating_toolbar_placement", NULL))
349  remmina_pref.floating_toolbar_placement = g_key_file_get_integer(gkeyfile, "remmina_pref", "floating_toolbar_placement", NULL);
350  else
352 
353  if (g_key_file_has_key(gkeyfile, "remmina_pref", "prevent_snap_welcome_message", NULL))
354  remmina_pref.prevent_snap_welcome_message = g_key_file_get_boolean(gkeyfile, "remmina_pref", "prevent_snap_welcome_message", NULL);
355  else
357 
358  if (g_key_file_has_key(gkeyfile, "remmina_pref", "last_quickconnect_protocol", NULL))
359  remmina_pref.last_quickconnect_protocol = g_key_file_get_string(gkeyfile, "remmina_pref", "last_quickconnect_protocol", NULL);
360  else
362 
363  if (g_key_file_has_key(gkeyfile, "remmina_pref", "toolbar_placement", NULL))
364  remmina_pref.toolbar_placement = g_key_file_get_integer(gkeyfile, "remmina_pref", "toolbar_placement", NULL);
365  else
367 
368  if (g_key_file_has_key(gkeyfile, "remmina_pref", "always_show_tab", NULL))
369  remmina_pref.always_show_tab = g_key_file_get_boolean(gkeyfile, "remmina_pref", "always_show_tab", NULL);
370  else
372 
373  if (extrahardening)
375 
376  if (g_key_file_has_key(gkeyfile, "remmina_pref", "always_show_notes", NULL))
377  remmina_pref.always_show_notes = g_key_file_get_boolean(gkeyfile, "remmina_pref", "always_show_notes", NULL);
378  else
380 
381  if (g_key_file_has_key(gkeyfile, "remmina_pref", "hide_connection_toolbar", NULL))
382  remmina_pref.hide_connection_toolbar = g_key_file_get_boolean(gkeyfile, "remmina_pref",
383  "hide_connection_toolbar", NULL);
384  else
386 
387  if (disabletoolbar)
389 
390  if (g_key_file_has_key(gkeyfile, "remmina_pref", "hide_searchbar", NULL))
391  remmina_pref.hide_searchbar = g_key_file_get_boolean(gkeyfile, "remmina_pref",
392  "hide_searchbar", NULL);
393  else
395 
396  if (extrahardening)
398 
399  if (g_key_file_has_key(gkeyfile, "remmina_pref", "default_action", NULL))
400  remmina_pref.default_action = g_key_file_get_integer(gkeyfile, "remmina_pref", "default_action", NULL);
401  else
403 
404  if (g_key_file_has_key(gkeyfile, "remmina_pref", "scale_quality", NULL))
405  remmina_pref.scale_quality = g_key_file_get_integer(gkeyfile, "remmina_pref", "scale_quality", NULL);
406  else
407  remmina_pref.scale_quality = GDK_INTERP_HYPER;
408 
409  if (g_key_file_has_key(gkeyfile, "remmina_pref", "hide_toolbar", NULL))
410  remmina_pref.hide_toolbar = g_key_file_get_boolean(gkeyfile, "remmina_pref", "hide_toolbar", NULL);
411  else
412  remmina_pref.hide_toolbar = FALSE;
413 
414  if (g_key_file_has_key(gkeyfile, "remmina_pref", "small_toolbutton", NULL))
415  remmina_pref.small_toolbutton = g_key_file_get_boolean(gkeyfile, "remmina_pref", "small_toolbutton", NULL);
416  else
418 
419  if (g_key_file_has_key(gkeyfile, "remmina_pref", "view_file_mode", NULL))
420  remmina_pref.view_file_mode = g_key_file_get_integer(gkeyfile, "remmina_pref", "view_file_mode", NULL);
421  else
423 
424  if (g_key_file_has_key(gkeyfile, "remmina_pref", "resolutions", NULL))
425  remmina_pref.resolutions = g_key_file_get_string(gkeyfile, "remmina_pref", "resolutions", NULL);
426  else
428 
429  if (g_key_file_has_key(gkeyfile, "remmina_pref", "keystrokes", NULL))
430  remmina_pref.keystrokes = g_key_file_get_string(gkeyfile, "remmina_pref", "keystrokes", NULL);
431  else
433 
434  if (g_key_file_has_key(gkeyfile, "remmina_pref", "main_width", NULL))
435  remmina_pref.main_width = MAX(600, g_key_file_get_integer(gkeyfile, "remmina_pref", "main_width", NULL));
436  else
437  remmina_pref.main_width = 600;
438 
439  if (g_key_file_has_key(gkeyfile, "remmina_pref", "main_height", NULL))
440  remmina_pref.main_height = MAX(400, g_key_file_get_integer(gkeyfile, "remmina_pref", "main_height", NULL));
441  else
443 
444  if (g_key_file_has_key(gkeyfile, "remmina_pref", "main_maximize", NULL))
445  remmina_pref.main_maximize = g_key_file_get_boolean(gkeyfile, "remmina_pref", "main_maximize", NULL);
446  else
447  remmina_pref.main_maximize = FALSE;
448 
449  if (g_key_file_has_key(gkeyfile, "remmina_pref", "main_sort_column_id", NULL))
450  remmina_pref.main_sort_column_id = g_key_file_get_integer(gkeyfile, "remmina_pref", "main_sort_column_id",
451  NULL);
452  else
454 
455  if (g_key_file_has_key(gkeyfile, "remmina_pref", "main_sort_order", NULL))
456  remmina_pref.main_sort_order = g_key_file_get_integer(gkeyfile, "remmina_pref", "main_sort_order", NULL);
457  else
459 
460  if (g_key_file_has_key(gkeyfile, "remmina_pref", "expanded_group", NULL))
461  remmina_pref.expanded_group = g_key_file_get_string(gkeyfile, "remmina_pref", "expanded_group", NULL);
462  else
463  remmina_pref.expanded_group = g_strdup("");
464 
465  if (g_key_file_has_key(gkeyfile, "remmina_pref", "toolbar_pin_down", NULL))
466  remmina_pref.toolbar_pin_down = g_key_file_get_boolean(gkeyfile, "remmina_pref", "toolbar_pin_down", NULL);
467  else
469 
470  if (g_key_file_has_key(gkeyfile, "remmina_pref", "ssh_loglevel", NULL))
471  remmina_pref.ssh_loglevel = g_key_file_get_integer(gkeyfile, "remmina_pref", "ssh_loglevel", NULL);
472  else
473  remmina_pref.ssh_loglevel = DEFAULT_SSH_LOGLEVEL;
474 
475  if (g_key_file_has_key(gkeyfile, "remmina_pref", "deny_screenshot_clipboard", NULL))
476  remmina_pref.deny_screenshot_clipboard = g_key_file_get_boolean(gkeyfile, "remmina_pref", "deny_screenshot_clipboard", NULL);
477  else
479 
480  if (g_key_file_has_key(gkeyfile, "remmina_pref", "datadir_path", NULL))
481  remmina_pref.datadir_path = g_key_file_get_string(gkeyfile, "remmina_pref", "datadir_path", NULL);
482  else
483  remmina_pref.datadir_path = g_strdup("");
484 
485  if (g_key_file_has_key(gkeyfile, "remmina_pref", "remmina_file_name", NULL))
486  remmina_pref.remmina_file_name = g_key_file_get_string(gkeyfile, "remmina_pref", "remmina_file_name", NULL);
487  else
488  remmina_pref.remmina_file_name = g_strdup("%G_%P_%N_%h");
489 
490  if (g_key_file_has_key(gkeyfile, "remmina_pref", "screenshot_path", NULL)) {
491  remmina_pref.screenshot_path = g_key_file_get_string(gkeyfile, "remmina_pref", "screenshot_path", NULL);
492  } else {
493  remmina_pref.screenshot_path = g_get_user_special_dir(G_USER_DIRECTORY_PICTURES);
494  if (remmina_pref.screenshot_path == NULL)
495  remmina_pref.screenshot_path = g_get_home_dir();
496  }
497 
498  if (g_key_file_has_key(gkeyfile, "remmina_pref", "screenshot_name", NULL))
499  remmina_pref.screenshot_name = g_key_file_get_string(gkeyfile, "remmina_pref", "screenshot_name", NULL);
500  else
501  remmina_pref.screenshot_name = g_strdup("remmina_%p_%h_%Y%m%d-%H%M%S");
502 
503  if (g_key_file_has_key(gkeyfile, "remmina_pref", "ssh_parseconfig", NULL))
504  remmina_pref.ssh_parseconfig = g_key_file_get_boolean(gkeyfile, "remmina_pref", "ssh_parseconfig", NULL);
505  else
506  remmina_pref.ssh_parseconfig = DEFAULT_SSH_PARSECONFIG;
507 
508  if (g_key_file_has_key(gkeyfile, "remmina_pref", "sshtunnel_port", NULL))
509  remmina_pref.sshtunnel_port = g_key_file_get_integer(gkeyfile, "remmina_pref", "sshtunnel_port", NULL);
510  else
511  remmina_pref.sshtunnel_port = DEFAULT_SSHTUNNEL_PORT;
512 
513  if (g_key_file_has_key(gkeyfile, "remmina_pref", "ssh_tcp_keepidle", NULL))
514  remmina_pref.ssh_tcp_keepidle = g_key_file_get_integer(gkeyfile, "remmina_pref", "ssh_tcp_keepidle", NULL);
515  else
516  remmina_pref.ssh_tcp_keepidle = SSH_SOCKET_TCP_KEEPIDLE;
517 
518  if (g_key_file_has_key(gkeyfile, "remmina_pref", "ssh_tcp_keepintvl", NULL))
519  remmina_pref.ssh_tcp_keepintvl = g_key_file_get_integer(gkeyfile, "remmina_pref", "ssh_tcp_keepintvl", NULL);
520  else
521  remmina_pref.ssh_tcp_keepintvl = SSH_SOCKET_TCP_KEEPINTVL;
522 
523  if (g_key_file_has_key(gkeyfile, "remmina_pref", "ssh_tcp_keepcnt", NULL))
524  remmina_pref.ssh_tcp_keepcnt = g_key_file_get_integer(gkeyfile, "remmina_pref", "ssh_tcp_keepcnt", NULL);
525  else
526  remmina_pref.ssh_tcp_keepcnt = SSH_SOCKET_TCP_KEEPCNT;
527 
528  if (g_key_file_has_key(gkeyfile, "remmina_pref", "ssh_tcp_usrtimeout", NULL))
529  remmina_pref.ssh_tcp_usrtimeout = g_key_file_get_integer(gkeyfile, "remmina_pref", "ssh_tcp_usrtimeout", NULL);
530  else
531  remmina_pref.ssh_tcp_usrtimeout = SSH_SOCKET_TCP_USER_TIMEOUT;
532 
533  if (g_key_file_has_key(gkeyfile, "remmina_pref", "applet_new_ontop", NULL))
534  remmina_pref.applet_new_ontop = g_key_file_get_boolean(gkeyfile, "remmina_pref", "applet_new_ontop", NULL);
535  else
537 
538  if (g_key_file_has_key(gkeyfile, "remmina_pref", "applet_hide_count", NULL))
539  remmina_pref.applet_hide_count = g_key_file_get_boolean(gkeyfile, "remmina_pref", "applet_hide_count", NULL);
540  else
542 
543  if (g_key_file_has_key(gkeyfile, "remmina_pref", "applet_enable_avahi", NULL))
544  remmina_pref.applet_enable_avahi = g_key_file_get_boolean(gkeyfile, "remmina_pref", "applet_enable_avahi",
545  NULL);
546  else
548 
549  if (g_key_file_has_key(gkeyfile, "remmina_pref", "disable_tray_icon", NULL))
550  remmina_pref.disable_tray_icon = g_key_file_get_boolean(gkeyfile, "remmina_pref", "disable_tray_icon", NULL);
551  else
553 
554  if (disabletrayicon)
556 
557  if (g_key_file_has_key(gkeyfile, "remmina_pref", "dark_theme", NULL))
558  remmina_pref.dark_theme = g_key_file_get_boolean(gkeyfile, "remmina_pref", "dark_theme", NULL);
559  else
560  remmina_pref.dark_theme = FALSE;
561 
562  if (g_key_file_has_key(gkeyfile, "remmina_pref", "list_refresh_workaround", NULL))
563  remmina_pref.list_refresh_workaround = g_key_file_get_boolean(gkeyfile, "remmina_pref", "list_refresh_workaround", NULL);
564  else
566 
567  if (g_key_file_has_key(gkeyfile, "remmina_pref", "grab_color_switch", NULL))
568  remmina_pref.grab_color_switch = g_key_file_get_boolean(gkeyfile, "remmina_pref", "grab_color_switch", NULL);
569  else
571 
572  if (g_key_file_has_key(gkeyfile, "remmina_pref", "grab_color", NULL))
573  remmina_pref.grab_color = g_key_file_get_string(gkeyfile, "remmina_pref", "grab_color", NULL);
574  else
575  remmina_pref.grab_color = "#00ff00";
576 
577  if (g_key_file_has_key(gkeyfile, "remmina_pref", "recent_maximum", NULL))
578  remmina_pref.recent_maximum = g_key_file_get_integer(gkeyfile, "remmina_pref", "recent_maximum", NULL);
579  else
581 
582  if (g_key_file_has_key(gkeyfile, "remmina_pref", "default_mode", NULL))
583  remmina_pref.default_mode = g_key_file_get_integer(gkeyfile, "remmina_pref", "default_mode", NULL);
584  else
586 
587  if (fullscreen)
589 
590  if (g_key_file_has_key(gkeyfile, "remmina_pref", "tab_mode", NULL))
591  remmina_pref.tab_mode = g_key_file_get_integer(gkeyfile, "remmina_pref", "tab_mode", NULL);
592  else
594 
595  if (g_key_file_has_key(gkeyfile, "remmina_pref", "fullscreen_toolbar_visibility", NULL))
596  remmina_pref.fullscreen_toolbar_visibility = g_key_file_get_integer(gkeyfile, "remmina_pref", "fullscreen_toolbar_visibility", NULL);
597  else
599 
600  if (disabletoolbar)
602 
603  if (g_key_file_has_key(gkeyfile, "remmina_pref", "auto_scroll_step", NULL))
604  remmina_pref.auto_scroll_step = g_key_file_get_integer(gkeyfile, "remmina_pref", "auto_scroll_step", NULL);
605  else
607 
608  if (g_key_file_has_key(gkeyfile, "remmina_pref", "hostkey", NULL))
609  remmina_pref.hostkey = g_key_file_get_integer(gkeyfile, "remmina_pref", "hostkey", NULL);
610  else
611  remmina_pref.hostkey = GDK_KEY_Control_R;
612 
613  if (g_key_file_has_key(gkeyfile, "remmina_pref", "shortcutkey_fullscreen", NULL))
614  remmina_pref.shortcutkey_fullscreen = g_key_file_get_integer(gkeyfile, "remmina_pref", "shortcutkey_fullscreen",
615  NULL);
616  else
618 
619  if (g_key_file_has_key(gkeyfile, "remmina_pref", "shortcutkey_autofit", NULL))
620  remmina_pref.shortcutkey_autofit = g_key_file_get_integer(gkeyfile, "remmina_pref", "shortcutkey_autofit",
621  NULL);
622  else
623  remmina_pref.shortcutkey_autofit = GDK_KEY_1;
624 
625  if (g_key_file_has_key(gkeyfile, "remmina_pref", "shortcutkey_nexttab", NULL))
626  remmina_pref.shortcutkey_nexttab = g_key_file_get_integer(gkeyfile, "remmina_pref", "shortcutkey_nexttab",
627  NULL);
628  else
629  remmina_pref.shortcutkey_nexttab = GDK_KEY_Right;
630 
631  if (g_key_file_has_key(gkeyfile, "remmina_pref", "shortcutkey_prevtab", NULL))
632  remmina_pref.shortcutkey_prevtab = g_key_file_get_integer(gkeyfile, "remmina_pref", "shortcutkey_prevtab",
633  NULL);
634  else
635  remmina_pref.shortcutkey_prevtab = GDK_KEY_Left;
636 
637  if (g_key_file_has_key(gkeyfile, "remmina_pref", "shortcutkey_scale", NULL))
638  remmina_pref.shortcutkey_scale = g_key_file_get_integer(gkeyfile, "remmina_pref", "shortcutkey_scale", NULL);
639  else
640  remmina_pref.shortcutkey_scale = GDK_KEY_s;
641 
642  if (g_key_file_has_key(gkeyfile, "remmina_pref", "shortcutkey_viewonly", NULL))
643  remmina_pref.shortcutkey_viewonly = g_key_file_get_integer(gkeyfile, "remmina_pref", "shortcutkey_viewonly", NULL);
644  else
646 
647  if (g_key_file_has_key(gkeyfile, "remmina_pref", "shortcutkey_multimon", NULL))
648  remmina_pref.shortcutkey_multimon = g_key_file_get_integer(gkeyfile, "remmina_pref", "shortcutkey_multimon", NULL);
649  else
650  remmina_pref.shortcutkey_multimon = GDK_KEY_Page_Up;
651 
652  if (g_key_file_has_key(gkeyfile, "remmina_pref", "shortcutkey_grab", NULL))
653  remmina_pref.shortcutkey_grab = g_key_file_get_integer(gkeyfile, "remmina_pref", "shortcutkey_grab", NULL);
654  else
655  remmina_pref.shortcutkey_grab = GDK_KEY_Control_R;
656 
657  if (g_key_file_has_key(gkeyfile, "remmina_pref", "shortcutkey_minimize", NULL))
658  remmina_pref.shortcutkey_minimize = g_key_file_get_integer(gkeyfile, "remmina_pref", "shortcutkey_minimize", NULL);
659  else
660  remmina_pref.shortcutkey_minimize = GDK_KEY_F9;
661 
662  if (g_key_file_has_key(gkeyfile, "remmina_pref", "shortcutkey_screenshot", NULL))
663  remmina_pref.shortcutkey_screenshot = g_key_file_get_integer(gkeyfile, "remmina_pref", "shortcutkey_screenshot", NULL);
664  else
665  remmina_pref.shortcutkey_screenshot = GDK_KEY_F12;
666 
667  if (g_key_file_has_key(gkeyfile, "remmina_pref", "shortcutkey_disconnect", NULL))
668  remmina_pref.shortcutkey_disconnect = g_key_file_get_integer(gkeyfile, "remmina_pref", "shortcutkey_disconnect",
669  NULL);
670  else
672 
673  if (g_key_file_has_key(gkeyfile, "remmina_pref", "shortcutkey_toolbar", NULL))
674  remmina_pref.shortcutkey_toolbar = g_key_file_get_integer(gkeyfile, "remmina_pref", "shortcutkey_toolbar",
675  NULL);
676  else
677  remmina_pref.shortcutkey_toolbar = GDK_KEY_t;
678 
679  if (g_key_file_has_key(gkeyfile, "remmina_pref", "secret", NULL))
680  remmina_pref.secret = g_key_file_get_string(gkeyfile, "remmina_pref", "secret", NULL);
681  else
682  remmina_pref.secret = NULL;
683 
684  if (g_key_file_has_key(gkeyfile, "remmina_pref", "uid", NULL))
685  remmina_pref.uid = g_key_file_get_string(gkeyfile, "remmina_pref", "uid", NULL);
686  else
687  remmina_pref.uid = NULL;
688 
689  if (g_key_file_has_key(gkeyfile, "remmina_pref", "vte_font", NULL))
690  remmina_pref.vte_font = g_key_file_get_string(gkeyfile, "remmina_pref", "vte_font", NULL);
691  else
693 
694  if (g_key_file_has_key(gkeyfile, "remmina_pref", "vte_allow_bold_text", NULL))
695  remmina_pref.vte_allow_bold_text = g_key_file_get_boolean(gkeyfile, "remmina_pref", "vte_allow_bold_text",
696  NULL);
697  else
699 
700  if (g_key_file_has_key(gkeyfile, "remmina_pref", "vte_lines", NULL))
701  remmina_pref.vte_lines = g_key_file_get_integer(gkeyfile, "remmina_pref", "vte_lines", NULL);
702  else
703  remmina_pref.vte_lines = 512;
704 
705  if (g_key_file_has_key(gkeyfile, "remmina_pref", "vte_shortcutkey_copy", NULL))
706  remmina_pref.vte_shortcutkey_copy = g_key_file_get_integer(gkeyfile, "remmina_pref", "vte_shortcutkey_copy",
707  NULL);
708  else
710 
711  if (g_key_file_has_key(gkeyfile, "remmina_pref", "vte_shortcutkey_paste", NULL))
712  remmina_pref.vte_shortcutkey_paste = g_key_file_get_integer(gkeyfile, "remmina_pref", "vte_shortcutkey_paste",
713  NULL);
714  else
716 
717  if (g_key_file_has_key(gkeyfile, "remmina_pref", "vte_shortcutkey_select_all", NULL))
718  remmina_pref.vte_shortcutkey_select_all = g_key_file_get_integer(gkeyfile, "remmina_pref", "vte_shortcutkey_select_all",
719  NULL);
720  else
722 
723  if (g_key_file_has_key(gkeyfile, "remmina_pref", "vte_shortcutkey_increase_font", NULL))
724  remmina_pref.vte_shortcutkey_increase_font = g_key_file_get_integer(gkeyfile, "remmina_pref", "vte_shortcutkey_increase_font",
725  NULL);
726  else
728 
729  if (g_key_file_has_key(gkeyfile, "remmina_pref", "vte_shortcutkey_decrease_font", NULL))
730  remmina_pref.vte_shortcutkey_decrease_font = g_key_file_get_integer(gkeyfile, "remmina_pref", "vte_shortcutkey_decrease_font",
731  NULL);
732  else
733  remmina_pref.vte_shortcutkey_decrease_font = GDK_KEY_Page_Down;
734 
735  if (g_key_file_has_key(gkeyfile, "remmina_pref", "vte_shortcutkey_search_text", NULL))
736  remmina_pref.vte_shortcutkey_search_text = g_key_file_get_integer(gkeyfile, "remmina_pref", "vte_shortcutkey_search_text",
737  NULL);
738  else
740 
741 
743 
744  /* If we have a color scheme file, we switch to it, GIO will merge it in the
745  * remmina.pref file */
746  if (g_file_test(remmina_colors_file, G_FILE_TEST_IS_REGULAR)) {
747  g_key_file_load_from_file(gkeyfile, remmina_colors_file, G_KEY_FILE_NONE, NULL);
748  g_remove(remmina_colors_file);
749  }
750 
751  /* Default settings */
752  if (!g_key_file_has_key(gkeyfile, "remmina", "name", NULL)) {
753  g_key_file_set_string(gkeyfile, "remmina", "name", "");
754  g_key_file_set_integer(gkeyfile, "remmina", "ignore-tls-errors", 1);
755  g_key_file_set_integer(gkeyfile, "remmina", "enable-plugins", 1);
757  }
758 
759  g_key_file_free(gkeyfile);
760 
761  if (remmina_pref.secret == NULL)
763 
765 }
766 
767 gboolean remmina_pref_is_rw(void)
768 {
769  TRACE_CALL(__func__);
770  if (access(remmina_pref_file, W_OK) == 0)
771  return TRUE;
772  else
773  return FALSE;
774  return FALSE;
775 }
776 
777 gboolean remmina_pref_save(void)
778 {
779  TRACE_CALL(__func__);
780 
781  if (remmina_pref_is_rw() == FALSE) {
782  g_debug("remmina.pref is not writable, returning");
783  return FALSE;
784  }
785  GKeyFile *gkeyfile;
786  GError *error = NULL;
787  g_autofree gchar *content = NULL;
788  gsize length;
789 
790  gkeyfile = g_key_file_new();
791 
792  g_key_file_load_from_file(gkeyfile, remmina_pref_file, G_KEY_FILE_NONE, NULL);
793 
794  g_key_file_set_string(gkeyfile, "remmina_pref", "datadir_path", remmina_pref.datadir_path);
795  g_key_file_set_string(gkeyfile, "remmina_pref", "remmina_file_name", remmina_pref.remmina_file_name);
796  g_key_file_set_string(gkeyfile, "remmina_pref", "screenshot_path", remmina_pref.screenshot_path);
797  g_key_file_set_string(gkeyfile, "remmina_pref", "screenshot_name", remmina_pref.screenshot_name);
798  g_key_file_set_boolean(gkeyfile, "remmina_pref", "deny_screenshot_clipboard", remmina_pref.deny_screenshot_clipboard);
799  g_key_file_set_boolean(gkeyfile, "remmina_pref", "save_view_mode", remmina_pref.save_view_mode);
800  g_key_file_set_boolean(gkeyfile, "remmina_pref", "confirm_close", remmina_pref.confirm_close);
801  if (g_key_file_remove_key(gkeyfile, "remmina_pref", "use_master_password", NULL))
802  REMMINA_DEBUG("use_master_password removed…");
803  else
804  REMMINA_INFO("use_master_password already migrated");
805 #if SODIUM_VERSION_INT >= 90200
806  g_key_file_set_boolean(gkeyfile, "remmina_pref", "use_primary_password", remmina_pref.use_primary_password);
807  g_key_file_set_integer(gkeyfile, "remmina_pref", "unlock_timeout", remmina_pref.unlock_timeout);
808  g_key_file_set_string(gkeyfile, "remmina_pref", "unlock_password", remmina_pref.unlock_password);
809  g_key_file_set_boolean(gkeyfile, "remmina_pref", "lock_connect", remmina_pref.lock_connect);
810  g_key_file_set_boolean(gkeyfile, "remmina_pref", "lock_edit", remmina_pref.lock_edit);
811  g_key_file_set_boolean(gkeyfile, "remmina_pref", "lock_view_passwords", remmina_pref.lock_view_passwords);
812 #else
813  g_key_file_set_boolean(gkeyfile, "remmina_pref", "use_primary_password", FALSE);
814  g_key_file_set_integer(gkeyfile, "remmina_pref", "unlock_timeout", 0);
815  g_key_file_set_string(gkeyfile, "remmina_pref", "unlock_password", g_strdup(""));
816  g_key_file_set_boolean(gkeyfile, "remmina_pref", "lock_connect", FALSE);
817  g_key_file_set_boolean(gkeyfile, "remmina_pref", "lock_edit", FALSE);
818  g_key_file_set_boolean(gkeyfile, "remmina_pref", "lock_view_passwords", FALSE);
819 #endif
820  g_key_file_set_integer(gkeyfile, "remmina_pref", "enc_mode", remmina_pref.enc_mode);
821  g_key_file_set_boolean(gkeyfile, "remmina_pref", "audit", remmina_pref.audit);
822  g_key_file_set_boolean(gkeyfile, "remmina_pref", "trust_all", remmina_pref.trust_all);
823  g_key_file_set_integer(gkeyfile, "remmina_pref", "floating_toolbar_placement", remmina_pref.floating_toolbar_placement);
824  g_key_file_set_integer(gkeyfile, "remmina_pref", "toolbar_placement", remmina_pref.toolbar_placement);
825  g_key_file_set_boolean(gkeyfile, "remmina_pref", "prevent_snap_welcome_message", remmina_pref.prevent_snap_welcome_message);
826  g_key_file_set_string(gkeyfile, "remmina_pref", "last_quickconnect_protocol", remmina_pref.last_quickconnect_protocol);
827  g_key_file_set_boolean(gkeyfile, "remmina_pref", "fullscreen_on_auto", remmina_pref.fullscreen_on_auto);
828  g_key_file_set_boolean(gkeyfile, "remmina_pref", "always_show_tab", remmina_pref.always_show_tab);
829  g_key_file_set_boolean(gkeyfile, "remmina_pref", "always_show_notes", remmina_pref.always_show_notes);
830  g_key_file_set_boolean(gkeyfile, "remmina_pref", "hide_connection_toolbar", remmina_pref.hide_connection_toolbar);
831  g_key_file_set_boolean(gkeyfile, "remmina_pref", "hide_searchbar", remmina_pref.hide_searchbar);
832  g_key_file_set_integer(gkeyfile, "remmina_pref", "default_action", remmina_pref.default_action);
833  g_key_file_set_integer(gkeyfile, "remmina_pref", "scale_quality", remmina_pref.scale_quality);
834  g_key_file_set_integer(gkeyfile, "remmina_pref", "ssh_loglevel", remmina_pref.ssh_loglevel);
835  g_key_file_set_boolean(gkeyfile, "remmina_pref", "ssh_parseconfig", remmina_pref.ssh_parseconfig);
836  g_key_file_set_boolean(gkeyfile, "remmina_pref", "hide_toolbar", remmina_pref.hide_toolbar);
837  g_key_file_set_boolean(gkeyfile, "remmina_pref", "small_toolbutton", remmina_pref.small_toolbutton);
838  g_key_file_set_integer(gkeyfile, "remmina_pref", "view_file_mode", remmina_pref.view_file_mode);
839  g_key_file_set_string(gkeyfile, "remmina_pref", "resolutions", remmina_pref.resolutions);
840  g_key_file_set_string(gkeyfile, "remmina_pref", "keystrokes", remmina_pref.keystrokes);
841  g_key_file_set_integer(gkeyfile, "remmina_pref", "main_width", remmina_pref.main_width);
842  g_key_file_set_integer(gkeyfile, "remmina_pref", "main_height", remmina_pref.main_height);
843  g_key_file_set_boolean(gkeyfile, "remmina_pref", "main_maximize", remmina_pref.main_maximize);
844  g_key_file_set_integer(gkeyfile, "remmina_pref", "main_sort_column_id", remmina_pref.main_sort_column_id);
845  g_key_file_set_integer(gkeyfile, "remmina_pref", "main_sort_order", remmina_pref.main_sort_order);
846  g_key_file_set_string(gkeyfile, "remmina_pref", "expanded_group", remmina_pref.expanded_group);
847  g_key_file_set_boolean(gkeyfile, "remmina_pref", "toolbar_pin_down", remmina_pref.toolbar_pin_down);
848  g_key_file_set_integer(gkeyfile, "remmina_pref", "sshtunnel_port", remmina_pref.sshtunnel_port);
849  g_key_file_set_integer(gkeyfile, "remmina_pref", "ssh_tcp_keepidle", remmina_pref.ssh_tcp_keepidle);
850  g_key_file_set_integer(gkeyfile, "remmina_pref", "ssh_tcp_keepintvl", remmina_pref.ssh_tcp_keepintvl);
851  g_key_file_set_integer(gkeyfile, "remmina_pref", "ssh_tcp_keepcnt", remmina_pref.ssh_tcp_keepcnt);
852  g_key_file_set_integer(gkeyfile, "remmina_pref", "ssh_tcp_usrtimeout", remmina_pref.ssh_tcp_usrtimeout);
853  g_key_file_set_boolean(gkeyfile, "remmina_pref", "applet_new_ontop", remmina_pref.applet_new_ontop);
854  g_key_file_set_boolean(gkeyfile, "remmina_pref", "applet_hide_count", remmina_pref.applet_hide_count);
855  g_key_file_set_boolean(gkeyfile, "remmina_pref", "applet_enable_avahi", remmina_pref.applet_enable_avahi);
856  g_key_file_set_boolean(gkeyfile, "remmina_pref", "disable_tray_icon", remmina_pref.disable_tray_icon);
857  g_key_file_set_boolean(gkeyfile, "remmina_pref", "dark_theme", remmina_pref.dark_theme);
858  g_key_file_set_integer(gkeyfile, "remmina_pref", "recent_maximum", remmina_pref.recent_maximum);
859  g_key_file_set_integer(gkeyfile, "remmina_pref", "default_mode", remmina_pref.default_mode);
860  g_key_file_set_integer(gkeyfile, "remmina_pref", "tab_mode", remmina_pref.tab_mode);
861  g_key_file_set_integer(gkeyfile, "remmina_pref", "fullscreen_toolbar_visibility", remmina_pref.fullscreen_toolbar_visibility);
862  g_key_file_set_integer(gkeyfile, "remmina_pref", "auto_scroll_step", remmina_pref.auto_scroll_step);
863  g_key_file_set_integer(gkeyfile, "remmina_pref", "hostkey", remmina_pref.hostkey);
864  g_key_file_set_integer(gkeyfile, "remmina_pref", "shortcutkey_fullscreen", remmina_pref.shortcutkey_fullscreen);
865  g_key_file_set_integer(gkeyfile, "remmina_pref", "shortcutkey_autofit", remmina_pref.shortcutkey_autofit);
866  g_key_file_set_integer(gkeyfile, "remmina_pref", "shortcutkey_nexttab", remmina_pref.shortcutkey_nexttab);
867  g_key_file_set_integer(gkeyfile, "remmina_pref", "shortcutkey_prevtab", remmina_pref.shortcutkey_prevtab);
868  g_key_file_set_integer(gkeyfile, "remmina_pref", "shortcutkey_scale", remmina_pref.shortcutkey_scale);
869  g_key_file_set_integer(gkeyfile, "remmina_pref", "shortcutkey_grab", remmina_pref.shortcutkey_grab);
870  g_key_file_set_integer(gkeyfile, "remmina_pref", "shortcutkey_multimon", remmina_pref.shortcutkey_multimon);
871  g_key_file_set_integer(gkeyfile, "remmina_pref", "shortcutkey_viewonly", remmina_pref.shortcutkey_viewonly);
872  g_key_file_set_integer(gkeyfile, "remmina_pref", "shortcutkey_screenshot", remmina_pref.shortcutkey_screenshot);
873  g_key_file_set_integer(gkeyfile, "remmina_pref", "shortcutkey_minimize", remmina_pref.shortcutkey_minimize);
874  g_key_file_set_integer(gkeyfile, "remmina_pref", "shortcutkey_disconnect", remmina_pref.shortcutkey_disconnect);
875  g_key_file_set_integer(gkeyfile, "remmina_pref", "shortcutkey_toolbar", remmina_pref.shortcutkey_toolbar);
876  g_key_file_set_integer(gkeyfile, "remmina_pref", "vte_shortcutkey_copy", remmina_pref.vte_shortcutkey_copy);
877  g_key_file_set_integer(gkeyfile, "remmina_pref", "vte_shortcutkey_paste", remmina_pref.vte_shortcutkey_paste);
878  g_key_file_set_integer(gkeyfile, "remmina_pref", "vte_shortcutkey_select_all", remmina_pref.vte_shortcutkey_select_all);
879  g_key_file_set_integer(gkeyfile, "remmina_pref", "vte_shortcutkey_increase_font", remmina_pref.vte_shortcutkey_increase_font);
880  g_key_file_set_integer(gkeyfile, "remmina_pref", "vte_shortcutkey_decrease_font", remmina_pref.vte_shortcutkey_decrease_font);
881  g_key_file_set_integer(gkeyfile, "remmina_pref", "vte_shortcutkey_search_text", remmina_pref.vte_shortcutkey_search_text);
882  g_key_file_set_string(gkeyfile, "remmina_pref", "vte_font", remmina_pref.vte_font ? remmina_pref.vte_font : "");
883  g_key_file_set_string(gkeyfile, "remmina_pref", "grab_color", remmina_pref.grab_color ? remmina_pref.grab_color : "");
884  g_key_file_set_boolean(gkeyfile, "remmina_pref", "grab_color_switch", remmina_pref.grab_color_switch);
885  g_key_file_set_boolean(gkeyfile, "remmina_pref", "vte_allow_bold_text", remmina_pref.vte_allow_bold_text);
886  g_key_file_set_integer(gkeyfile, "remmina_pref", "vte_lines", remmina_pref.vte_lines);
887  g_key_file_set_string(gkeyfile, "ssh_colors", "background", remmina_pref.color_pref.background ? remmina_pref.color_pref.background : "");
888  g_key_file_set_string(gkeyfile, "ssh_colors", "cursor", remmina_pref.color_pref.cursor ? remmina_pref.color_pref.cursor : "");
889  g_key_file_set_string(gkeyfile, "ssh_colors", "cursor_foreground", remmina_pref.color_pref.cursor_foreground ? remmina_pref.color_pref.cursor_foreground : "");
890  g_key_file_set_string(gkeyfile, "ssh_colors", "highlight", remmina_pref.color_pref.highlight ? remmina_pref.color_pref.highlight : "");
891  g_key_file_set_string(gkeyfile, "ssh_colors", "highlight_foreground", remmina_pref.color_pref.highlight_foreground ? remmina_pref.color_pref.highlight_foreground : "");
892  g_key_file_set_string(gkeyfile, "ssh_colors", "colorBD", remmina_pref.color_pref.colorBD ? remmina_pref.color_pref.colorBD : "");
893  g_key_file_set_string(gkeyfile, "ssh_colors", "foreground", remmina_pref.color_pref.foreground ? remmina_pref.color_pref.foreground : "");
894  g_key_file_set_string(gkeyfile, "ssh_colors", "color0", remmina_pref.color_pref.color0 ? remmina_pref.color_pref.color0 : "");
895  g_key_file_set_string(gkeyfile, "ssh_colors", "color1", remmina_pref.color_pref.color1 ? remmina_pref.color_pref.color1 : "");
896  g_key_file_set_string(gkeyfile, "ssh_colors", "color2", remmina_pref.color_pref.color2 ? remmina_pref.color_pref.color2 : "");
897  g_key_file_set_string(gkeyfile, "ssh_colors", "color3", remmina_pref.color_pref.color3 ? remmina_pref.color_pref.color3 : "");
898  g_key_file_set_string(gkeyfile, "ssh_colors", "color4", remmina_pref.color_pref.color4 ? remmina_pref.color_pref.color4 : "");
899  g_key_file_set_string(gkeyfile, "ssh_colors", "color5", remmina_pref.color_pref.color5 ? remmina_pref.color_pref.color5 : "");
900  g_key_file_set_string(gkeyfile, "ssh_colors", "color6", remmina_pref.color_pref.color6 ? remmina_pref.color_pref.color6 : "");
901  g_key_file_set_string(gkeyfile, "ssh_colors", "color7", remmina_pref.color_pref.color7 ? remmina_pref.color_pref.color7 : "");
902  g_key_file_set_string(gkeyfile, "ssh_colors", "color8", remmina_pref.color_pref.color8 ? remmina_pref.color_pref.color8 : "");
903  g_key_file_set_string(gkeyfile, "ssh_colors", "color9", remmina_pref.color_pref.color9 ? remmina_pref.color_pref.color9 : "");
904  g_key_file_set_string(gkeyfile, "ssh_colors", "color10", remmina_pref.color_pref.color10 ? remmina_pref.color_pref.color10 : "");
905  g_key_file_set_string(gkeyfile, "ssh_colors", "color11", remmina_pref.color_pref.color11 ? remmina_pref.color_pref.color11 : "");
906  g_key_file_set_string(gkeyfile, "ssh_colors", "color12", remmina_pref.color_pref.color12 ? remmina_pref.color_pref.color12 : "");
907  g_key_file_set_string(gkeyfile, "ssh_colors", "color13", remmina_pref.color_pref.color13 ? remmina_pref.color_pref.color13 : "");
908  g_key_file_set_string(gkeyfile, "ssh_colors", "color14", remmina_pref.color_pref.color14 ? remmina_pref.color_pref.color14 : "");
909  g_key_file_set_string(gkeyfile, "ssh_colors", "color15", remmina_pref.color_pref.color15 ? remmina_pref.color_pref.color15 : "");
910 
911  /* Default settings */
912  g_key_file_set_string(gkeyfile, "remmina", "name", "");
913  g_key_file_set_integer(gkeyfile, "remmina", "ignore-tls-errors", 1);
914 
915  content = g_key_file_to_data(gkeyfile, &length, NULL);
916  g_file_set_contents(remmina_pref_file, content, length, &error);
917 
918  if (error != NULL) {
919  g_warning("remmina_pref_save error: %s", error->message);
920  g_clear_error(&error);
921  g_key_file_free(gkeyfile);
922  return FALSE;
923  }
924  g_key_file_free(gkeyfile);
925  return TRUE;
926 }
927 
928 void remmina_pref_add_recent(const gchar *protocol, const gchar *server)
929 {
930  TRACE_CALL(__func__);
931  RemminaStringArray *array;
932  GKeyFile *gkeyfile;
933  gchar key[20];
934  g_autofree gchar *val = NULL;
935  g_autofree gchar *content = NULL;
936  gsize length;
937 
938  if (remmina_pref.recent_maximum <= 0 || server == NULL || server[0] == 0)
939  return;
940 
941  /* Load original value into memory */
942  gkeyfile = g_key_file_new();
943 
944  g_key_file_load_from_file(gkeyfile, remmina_pref_file, G_KEY_FILE_NONE, NULL);
945 
946  g_snprintf(key, sizeof(key), "recent_%s", protocol);
947  array = remmina_string_array_new_from_allocated_string(g_key_file_get_string(gkeyfile, "remmina_pref", key, NULL));
948 
949  /* Add the new value */
950  remmina_string_array_remove(array, server);
951  while (array->len >= remmina_pref.recent_maximum)
953  remmina_string_array_add(array, server);
954 
955  /* Save */
956  val = remmina_string_array_to_string(array);
957  g_key_file_set_string(gkeyfile, "remmina_pref", key, val);
958 
959  content = g_key_file_to_data(gkeyfile, &length, NULL);
960  g_file_set_contents(remmina_pref_file, content, length, NULL);
961 
962  g_key_file_free(gkeyfile);
963 }
964 
965 gchar *
966 remmina_pref_get_recent(const gchar *protocol)
967 {
968  TRACE_CALL(__func__);
969  GKeyFile *gkeyfile;
970  gchar key[20];
971  gchar *val = NULL;
972 
973  gkeyfile = g_key_file_new();
974 
975  g_key_file_load_from_file(gkeyfile, remmina_pref_file, G_KEY_FILE_NONE, NULL);
976 
977  g_snprintf(key, sizeof(key), "recent_%s", protocol);
978  val = g_key_file_get_string(gkeyfile, "remmina_pref", key, NULL);
979 
980  g_key_file_free(gkeyfile);
981 
982  return val;
983 }
984 
986 {
987  TRACE_CALL(__func__);
988  GKeyFile *gkeyfile;
989  gchar **keys;
990  gint i;
991  g_autofree gchar *content = NULL;
992  gsize length;
993 
994  gkeyfile = g_key_file_new();
995 
996  g_key_file_load_from_file(gkeyfile, remmina_pref_file, G_KEY_FILE_NONE, NULL);
997  keys = g_key_file_get_keys(gkeyfile, "remmina_pref", NULL, NULL);
998  if (keys) {
999  for (i = 0; keys[i]; i++)
1000  if (strncmp(keys[i], "recent_", 7) == 0)
1001  g_key_file_set_string(gkeyfile, "remmina_pref", keys[i], "");
1002  g_strfreev(keys);
1003  }
1004 
1005  content = g_key_file_to_data(gkeyfile, &length, NULL);
1006  g_file_set_contents(remmina_pref_file, content, length, NULL);
1007 
1008  g_key_file_free(gkeyfile);
1009 }
1010 
1011 guint *remmina_pref_keymap_get_table(const gchar *keymap)
1012 {
1013  TRACE_CALL(__func__);
1014 
1015  if (!keymap || keymap[0] == '\0')
1016  return NULL;
1017 
1018  return (guint *)g_hash_table_lookup(remmina_keymap_table, keymap);
1019 }
1020 
1021 guint remmina_pref_keymap_get_keyval(const gchar *keymap, guint keyval)
1022 {
1023  TRACE_CALL(__func__);
1024  guint *table;
1025  gint i;
1026 
1027  if (!keymap || keymap[0] == '\0')
1028  return keyval;
1029 
1030  table = (guint *)g_hash_table_lookup(remmina_keymap_table, keymap);
1031  if (!table)
1032  return keyval;
1033  for (i = 0; table[i] > 0; i += 2)
1034  if (table[i] == keyval)
1035  return table[i + 1];
1036  return keyval;
1037 }
1038 
1039 gchar **
1041 {
1042  TRACE_CALL(__func__);
1043  GList *list;
1044  guint len;
1045  gchar **keys;
1046  guint i;
1047 
1048  list = g_hash_table_get_keys(remmina_keymap_table);
1049  len = g_list_length(list);
1050 
1051  keys = g_new0(gchar *, (len + 1) * 2 + 1);
1052  keys[0] = g_strdup("");
1053  keys[1] = g_strdup("");
1054  for (i = 0; i < len; i++) {
1055  keys[(i + 1) * 2] = g_strdup((gchar *)g_list_nth_data(list, i));
1056  keys[(i + 1) * 2 + 1] = g_strdup((gchar *)g_list_nth_data(list, i));
1057  }
1058  g_list_free(list);
1059 
1060  return keys;
1061 }
1062 
1064 {
1065  TRACE_CALL(__func__);
1066  /* Paranoid programming */
1067  if (remmina_pref.scale_quality < 0)
1069  return remmina_pref.scale_quality;
1070 }
1071 
1073 {
1074  TRACE_CALL(__func__);
1075  return remmina_pref.ssh_loglevel;
1076 }
1077 
1079 {
1080  TRACE_CALL(__func__);
1082 }
1083 
1085 {
1086  TRACE_CALL(__func__);
1088 }
1089 
1091 {
1092  TRACE_CALL(__func__);
1094 }
1095 
1097 {
1098  TRACE_CALL(__func__);
1100 }
1101 
1103 {
1104  TRACE_CALL(__func__);
1106 }
1107 
1109 {
1110  TRACE_CALL(__func__);
1112 }
1113 
1114 void remmina_pref_set_value(const gchar *key, const gchar *value)
1115 {
1116  TRACE_CALL(__func__);
1117  GKeyFile *gkeyfile;
1118  gsize length;
1119 
1120  gkeyfile = g_key_file_new();
1121  if (g_key_file_load_from_file(gkeyfile, remmina_pref_file, G_KEY_FILE_NONE, NULL)) {
1122  g_key_file_set_string(gkeyfile, "remmina_pref", key, value);
1123  gchar *content = g_key_file_to_data(gkeyfile, &length, NULL);
1124  if (g_file_set_contents(remmina_pref_file, content, length, NULL)) {
1125  g_free(content);
1126  } else {
1127  REMMINA_WARNING("Cannot save Remmina preferences");
1128  REMMINA_WARNING("Key was \"%s\", and value \"%s\"", key, value);
1129  }
1130  g_key_file_free(gkeyfile);
1131  } else {
1132  REMMINA_WARNING("Cannot load Remmina preferences file");
1133  }
1134 }
1135 
1136 gchar *remmina_pref_get_value(const gchar *key)
1137 {
1138  TRACE_CALL(__func__);
1139  GKeyFile *gkeyfile;
1140  gchar *value = NULL;
1141 
1142  gkeyfile = g_key_file_new();
1143  g_key_file_load_from_file(gkeyfile, remmina_pref_file, G_KEY_FILE_NONE, NULL);
1144  value = g_key_file_get_string(gkeyfile, "remmina_pref", key, NULL);
1145  g_key_file_free(gkeyfile);
1146 
1147  return value;
1148 }
1149 
1150 gboolean remmina_pref_get_boolean(const gchar *key)
1151 {
1152  TRACE_CALL(__func__);
1153  GKeyFile *gkeyfile;
1154  gboolean value;
1155 
1156  gkeyfile = g_key_file_new();
1157  g_key_file_load_from_file(gkeyfile, remmina_pref_file, G_KEY_FILE_NONE, NULL);
1158  value = g_key_file_get_boolean(gkeyfile, "remmina_pref", key, NULL);
1159  g_key_file_free(gkeyfile);
1160 
1161  return value;
1162 }
guint shortcutkey_fullscreen
Definition: remmina_pref.h:175
+Go to the documentation of this file.
1 /*
2  * Remmina - The GTK+ Remote Desktop Client
3  * Copyright (C) 2009-2011 Vic Lee
4  * Copyright (C) 2014-2015 Antenore Gatta, Fabio Castelli, Giovanni Panozzo
5  * Copyright (C) 2016-2022 Antenore Gatta, Giovanni Panozzo
6  * Copyright (C) 2022-2023 Antenore Gatta, Giovanni Panozzo, Hiroyuki Tanaka
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor,
21  * Boston, MA 02110-1301, USA.
22  *
23  * In addition, as a special exception, the copyright holders give
24  * permission to link the code of portions of this program with the
25  * OpenSSL library under certain conditions as described in each
26  * individual source file, and distribute linked combinations
27  * including the two.
28  * You must obey the GNU General Public License in all respects
29  * for all of the code used other than OpenSSL. * If you modify
30  * file(s) with this exception, you may extend this exception to your
31  * version of the file(s), but you are not obligated to do so. * If you
32  * do not wish to do so, delete this exception statement from your
33  * version. * If you delete this exception statement from all source
34  * files in the program, then also delete it here.
35  *
36  */
37 
38 #include "config.h"
39 
40 #include <stdlib.h>
41 #include <string.h>
42 #include <unistd.h>
43 #include <sys/time.h>
44 #include <sys/utsname.h>
45 
46 #include <glib/gstdio.h>
47 #include <gdk/gdkkeysyms.h>
48 #include <gtk/gtk.h>
49 
50 #include "remmina_sodium.h"
51 
52 #include "remmina_public.h"
53 #include "remmina_string_array.h"
54 #include "remmina_pref.h"
55 #include "remmina_log.h"
57 
58 const gchar *default_resolutions = "640x480,800x600,1024x768,1152x864,1280x960,1400x1050,1920x1080";
59 const gchar *default_keystrokes = "Send hello world§hello world\\n";
60 
62 static GHashTable *remmina_keymap_table = NULL;
63 
64 /* We could customize this further if there are more requirements */
65 static const gchar *default_keymap_data = "# Please check gdk/gdkkeysyms.h for a full list of all key names or hex key values\n"
66  "\n"
67  "[Map Meta Keys]\n"
68  "Super_L = Meta_L\n"
69  "Super_R = Meta_R\n"
70  "Meta_L = Super_L\n"
71  "Meta_R = Super_R\n";
72 
73 static void remmina_pref_gen_secret(void)
74 {
75  TRACE_CALL(__func__);
76  guchar s[32];
77  gint i;
78  GKeyFile *gkeyfile;
79  g_autofree gchar *content = NULL;
80  gsize length;
81 
82  for (i = 0; i < 32; i++)
83  s[i] = (guchar)(randombytes_uniform(257));
84  remmina_pref.secret = g_base64_encode(s, 32);
85 
86  gkeyfile = g_key_file_new();
87  g_key_file_load_from_file(gkeyfile, remmina_pref_file, G_KEY_FILE_NONE, NULL);
88  g_key_file_set_string(gkeyfile, "remmina_pref", "secret", remmina_pref.secret);
89  content = g_key_file_to_data(gkeyfile, &length, NULL);
90  g_file_set_contents(remmina_pref_file, content, length, NULL);
91 
92  g_key_file_free(gkeyfile);
93 }
94 
95 static guint remmina_pref_get_keyval_from_str(const gchar *str)
96 {
97  TRACE_CALL(__func__);
98  guint k;
99 
100  if (!str)
101  return 0;
102 
103  k = gdk_keyval_from_name(str);
104  if (!k)
105  if (sscanf(str, "%x", &k) < 1)
106  k = 0;
107  return k;
108 }
109 
110 static void remmina_pref_init_keymap(void)
111 {
112  TRACE_CALL(__func__);
113  GKeyFile *gkeyfile;
114  gchar **groups;
115  gchar **gptr;
116  gchar **keys;
117  gchar **kptr;
118  gsize nkeys;
119  g_autofree gchar *value = NULL;
120  guint *table;
121  guint *tableptr;
122  guint k1, k2;
123 
125  g_hash_table_destroy(remmina_keymap_table);
126  remmina_keymap_table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
127 
128  gkeyfile = g_key_file_new();
129  if (!g_key_file_load_from_file(gkeyfile, remmina_keymap_file, G_KEY_FILE_NONE, NULL)) {
130  if (!g_key_file_load_from_data(gkeyfile, default_keymap_data, strlen(default_keymap_data), G_KEY_FILE_NONE,
131  NULL)) {
132  g_print("Failed to initialize keymap table\n");
133  g_key_file_free(gkeyfile);
134  return;
135  }
136  }
137 
138  groups = g_key_file_get_groups(gkeyfile, NULL);
139  gptr = groups;
140  while (*gptr) {
141  keys = g_key_file_get_keys(gkeyfile, *gptr, &nkeys, NULL);
142  table = g_new0(guint, nkeys * 2 + 1);
143  g_hash_table_insert(remmina_keymap_table, g_strdup(*gptr), table);
144 
145  kptr = keys;
146  tableptr = table;
147  while (*kptr) {
149  if (k1) {
150  value = g_key_file_get_string(gkeyfile, *gptr, *kptr, NULL);
152  *tableptr++ = k1;
153  *tableptr++ = k2;
154  }
155  kptr++;
156  }
157  g_strfreev(keys);
158  gptr++;
159  }
160  g_strfreev(groups);
161  g_key_file_free(gkeyfile);
162 }
163 
165 static gboolean remmina_pref_file_do_copy(const char *src_path, const char *dst_path)
166 {
167  GFile *src = g_file_new_for_path(src_path), *dst = g_file_new_for_path(dst_path);
168  /* We don’t overwrite the target if it exists, because overwrite is not set */
169  const gboolean ok = g_file_copy(src, dst, G_FILE_COPY_NONE, NULL, NULL, NULL, NULL);
170 
171  g_object_unref(dst);
172  g_object_unref(src);
173 
174  return ok;
175 }
176 
177 void remmina_pref_file_load_colors(GKeyFile *gkeyfile, RemminaColorPref *color_pref)
178 {
179  const struct {
180  const char * name;
181  char ** setting;
182  char * fallback;
183  } colors[] = {
184  { "background", &color_pref->background, "#d5ccba" },
185  { "cursor", &color_pref->cursor, "#45373c" },
186  { "cursor_foreground", &color_pref->cursor_foreground, "#d5ccba" },
187  { "highlight", &color_pref->highlight, "#45373c" },
188  { "highlight_foreground", &color_pref->highlight_foreground, "#d5ccba" },
189  { "colorBD", &color_pref->colorBD, "#45373c" },
190  { "foreground", &color_pref->foreground, "#45373c" },
191  { "color0", &color_pref->color0, "#20111b" },
192  { "color1", &color_pref->color1, "#be100e" },
193  { "color2", &color_pref->color2, "#858162" },
194  { "color3", &color_pref->color3, "#eaa549" },
195  { "color4", &color_pref->color4, "#426a79" },
196  { "color5", &color_pref->color5, "#97522c" },
197  { "color6", &color_pref->color6, "#989a9c" },
198  { "color7", &color_pref->color7, "#968c83" },
199  { "color8", &color_pref->color8, "#5e5252" },
200  { "color9", &color_pref->color9, "#be100e" },
201  { "color10", &color_pref->color10, "#858162" },
202  { "color11", &color_pref->color11, "#eaa549" },
203  { "color12", &color_pref->color12, "#426a79" },
204  { "color13", &color_pref->color13, "#97522c" },
205  { "color14", &color_pref->color14, "#989a9c" },
206  { "color15", &color_pref->color15, "#d5ccba" },
207  };
208 
209  int i;
210 
211  for (i = 0; i < (sizeof(colors) / sizeof(colors[0])); i++) {
212  if (g_key_file_has_key(gkeyfile, "ssh_colors", colors[i].name, NULL))
213  *colors[i].setting = g_key_file_get_string(gkeyfile, "ssh_colors", colors[i].name,
214  NULL);
215  else
216  *colors[i].setting = colors[i].fallback;
217  }
218 }
219 
221 {
222  TRACE_CALL(__func__);
223  GKeyFile *gkeyfile;
224  gchar *remmina_dir;
225  const gchar *filename = "remmina.pref";
226  const gchar *colors_filename = "remmina.colors";
227  g_autofree gchar *remmina_colors_file = NULL;
228  GDir *dir;
229  const gchar *legacy = ".remmina";
230  int i;
231 
232  remmina_dir = g_build_path("/", g_get_user_config_dir(), "remmina", NULL);
233  /* Create the XDG_CONFIG_HOME directory */
234  g_mkdir_with_parents(remmina_dir, 0750);
235 
236  g_free(remmina_dir), remmina_dir = NULL;
237  /* Legacy ~/.remmina we copy the existing remmina.pref file inside
238  * XDG_CONFIG_HOME */
239  remmina_dir = g_build_path("/", g_get_home_dir(), legacy, NULL);
240  if (g_file_test(remmina_dir, G_FILE_TEST_IS_DIR)) {
241  dir = g_dir_open(remmina_dir, 0, NULL);
243  g_build_path("/", remmina_dir, filename, NULL),
244  g_build_path("/", g_get_user_config_dir(),
245  "remmina", filename, NULL));
246  g_dir_close(dir);
247  }
248 
249  /* /usr/local/etc/remmina */
250  const gchar *const *dirs = g_get_system_config_dirs();
251 
252  g_free(remmina_dir), remmina_dir = NULL;
253  for (i = 0; dirs[i] != NULL; ++i) {
254  remmina_dir = g_build_path("/", dirs[i], "remmina", NULL);
255  if (g_file_test(remmina_dir, G_FILE_TEST_IS_DIR)) {
256  dir = g_dir_open(remmina_dir, 0, NULL);
257  while ((filename = g_dir_read_name(dir)) != NULL) {
259  g_build_path("/", remmina_dir, filename, NULL),
260  g_build_path("/", g_get_user_config_dir(),
261  "remmina", filename, NULL));
262  }
263  g_free(remmina_dir), remmina_dir = NULL;
264  }
265  }
266 
267  /* The last case we use the home ~/.config/remmina */
268  if (remmina_dir != NULL)
269  g_free(remmina_dir), remmina_dir = NULL;
270  remmina_dir = g_build_path("/", g_get_user_config_dir(),
271  "remmina", NULL);
272 
273  remmina_pref_file = g_strdup_printf("%s/remmina.pref", remmina_dir);
274  /* remmina.colors */
275  remmina_colors_file = g_strdup_printf("%s/%s", remmina_dir, colors_filename);
276 
277  remmina_keymap_file = g_strdup_printf("%s/remmina.keymap", remmina_dir);
278 
279  gkeyfile = g_key_file_new();
280 
281  g_key_file_load_from_file(gkeyfile, remmina_pref_file, G_KEY_FILE_NONE, NULL);
282 
283  if (g_key_file_has_key(gkeyfile, "remmina_pref", "save_view_mode", NULL))
284  remmina_pref.save_view_mode = g_key_file_get_boolean(gkeyfile, "remmina_pref", "save_view_mode", NULL);
285  else
287 
288  if (g_key_file_has_key(gkeyfile, "remmina_pref", "confirm_close", NULL))
289  remmina_pref.confirm_close = g_key_file_get_boolean(gkeyfile, "remmina_pref", "confirm_close", NULL);
290  else
292 
293  if (extrahardening)
294  remmina_pref.confirm_close = FALSE;
295 
296  if (g_key_file_has_key(gkeyfile, "remmina_pref", "use_master_password", NULL)) {
297  remmina_pref.use_primary_password = g_key_file_get_boolean(gkeyfile, "remmina_pref", "use_master_password", NULL);
298  } else if (g_key_file_has_key(gkeyfile, "remmina_pref", "use_primary_password", NULL))
299  remmina_pref.use_primary_password = g_key_file_get_boolean(gkeyfile, "remmina_pref", "use_primary_password", NULL);
300  else
302 
303  if (g_key_file_has_key(gkeyfile, "remmina_pref", "unlock_timeout", NULL))
304  remmina_pref.unlock_timeout = g_key_file_get_integer(gkeyfile, "remmina_pref", "unlock_timeout", NULL);
305  else
307 
308  if (g_key_file_has_key(gkeyfile, "remmina_pref", "unlock_password", NULL))
309  remmina_pref.unlock_password = g_key_file_get_string(gkeyfile, "remmina_pref", "unlock_password", NULL);
310  else
311  remmina_pref.unlock_password = g_strdup("");
312 
313  if (g_key_file_has_key(gkeyfile, "remmina_pref", "lock_connect", NULL))
314  remmina_pref.lock_connect = g_key_file_get_boolean(gkeyfile, "remmina_pref", "lock_connect", NULL);
315  else
316  remmina_pref.lock_connect = FALSE;
317 
318  if (g_key_file_has_key(gkeyfile, "remmina_pref", "lock_edit", NULL))
319  remmina_pref.lock_edit = g_key_file_get_boolean(gkeyfile, "remmina_pref", "lock_edit", NULL);
320  else
321  remmina_pref.lock_edit = FALSE;
322 
323 
324  if (g_key_file_has_key(gkeyfile, "remmina_pref", "lock_view_passwords", NULL))
325  remmina_pref.lock_view_passwords = g_key_file_get_boolean(gkeyfile, "remmina_pref", "lock_view_passwords", NULL);
326  else
328 
329  if (g_key_file_has_key(gkeyfile, "remmina_pref", "enc_mode", NULL))
330  remmina_pref.enc_mode = g_key_file_get_integer(gkeyfile, "remmina_pref", "enc_mode", NULL);
331  else
333 
334  if (g_key_file_has_key(gkeyfile, "remmina_pref", "audit", NULL))
335  remmina_pref.audit = g_key_file_get_boolean(gkeyfile, "remmina_pref", "audit", NULL);
336  else
337  remmina_pref.audit = FALSE;
338 
339  if (g_key_file_has_key(gkeyfile, "remmina_pref", "trust_all", NULL))
340  remmina_pref.trust_all = g_key_file_get_boolean(gkeyfile, "remmina_pref", "trust_all", NULL);
341  else
342  remmina_pref.trust_all = FALSE;
343 
344  if (g_key_file_has_key(gkeyfile, "remmina_pref", "fullscreen_on_auto", NULL))
345  remmina_pref.fullscreen_on_auto = g_key_file_get_boolean(gkeyfile, "remmina_pref", "fullscreen_on_auto", NULL);
346  else
348 
349  if (g_key_file_has_key(gkeyfile, "remmina_pref", "floating_toolbar_placement", NULL))
350  remmina_pref.floating_toolbar_placement = g_key_file_get_integer(gkeyfile, "remmina_pref", "floating_toolbar_placement", NULL);
351  else
353 
354  if (g_key_file_has_key(gkeyfile, "remmina_pref", "prevent_snap_welcome_message", NULL))
355  remmina_pref.prevent_snap_welcome_message = g_key_file_get_boolean(gkeyfile, "remmina_pref", "prevent_snap_welcome_message", NULL);
356  else
358 
359  if (g_key_file_has_key(gkeyfile, "remmina_pref", "last_quickconnect_protocol", NULL))
360  remmina_pref.last_quickconnect_protocol = g_key_file_get_string(gkeyfile, "remmina_pref", "last_quickconnect_protocol", NULL);
361  else
363 
364  if (g_key_file_has_key(gkeyfile, "remmina_pref", "toolbar_placement", NULL))
365  remmina_pref.toolbar_placement = g_key_file_get_integer(gkeyfile, "remmina_pref", "toolbar_placement", NULL);
366  else
368 
369  if (g_key_file_has_key(gkeyfile, "remmina_pref", "always_show_tab", NULL))
370  remmina_pref.always_show_tab = g_key_file_get_boolean(gkeyfile, "remmina_pref", "always_show_tab", NULL);
371  else
373 
374  if (extrahardening)
376 
377  if (g_key_file_has_key(gkeyfile, "remmina_pref", "always_show_notes", NULL))
378  remmina_pref.always_show_notes = g_key_file_get_boolean(gkeyfile, "remmina_pref", "always_show_notes", NULL);
379  else
381 
382  if (g_key_file_has_key(gkeyfile, "remmina_pref", "hide_connection_toolbar", NULL))
383  remmina_pref.hide_connection_toolbar = g_key_file_get_boolean(gkeyfile, "remmina_pref",
384  "hide_connection_toolbar", NULL);
385  else
387 
388  if (disabletoolbar)
390 
391  if (g_key_file_has_key(gkeyfile, "remmina_pref", "hide_searchbar", NULL))
392  remmina_pref.hide_searchbar = g_key_file_get_boolean(gkeyfile, "remmina_pref",
393  "hide_searchbar", NULL);
394  else
396 
397  if (extrahardening)
399 
400  if (g_key_file_has_key(gkeyfile, "remmina_pref", "default_action", NULL))
401  remmina_pref.default_action = g_key_file_get_integer(gkeyfile, "remmina_pref", "default_action", NULL);
402  else
404 
405  if (g_key_file_has_key(gkeyfile, "remmina_pref", "scale_quality", NULL))
406  remmina_pref.scale_quality = g_key_file_get_integer(gkeyfile, "remmina_pref", "scale_quality", NULL);
407  else
408  remmina_pref.scale_quality = GDK_INTERP_HYPER;
409 
410  if (g_key_file_has_key(gkeyfile, "remmina_pref", "hide_toolbar", NULL))
411  remmina_pref.hide_toolbar = g_key_file_get_boolean(gkeyfile, "remmina_pref", "hide_toolbar", NULL);
412  else
413  remmina_pref.hide_toolbar = FALSE;
414 
415  if (g_key_file_has_key(gkeyfile, "remmina_pref", "small_toolbutton", NULL))
416  remmina_pref.small_toolbutton = g_key_file_get_boolean(gkeyfile, "remmina_pref", "small_toolbutton", NULL);
417  else
419 
420  if (g_key_file_has_key(gkeyfile, "remmina_pref", "view_file_mode", NULL))
421  remmina_pref.view_file_mode = g_key_file_get_integer(gkeyfile, "remmina_pref", "view_file_mode", NULL);
422  else
424 
425  if (g_key_file_has_key(gkeyfile, "remmina_pref", "resolutions", NULL))
426  remmina_pref.resolutions = g_key_file_get_string(gkeyfile, "remmina_pref", "resolutions", NULL);
427  else
429 
430  if (g_key_file_has_key(gkeyfile, "remmina_pref", "keystrokes", NULL))
431  remmina_pref.keystrokes = g_key_file_get_string(gkeyfile, "remmina_pref", "keystrokes", NULL);
432  else
434 
435  if (g_key_file_has_key(gkeyfile, "remmina_pref", "main_width", NULL))
436  remmina_pref.main_width = MAX(600, g_key_file_get_integer(gkeyfile, "remmina_pref", "main_width", NULL));
437  else
438  remmina_pref.main_width = 600;
439 
440  if (g_key_file_has_key(gkeyfile, "remmina_pref", "main_height", NULL))
441  remmina_pref.main_height = MAX(400, g_key_file_get_integer(gkeyfile, "remmina_pref", "main_height", NULL));
442  else
444 
445  if (g_key_file_has_key(gkeyfile, "remmina_pref", "main_maximize", NULL))
446  remmina_pref.main_maximize = g_key_file_get_boolean(gkeyfile, "remmina_pref", "main_maximize", NULL);
447  else
448  remmina_pref.main_maximize = FALSE;
449 
450  if (g_key_file_has_key(gkeyfile, "remmina_pref", "main_sort_column_id", NULL))
451  remmina_pref.main_sort_column_id = g_key_file_get_integer(gkeyfile, "remmina_pref", "main_sort_column_id",
452  NULL);
453  else
455 
456  if (g_key_file_has_key(gkeyfile, "remmina_pref", "main_sort_order", NULL))
457  remmina_pref.main_sort_order = g_key_file_get_integer(gkeyfile, "remmina_pref", "main_sort_order", NULL);
458  else
460 
461  if (g_key_file_has_key(gkeyfile, "remmina_pref", "expanded_group", NULL))
462  remmina_pref.expanded_group = g_key_file_get_string(gkeyfile, "remmina_pref", "expanded_group", NULL);
463  else
464  remmina_pref.expanded_group = g_strdup("");
465 
466  if (g_key_file_has_key(gkeyfile, "remmina_pref", "toolbar_pin_down", NULL))
467  remmina_pref.toolbar_pin_down = g_key_file_get_boolean(gkeyfile, "remmina_pref", "toolbar_pin_down", NULL);
468  else
470 
471  if (g_key_file_has_key(gkeyfile, "remmina_pref", "ssh_loglevel", NULL))
472  remmina_pref.ssh_loglevel = g_key_file_get_integer(gkeyfile, "remmina_pref", "ssh_loglevel", NULL);
473  else
474  remmina_pref.ssh_loglevel = DEFAULT_SSH_LOGLEVEL;
475 
476  if (g_key_file_has_key(gkeyfile, "remmina_pref", "deny_screenshot_clipboard", NULL))
477  remmina_pref.deny_screenshot_clipboard = g_key_file_get_boolean(gkeyfile, "remmina_pref", "deny_screenshot_clipboard", NULL);
478  else
480 
481  if (g_key_file_has_key(gkeyfile, "remmina_pref", "datadir_path", NULL))
482  remmina_pref.datadir_path = g_key_file_get_string(gkeyfile, "remmina_pref", "datadir_path", NULL);
483  else
484  remmina_pref.datadir_path = g_strdup("");
485 
486  if (g_key_file_has_key(gkeyfile, "remmina_pref", "remmina_file_name", NULL))
487  remmina_pref.remmina_file_name = g_key_file_get_string(gkeyfile, "remmina_pref", "remmina_file_name", NULL);
488  else
489  remmina_pref.remmina_file_name = g_strdup("%G_%P_%N_%h");
490 
491  if (g_key_file_has_key(gkeyfile, "remmina_pref", "screenshot_path", NULL)) {
492  remmina_pref.screenshot_path = g_key_file_get_string(gkeyfile, "remmina_pref", "screenshot_path", NULL);
493  } else {
494  remmina_pref.screenshot_path = g_get_user_special_dir(G_USER_DIRECTORY_PICTURES);
495  if (remmina_pref.screenshot_path == NULL)
496  remmina_pref.screenshot_path = g_get_home_dir();
497  }
498 
499  if (g_key_file_has_key(gkeyfile, "remmina_pref", "screenshot_name", NULL))
500  remmina_pref.screenshot_name = g_key_file_get_string(gkeyfile, "remmina_pref", "screenshot_name", NULL);
501  else
502  remmina_pref.screenshot_name = g_strdup("remmina_%p_%h_%Y%m%d-%H%M%S");
503 
504  if (g_key_file_has_key(gkeyfile, "remmina_pref", "ssh_parseconfig", NULL))
505  remmina_pref.ssh_parseconfig = g_key_file_get_boolean(gkeyfile, "remmina_pref", "ssh_parseconfig", NULL);
506  else
507  remmina_pref.ssh_parseconfig = DEFAULT_SSH_PARSECONFIG;
508 
509  if (g_key_file_has_key(gkeyfile, "remmina_pref", "sshtunnel_port", NULL))
510  remmina_pref.sshtunnel_port = g_key_file_get_integer(gkeyfile, "remmina_pref", "sshtunnel_port", NULL);
511  else
512  remmina_pref.sshtunnel_port = DEFAULT_SSHTUNNEL_PORT;
513 
514  if (g_key_file_has_key(gkeyfile, "remmina_pref", "ssh_tcp_keepidle", NULL))
515  remmina_pref.ssh_tcp_keepidle = g_key_file_get_integer(gkeyfile, "remmina_pref", "ssh_tcp_keepidle", NULL);
516  else
517  remmina_pref.ssh_tcp_keepidle = SSH_SOCKET_TCP_KEEPIDLE;
518 
519  if (g_key_file_has_key(gkeyfile, "remmina_pref", "ssh_tcp_keepintvl", NULL))
520  remmina_pref.ssh_tcp_keepintvl = g_key_file_get_integer(gkeyfile, "remmina_pref", "ssh_tcp_keepintvl", NULL);
521  else
522  remmina_pref.ssh_tcp_keepintvl = SSH_SOCKET_TCP_KEEPINTVL;
523 
524  if (g_key_file_has_key(gkeyfile, "remmina_pref", "ssh_tcp_keepcnt", NULL))
525  remmina_pref.ssh_tcp_keepcnt = g_key_file_get_integer(gkeyfile, "remmina_pref", "ssh_tcp_keepcnt", NULL);
526  else
527  remmina_pref.ssh_tcp_keepcnt = SSH_SOCKET_TCP_KEEPCNT;
528 
529  if (g_key_file_has_key(gkeyfile, "remmina_pref", "ssh_tcp_usrtimeout", NULL))
530  remmina_pref.ssh_tcp_usrtimeout = g_key_file_get_integer(gkeyfile, "remmina_pref", "ssh_tcp_usrtimeout", NULL);
531  else
532  remmina_pref.ssh_tcp_usrtimeout = SSH_SOCKET_TCP_USER_TIMEOUT;
533 
534  if (g_key_file_has_key(gkeyfile, "remmina_pref", "applet_new_ontop", NULL))
535  remmina_pref.applet_new_ontop = g_key_file_get_boolean(gkeyfile, "remmina_pref", "applet_new_ontop", NULL);
536  else
538 
539  if (g_key_file_has_key(gkeyfile, "remmina_pref", "applet_hide_count", NULL))
540  remmina_pref.applet_hide_count = g_key_file_get_boolean(gkeyfile, "remmina_pref", "applet_hide_count", NULL);
541  else
543 
544  if (g_key_file_has_key(gkeyfile, "remmina_pref", "applet_enable_avahi", NULL))
545  remmina_pref.applet_enable_avahi = g_key_file_get_boolean(gkeyfile, "remmina_pref", "applet_enable_avahi",
546  NULL);
547  else
549 
550  if (g_key_file_has_key(gkeyfile, "remmina_pref", "disable_tray_icon", NULL))
551  remmina_pref.disable_tray_icon = g_key_file_get_boolean(gkeyfile, "remmina_pref", "disable_tray_icon", NULL);
552  else
554 
555  if (disabletrayicon)
557 
558  if (g_key_file_has_key(gkeyfile, "remmina_pref", "dark_theme", NULL))
559  remmina_pref.dark_theme = g_key_file_get_boolean(gkeyfile, "remmina_pref", "dark_theme", NULL);
560  else
561  remmina_pref.dark_theme = FALSE;
562 
563  if (g_key_file_has_key(gkeyfile, "remmina_pref", "list_refresh_workaround", NULL))
564  remmina_pref.list_refresh_workaround = g_key_file_get_boolean(gkeyfile, "remmina_pref", "list_refresh_workaround", NULL);
565  else
567 
568  if (g_key_file_has_key(gkeyfile, "remmina_pref", "grab_color_switch", NULL))
569  remmina_pref.grab_color_switch = g_key_file_get_boolean(gkeyfile, "remmina_pref", "grab_color_switch", NULL);
570  else
572 
573  if (g_key_file_has_key(gkeyfile, "remmina_pref", "grab_color", NULL))
574  remmina_pref.grab_color = g_key_file_get_string(gkeyfile, "remmina_pref", "grab_color", NULL);
575  else
576  remmina_pref.grab_color = "#00ff00";
577 
578  if (g_key_file_has_key(gkeyfile, "remmina_pref", "recent_maximum", NULL))
579  remmina_pref.recent_maximum = g_key_file_get_integer(gkeyfile, "remmina_pref", "recent_maximum", NULL);
580  else
582 
583  if (g_key_file_has_key(gkeyfile, "remmina_pref", "default_mode", NULL))
584  remmina_pref.default_mode = g_key_file_get_integer(gkeyfile, "remmina_pref", "default_mode", NULL);
585  else
587 
588  if (fullscreen)
590 
591  if (g_key_file_has_key(gkeyfile, "remmina_pref", "tab_mode", NULL))
592  remmina_pref.tab_mode = g_key_file_get_integer(gkeyfile, "remmina_pref", "tab_mode", NULL);
593  else
595 
596  if (g_key_file_has_key(gkeyfile, "remmina_pref", "fullscreen_toolbar_visibility", NULL))
597  remmina_pref.fullscreen_toolbar_visibility = g_key_file_get_integer(gkeyfile, "remmina_pref", "fullscreen_toolbar_visibility", NULL);
598  else
600 
601  if (disabletoolbar)
603 
604  if (g_key_file_has_key(gkeyfile, "remmina_pref", "auto_scroll_step", NULL))
605  remmina_pref.auto_scroll_step = g_key_file_get_integer(gkeyfile, "remmina_pref", "auto_scroll_step", NULL);
606  else
608 
609  if (g_key_file_has_key(gkeyfile, "remmina_pref", "hostkey", NULL))
610  remmina_pref.hostkey = g_key_file_get_integer(gkeyfile, "remmina_pref", "hostkey", NULL);
611  else
612  remmina_pref.hostkey = GDK_KEY_Control_R;
613 
614  if (g_key_file_has_key(gkeyfile, "remmina_pref", "shortcutkey_fullscreen", NULL))
615  remmina_pref.shortcutkey_fullscreen = g_key_file_get_integer(gkeyfile, "remmina_pref", "shortcutkey_fullscreen",
616  NULL);
617  else
619 
620  if (g_key_file_has_key(gkeyfile, "remmina_pref", "shortcutkey_autofit", NULL))
621  remmina_pref.shortcutkey_autofit = g_key_file_get_integer(gkeyfile, "remmina_pref", "shortcutkey_autofit",
622  NULL);
623  else
624  remmina_pref.shortcutkey_autofit = GDK_KEY_1;
625 
626  if (g_key_file_has_key(gkeyfile, "remmina_pref", "shortcutkey_nexttab", NULL))
627  remmina_pref.shortcutkey_nexttab = g_key_file_get_integer(gkeyfile, "remmina_pref", "shortcutkey_nexttab",
628  NULL);
629  else
630  remmina_pref.shortcutkey_nexttab = GDK_KEY_Right;
631 
632  if (g_key_file_has_key(gkeyfile, "remmina_pref", "shortcutkey_prevtab", NULL))
633  remmina_pref.shortcutkey_prevtab = g_key_file_get_integer(gkeyfile, "remmina_pref", "shortcutkey_prevtab",
634  NULL);
635  else
636  remmina_pref.shortcutkey_prevtab = GDK_KEY_Left;
637 
638  if (g_key_file_has_key(gkeyfile, "remmina_pref", "shortcutkey_scale", NULL))
639  remmina_pref.shortcutkey_scale = g_key_file_get_integer(gkeyfile, "remmina_pref", "shortcutkey_scale", NULL);
640  else
641  remmina_pref.shortcutkey_scale = GDK_KEY_s;
642 
643  if (g_key_file_has_key(gkeyfile, "remmina_pref", "shortcutkey_viewonly", NULL))
644  remmina_pref.shortcutkey_viewonly = g_key_file_get_integer(gkeyfile, "remmina_pref", "shortcutkey_viewonly", NULL);
645  else
647 
648  if (g_key_file_has_key(gkeyfile, "remmina_pref", "shortcutkey_multimon", NULL))
649  remmina_pref.shortcutkey_multimon = g_key_file_get_integer(gkeyfile, "remmina_pref", "shortcutkey_multimon", NULL);
650  else
651  remmina_pref.shortcutkey_multimon = GDK_KEY_Page_Up;
652 
653  if (g_key_file_has_key(gkeyfile, "remmina_pref", "shortcutkey_grab", NULL))
654  remmina_pref.shortcutkey_grab = g_key_file_get_integer(gkeyfile, "remmina_pref", "shortcutkey_grab", NULL);
655  else
656  remmina_pref.shortcutkey_grab = GDK_KEY_Control_R;
657 
658  if (g_key_file_has_key(gkeyfile, "remmina_pref", "shortcutkey_minimize", NULL))
659  remmina_pref.shortcutkey_minimize = g_key_file_get_integer(gkeyfile, "remmina_pref", "shortcutkey_minimize", NULL);
660  else
661  remmina_pref.shortcutkey_minimize = GDK_KEY_F9;
662 
663  if (g_key_file_has_key(gkeyfile, "remmina_pref", "shortcutkey_screenshot", NULL))
664  remmina_pref.shortcutkey_screenshot = g_key_file_get_integer(gkeyfile, "remmina_pref", "shortcutkey_screenshot", NULL);
665  else
666  remmina_pref.shortcutkey_screenshot = GDK_KEY_F12;
667 
668  if (g_key_file_has_key(gkeyfile, "remmina_pref", "shortcutkey_disconnect", NULL))
669  remmina_pref.shortcutkey_disconnect = g_key_file_get_integer(gkeyfile, "remmina_pref", "shortcutkey_disconnect",
670  NULL);
671  else
673 
674  if (g_key_file_has_key(gkeyfile, "remmina_pref", "shortcutkey_toolbar", NULL))
675  remmina_pref.shortcutkey_toolbar = g_key_file_get_integer(gkeyfile, "remmina_pref", "shortcutkey_toolbar",
676  NULL);
677  else
678  remmina_pref.shortcutkey_toolbar = GDK_KEY_t;
679 
680  if (g_key_file_has_key(gkeyfile, "remmina_pref", "secret", NULL))
681  remmina_pref.secret = g_key_file_get_string(gkeyfile, "remmina_pref", "secret", NULL);
682  else
683  remmina_pref.secret = NULL;
684 
685  if (g_key_file_has_key(gkeyfile, "remmina_pref", "uid", NULL))
686  remmina_pref.uid = g_key_file_get_string(gkeyfile, "remmina_pref", "uid", NULL);
687  else
688  remmina_pref.uid = NULL;
689 
690  if (g_key_file_has_key(gkeyfile, "remmina_pref", "vte_font", NULL))
691  remmina_pref.vte_font = g_key_file_get_string(gkeyfile, "remmina_pref", "vte_font", NULL);
692  else
694 
695  if (g_key_file_has_key(gkeyfile, "remmina_pref", "vte_allow_bold_text", NULL))
696  remmina_pref.vte_allow_bold_text = g_key_file_get_boolean(gkeyfile, "remmina_pref", "vte_allow_bold_text",
697  NULL);
698  else
700 
701  if (g_key_file_has_key(gkeyfile, "remmina_pref", "vte_lines", NULL))
702  remmina_pref.vte_lines = g_key_file_get_integer(gkeyfile, "remmina_pref", "vte_lines", NULL);
703  else
704  remmina_pref.vte_lines = 512;
705 
706  if (g_key_file_has_key(gkeyfile, "remmina_pref", "vte_shortcutkey_copy", NULL))
707  remmina_pref.vte_shortcutkey_copy = g_key_file_get_integer(gkeyfile, "remmina_pref", "vte_shortcutkey_copy",
708  NULL);
709  else
711 
712  if (g_key_file_has_key(gkeyfile, "remmina_pref", "vte_shortcutkey_paste", NULL))
713  remmina_pref.vte_shortcutkey_paste = g_key_file_get_integer(gkeyfile, "remmina_pref", "vte_shortcutkey_paste",
714  NULL);
715  else
717 
718  if (g_key_file_has_key(gkeyfile, "remmina_pref", "vte_shortcutkey_select_all", NULL))
719  remmina_pref.vte_shortcutkey_select_all = g_key_file_get_integer(gkeyfile, "remmina_pref", "vte_shortcutkey_select_all",
720  NULL);
721  else
723 
724  if (g_key_file_has_key(gkeyfile, "remmina_pref", "vte_shortcutkey_increase_font", NULL))
725  remmina_pref.vte_shortcutkey_increase_font = g_key_file_get_integer(gkeyfile, "remmina_pref", "vte_shortcutkey_increase_font",
726  NULL);
727  else
729 
730  if (g_key_file_has_key(gkeyfile, "remmina_pref", "vte_shortcutkey_decrease_font", NULL))
731  remmina_pref.vte_shortcutkey_decrease_font = g_key_file_get_integer(gkeyfile, "remmina_pref", "vte_shortcutkey_decrease_font",
732  NULL);
733  else
734  remmina_pref.vte_shortcutkey_decrease_font = GDK_KEY_Page_Down;
735 
736  if (g_key_file_has_key(gkeyfile, "remmina_pref", "vte_shortcutkey_search_text", NULL))
737  remmina_pref.vte_shortcutkey_search_text = g_key_file_get_integer(gkeyfile, "remmina_pref", "vte_shortcutkey_search_text",
738  NULL);
739  else
741 
742 
744 
745  /* If we have a color scheme file, we switch to it, GIO will merge it in the
746  * remmina.pref file */
747  if (g_file_test(remmina_colors_file, G_FILE_TEST_IS_REGULAR)) {
748  g_key_file_load_from_file(gkeyfile, remmina_colors_file, G_KEY_FILE_NONE, NULL);
749  g_remove(remmina_colors_file);
750  }
751 
752  /* Default settings */
753  if (!g_key_file_has_key(gkeyfile, "remmina", "name", NULL)) {
754  g_key_file_set_string(gkeyfile, "remmina", "name", "");
755  g_key_file_set_integer(gkeyfile, "remmina", "ignore-tls-errors", 1);
756  g_key_file_set_integer(gkeyfile, "remmina", "enable-plugins", 1);
758  }
759 
760  g_key_file_free(gkeyfile);
761 
762  if (remmina_pref.secret == NULL)
764 
766 }
767 
768 gboolean remmina_pref_is_rw(void)
769 {
770  TRACE_CALL(__func__);
771  if (access(remmina_pref_file, W_OK) == 0)
772  return TRUE;
773  else
774  return FALSE;
775  return FALSE;
776 }
777 
778 gboolean remmina_pref_save(void)
779 {
780  TRACE_CALL(__func__);
781 
782  if (remmina_pref_is_rw() == FALSE) {
783  g_debug("remmina.pref is not writable, returning");
784  return FALSE;
785  }
786  GKeyFile *gkeyfile;
787  GError *error = NULL;
788  g_autofree gchar *content = NULL;
789  gsize length;
790 
791  gkeyfile = g_key_file_new();
792 
793  g_key_file_load_from_file(gkeyfile, remmina_pref_file, G_KEY_FILE_NONE, NULL);
794 
795  g_key_file_set_string(gkeyfile, "remmina_pref", "datadir_path", remmina_pref.datadir_path);
796  g_key_file_set_string(gkeyfile, "remmina_pref", "remmina_file_name", remmina_pref.remmina_file_name);
797  g_key_file_set_string(gkeyfile, "remmina_pref", "screenshot_path", remmina_pref.screenshot_path);
798  g_key_file_set_string(gkeyfile, "remmina_pref", "screenshot_name", remmina_pref.screenshot_name);
799  g_key_file_set_boolean(gkeyfile, "remmina_pref", "deny_screenshot_clipboard", remmina_pref.deny_screenshot_clipboard);
800  g_key_file_set_boolean(gkeyfile, "remmina_pref", "save_view_mode", remmina_pref.save_view_mode);
801  g_key_file_set_boolean(gkeyfile, "remmina_pref", "confirm_close", remmina_pref.confirm_close);
802  if (g_key_file_remove_key(gkeyfile, "remmina_pref", "use_master_password", NULL))
803  REMMINA_DEBUG("use_master_password removed…");
804  else
805  REMMINA_INFO("use_master_password already migrated");
806 #if SODIUM_VERSION_INT >= 90200
807  g_key_file_set_boolean(gkeyfile, "remmina_pref", "use_primary_password", remmina_pref.use_primary_password);
808  g_key_file_set_integer(gkeyfile, "remmina_pref", "unlock_timeout", remmina_pref.unlock_timeout);
809  g_key_file_set_string(gkeyfile, "remmina_pref", "unlock_password", remmina_pref.unlock_password);
810  g_key_file_set_boolean(gkeyfile, "remmina_pref", "lock_connect", remmina_pref.lock_connect);
811  g_key_file_set_boolean(gkeyfile, "remmina_pref", "lock_edit", remmina_pref.lock_edit);
812  g_key_file_set_boolean(gkeyfile, "remmina_pref", "lock_view_passwords", remmina_pref.lock_view_passwords);
813 #else
814  g_key_file_set_boolean(gkeyfile, "remmina_pref", "use_primary_password", FALSE);
815  g_key_file_set_integer(gkeyfile, "remmina_pref", "unlock_timeout", 0);
816  g_key_file_set_string(gkeyfile, "remmina_pref", "unlock_password", g_strdup(""));
817  g_key_file_set_boolean(gkeyfile, "remmina_pref", "lock_connect", FALSE);
818  g_key_file_set_boolean(gkeyfile, "remmina_pref", "lock_edit", FALSE);
819  g_key_file_set_boolean(gkeyfile, "remmina_pref", "lock_view_passwords", FALSE);
820 #endif
821  g_key_file_set_integer(gkeyfile, "remmina_pref", "enc_mode", remmina_pref.enc_mode);
822  g_key_file_set_boolean(gkeyfile, "remmina_pref", "audit", remmina_pref.audit);
823  g_key_file_set_boolean(gkeyfile, "remmina_pref", "trust_all", remmina_pref.trust_all);
824  g_key_file_set_integer(gkeyfile, "remmina_pref", "floating_toolbar_placement", remmina_pref.floating_toolbar_placement);
825  g_key_file_set_integer(gkeyfile, "remmina_pref", "toolbar_placement", remmina_pref.toolbar_placement);
826  g_key_file_set_boolean(gkeyfile, "remmina_pref", "prevent_snap_welcome_message", remmina_pref.prevent_snap_welcome_message);
827  g_key_file_set_string(gkeyfile, "remmina_pref", "last_quickconnect_protocol", remmina_pref.last_quickconnect_protocol);
828  g_key_file_set_boolean(gkeyfile, "remmina_pref", "fullscreen_on_auto", remmina_pref.fullscreen_on_auto);
829  g_key_file_set_boolean(gkeyfile, "remmina_pref", "always_show_tab", remmina_pref.always_show_tab);
830  g_key_file_set_boolean(gkeyfile, "remmina_pref", "always_show_notes", remmina_pref.always_show_notes);
831  g_key_file_set_boolean(gkeyfile, "remmina_pref", "hide_connection_toolbar", remmina_pref.hide_connection_toolbar);
832  g_key_file_set_boolean(gkeyfile, "remmina_pref", "hide_searchbar", remmina_pref.hide_searchbar);
833  g_key_file_set_integer(gkeyfile, "remmina_pref", "default_action", remmina_pref.default_action);
834  g_key_file_set_integer(gkeyfile, "remmina_pref", "scale_quality", remmina_pref.scale_quality);
835  g_key_file_set_integer(gkeyfile, "remmina_pref", "ssh_loglevel", remmina_pref.ssh_loglevel);
836  g_key_file_set_boolean(gkeyfile, "remmina_pref", "ssh_parseconfig", remmina_pref.ssh_parseconfig);
837  g_key_file_set_boolean(gkeyfile, "remmina_pref", "hide_toolbar", remmina_pref.hide_toolbar);
838  g_key_file_set_boolean(gkeyfile, "remmina_pref", "small_toolbutton", remmina_pref.small_toolbutton);
839  g_key_file_set_integer(gkeyfile, "remmina_pref", "view_file_mode", remmina_pref.view_file_mode);
840  g_key_file_set_string(gkeyfile, "remmina_pref", "resolutions", remmina_pref.resolutions);
841  g_key_file_set_string(gkeyfile, "remmina_pref", "keystrokes", remmina_pref.keystrokes);
842  g_key_file_set_integer(gkeyfile, "remmina_pref", "main_width", remmina_pref.main_width);
843  g_key_file_set_integer(gkeyfile, "remmina_pref", "main_height", remmina_pref.main_height);
844  g_key_file_set_boolean(gkeyfile, "remmina_pref", "main_maximize", remmina_pref.main_maximize);
845  g_key_file_set_integer(gkeyfile, "remmina_pref", "main_sort_column_id", remmina_pref.main_sort_column_id);
846  g_key_file_set_integer(gkeyfile, "remmina_pref", "main_sort_order", remmina_pref.main_sort_order);
847  g_key_file_set_string(gkeyfile, "remmina_pref", "expanded_group", remmina_pref.expanded_group);
848  g_key_file_set_boolean(gkeyfile, "remmina_pref", "toolbar_pin_down", remmina_pref.toolbar_pin_down);
849  g_key_file_set_integer(gkeyfile, "remmina_pref", "sshtunnel_port", remmina_pref.sshtunnel_port);
850  g_key_file_set_integer(gkeyfile, "remmina_pref", "ssh_tcp_keepidle", remmina_pref.ssh_tcp_keepidle);
851  g_key_file_set_integer(gkeyfile, "remmina_pref", "ssh_tcp_keepintvl", remmina_pref.ssh_tcp_keepintvl);
852  g_key_file_set_integer(gkeyfile, "remmina_pref", "ssh_tcp_keepcnt", remmina_pref.ssh_tcp_keepcnt);
853  g_key_file_set_integer(gkeyfile, "remmina_pref", "ssh_tcp_usrtimeout", remmina_pref.ssh_tcp_usrtimeout);
854  g_key_file_set_boolean(gkeyfile, "remmina_pref", "applet_new_ontop", remmina_pref.applet_new_ontop);
855  g_key_file_set_boolean(gkeyfile, "remmina_pref", "applet_hide_count", remmina_pref.applet_hide_count);
856  g_key_file_set_boolean(gkeyfile, "remmina_pref", "applet_enable_avahi", remmina_pref.applet_enable_avahi);
857  g_key_file_set_boolean(gkeyfile, "remmina_pref", "disable_tray_icon", remmina_pref.disable_tray_icon);
858  g_key_file_set_boolean(gkeyfile, "remmina_pref", "dark_theme", remmina_pref.dark_theme);
859  g_key_file_set_integer(gkeyfile, "remmina_pref", "recent_maximum", remmina_pref.recent_maximum);
860  g_key_file_set_integer(gkeyfile, "remmina_pref", "default_mode", remmina_pref.default_mode);
861  g_key_file_set_integer(gkeyfile, "remmina_pref", "tab_mode", remmina_pref.tab_mode);
862  g_key_file_set_integer(gkeyfile, "remmina_pref", "fullscreen_toolbar_visibility", remmina_pref.fullscreen_toolbar_visibility);
863  g_key_file_set_integer(gkeyfile, "remmina_pref", "auto_scroll_step", remmina_pref.auto_scroll_step);
864  g_key_file_set_integer(gkeyfile, "remmina_pref", "hostkey", remmina_pref.hostkey);
865  g_key_file_set_integer(gkeyfile, "remmina_pref", "shortcutkey_fullscreen", remmina_pref.shortcutkey_fullscreen);
866  g_key_file_set_integer(gkeyfile, "remmina_pref", "shortcutkey_autofit", remmina_pref.shortcutkey_autofit);
867  g_key_file_set_integer(gkeyfile, "remmina_pref", "shortcutkey_nexttab", remmina_pref.shortcutkey_nexttab);
868  g_key_file_set_integer(gkeyfile, "remmina_pref", "shortcutkey_prevtab", remmina_pref.shortcutkey_prevtab);
869  g_key_file_set_integer(gkeyfile, "remmina_pref", "shortcutkey_scale", remmina_pref.shortcutkey_scale);
870  g_key_file_set_integer(gkeyfile, "remmina_pref", "shortcutkey_grab", remmina_pref.shortcutkey_grab);
871  g_key_file_set_integer(gkeyfile, "remmina_pref", "shortcutkey_multimon", remmina_pref.shortcutkey_multimon);
872  g_key_file_set_integer(gkeyfile, "remmina_pref", "shortcutkey_viewonly", remmina_pref.shortcutkey_viewonly);
873  g_key_file_set_integer(gkeyfile, "remmina_pref", "shortcutkey_screenshot", remmina_pref.shortcutkey_screenshot);
874  g_key_file_set_integer(gkeyfile, "remmina_pref", "shortcutkey_minimize", remmina_pref.shortcutkey_minimize);
875  g_key_file_set_integer(gkeyfile, "remmina_pref", "shortcutkey_disconnect", remmina_pref.shortcutkey_disconnect);
876  g_key_file_set_integer(gkeyfile, "remmina_pref", "shortcutkey_toolbar", remmina_pref.shortcutkey_toolbar);
877  g_key_file_set_integer(gkeyfile, "remmina_pref", "vte_shortcutkey_copy", remmina_pref.vte_shortcutkey_copy);
878  g_key_file_set_integer(gkeyfile, "remmina_pref", "vte_shortcutkey_paste", remmina_pref.vte_shortcutkey_paste);
879  g_key_file_set_integer(gkeyfile, "remmina_pref", "vte_shortcutkey_select_all", remmina_pref.vte_shortcutkey_select_all);
880  g_key_file_set_integer(gkeyfile, "remmina_pref", "vte_shortcutkey_increase_font", remmina_pref.vte_shortcutkey_increase_font);
881  g_key_file_set_integer(gkeyfile, "remmina_pref", "vte_shortcutkey_decrease_font", remmina_pref.vte_shortcutkey_decrease_font);
882  g_key_file_set_integer(gkeyfile, "remmina_pref", "vte_shortcutkey_search_text", remmina_pref.vte_shortcutkey_search_text);
883  g_key_file_set_string(gkeyfile, "remmina_pref", "vte_font", remmina_pref.vte_font ? remmina_pref.vte_font : "");
884  g_key_file_set_string(gkeyfile, "remmina_pref", "grab_color", remmina_pref.grab_color ? remmina_pref.grab_color : "");
885  g_key_file_set_boolean(gkeyfile, "remmina_pref", "grab_color_switch", remmina_pref.grab_color_switch);
886  g_key_file_set_boolean(gkeyfile, "remmina_pref", "vte_allow_bold_text", remmina_pref.vte_allow_bold_text);
887  g_key_file_set_integer(gkeyfile, "remmina_pref", "vte_lines", remmina_pref.vte_lines);
888  g_key_file_set_string(gkeyfile, "ssh_colors", "background", remmina_pref.color_pref.background ? remmina_pref.color_pref.background : "");
889  g_key_file_set_string(gkeyfile, "ssh_colors", "cursor", remmina_pref.color_pref.cursor ? remmina_pref.color_pref.cursor : "");
890  g_key_file_set_string(gkeyfile, "ssh_colors", "cursor_foreground", remmina_pref.color_pref.cursor_foreground ? remmina_pref.color_pref.cursor_foreground : "");
891  g_key_file_set_string(gkeyfile, "ssh_colors", "highlight", remmina_pref.color_pref.highlight ? remmina_pref.color_pref.highlight : "");
892  g_key_file_set_string(gkeyfile, "ssh_colors", "highlight_foreground", remmina_pref.color_pref.highlight_foreground ? remmina_pref.color_pref.highlight_foreground : "");
893  g_key_file_set_string(gkeyfile, "ssh_colors", "colorBD", remmina_pref.color_pref.colorBD ? remmina_pref.color_pref.colorBD : "");
894  g_key_file_set_string(gkeyfile, "ssh_colors", "foreground", remmina_pref.color_pref.foreground ? remmina_pref.color_pref.foreground : "");
895  g_key_file_set_string(gkeyfile, "ssh_colors", "color0", remmina_pref.color_pref.color0 ? remmina_pref.color_pref.color0 : "");
896  g_key_file_set_string(gkeyfile, "ssh_colors", "color1", remmina_pref.color_pref.color1 ? remmina_pref.color_pref.color1 : "");
897  g_key_file_set_string(gkeyfile, "ssh_colors", "color2", remmina_pref.color_pref.color2 ? remmina_pref.color_pref.color2 : "");
898  g_key_file_set_string(gkeyfile, "ssh_colors", "color3", remmina_pref.color_pref.color3 ? remmina_pref.color_pref.color3 : "");
899  g_key_file_set_string(gkeyfile, "ssh_colors", "color4", remmina_pref.color_pref.color4 ? remmina_pref.color_pref.color4 : "");
900  g_key_file_set_string(gkeyfile, "ssh_colors", "color5", remmina_pref.color_pref.color5 ? remmina_pref.color_pref.color5 : "");
901  g_key_file_set_string(gkeyfile, "ssh_colors", "color6", remmina_pref.color_pref.color6 ? remmina_pref.color_pref.color6 : "");
902  g_key_file_set_string(gkeyfile, "ssh_colors", "color7", remmina_pref.color_pref.color7 ? remmina_pref.color_pref.color7 : "");
903  g_key_file_set_string(gkeyfile, "ssh_colors", "color8", remmina_pref.color_pref.color8 ? remmina_pref.color_pref.color8 : "");
904  g_key_file_set_string(gkeyfile, "ssh_colors", "color9", remmina_pref.color_pref.color9 ? remmina_pref.color_pref.color9 : "");
905  g_key_file_set_string(gkeyfile, "ssh_colors", "color10", remmina_pref.color_pref.color10 ? remmina_pref.color_pref.color10 : "");
906  g_key_file_set_string(gkeyfile, "ssh_colors", "color11", remmina_pref.color_pref.color11 ? remmina_pref.color_pref.color11 : "");
907  g_key_file_set_string(gkeyfile, "ssh_colors", "color12", remmina_pref.color_pref.color12 ? remmina_pref.color_pref.color12 : "");
908  g_key_file_set_string(gkeyfile, "ssh_colors", "color13", remmina_pref.color_pref.color13 ? remmina_pref.color_pref.color13 : "");
909  g_key_file_set_string(gkeyfile, "ssh_colors", "color14", remmina_pref.color_pref.color14 ? remmina_pref.color_pref.color14 : "");
910  g_key_file_set_string(gkeyfile, "ssh_colors", "color15", remmina_pref.color_pref.color15 ? remmina_pref.color_pref.color15 : "");
911 
912  /* Default settings */
913  g_key_file_set_string(gkeyfile, "remmina", "name", "");
914  g_key_file_set_integer(gkeyfile, "remmina", "ignore-tls-errors", 1);
915 
916  content = g_key_file_to_data(gkeyfile, &length, NULL);
917  g_file_set_contents(remmina_pref_file, content, length, &error);
918 
919  if (error != NULL) {
920  g_warning("remmina_pref_save error: %s", error->message);
921  g_clear_error(&error);
922  g_key_file_free(gkeyfile);
923  return FALSE;
924  }
925  g_key_file_free(gkeyfile);
926  return TRUE;
927 }
928 
929 void remmina_pref_add_recent(const gchar *protocol, const gchar *server)
930 {
931  TRACE_CALL(__func__);
932  RemminaStringArray *array;
933  GKeyFile *gkeyfile;
934  gchar key[20];
935  g_autofree gchar *val = NULL;
936  g_autofree gchar *content = NULL;
937  gsize length;
938 
939  if (remmina_pref.recent_maximum <= 0 || server == NULL || server[0] == 0)
940  return;
941 
942  /* Load original value into memory */
943  gkeyfile = g_key_file_new();
944 
945  g_key_file_load_from_file(gkeyfile, remmina_pref_file, G_KEY_FILE_NONE, NULL);
946 
947  g_snprintf(key, sizeof(key), "recent_%s", protocol);
948  array = remmina_string_array_new_from_allocated_string(g_key_file_get_string(gkeyfile, "remmina_pref", key, NULL));
949 
950  /* Add the new value */
951  remmina_string_array_remove(array, server);
952  while (array->len >= remmina_pref.recent_maximum)
954  remmina_string_array_add(array, server);
955 
956  /* Save */
957  val = remmina_string_array_to_string(array);
958  g_key_file_set_string(gkeyfile, "remmina_pref", key, val);
959 
960  content = g_key_file_to_data(gkeyfile, &length, NULL);
961  g_file_set_contents(remmina_pref_file, content, length, NULL);
962 
963  g_key_file_free(gkeyfile);
964 }
965 
966 gchar *
967 remmina_pref_get_recent(const gchar *protocol)
968 {
969  TRACE_CALL(__func__);
970  GKeyFile *gkeyfile;
971  gchar key[20];
972  gchar *val = NULL;
973 
974  gkeyfile = g_key_file_new();
975 
976  g_key_file_load_from_file(gkeyfile, remmina_pref_file, G_KEY_FILE_NONE, NULL);
977 
978  g_snprintf(key, sizeof(key), "recent_%s", protocol);
979  val = g_key_file_get_string(gkeyfile, "remmina_pref", key, NULL);
980 
981  g_key_file_free(gkeyfile);
982 
983  return val;
984 }
985 
987 {
988  TRACE_CALL(__func__);
989  GKeyFile *gkeyfile;
990  gchar **keys;
991  gint i;
992  g_autofree gchar *content = NULL;
993  gsize length;
994 
995  gkeyfile = g_key_file_new();
996 
997  g_key_file_load_from_file(gkeyfile, remmina_pref_file, G_KEY_FILE_NONE, NULL);
998  keys = g_key_file_get_keys(gkeyfile, "remmina_pref", NULL, NULL);
999  if (keys) {
1000  for (i = 0; keys[i]; i++)
1001  if (strncmp(keys[i], "recent_", 7) == 0)
1002  g_key_file_set_string(gkeyfile, "remmina_pref", keys[i], "");
1003  g_strfreev(keys);
1004  }
1005 
1006  content = g_key_file_to_data(gkeyfile, &length, NULL);
1007  g_file_set_contents(remmina_pref_file, content, length, NULL);
1008 
1009  g_key_file_free(gkeyfile);
1010 }
1011 
1012 guint *remmina_pref_keymap_get_table(const gchar *keymap)
1013 {
1014  TRACE_CALL(__func__);
1015 
1016  if (!keymap || keymap[0] == '\0')
1017  return NULL;
1018 
1019  return (guint *)g_hash_table_lookup(remmina_keymap_table, keymap);
1020 }
1021 
1022 guint remmina_pref_keymap_get_keyval(const gchar *keymap, guint keyval)
1023 {
1024  TRACE_CALL(__func__);
1025  guint *table;
1026  gint i;
1027 
1028  if (!keymap || keymap[0] == '\0')
1029  return keyval;
1030 
1031  table = (guint *)g_hash_table_lookup(remmina_keymap_table, keymap);
1032  if (!table)
1033  return keyval;
1034  for (i = 0; table[i] > 0; i += 2)
1035  if (table[i] == keyval)
1036  return table[i + 1];
1037  return keyval;
1038 }
1039 
1040 gchar **
1042 {
1043  TRACE_CALL(__func__);
1044  GList *list;
1045  guint len;
1046  gchar **keys;
1047  guint i;
1048 
1049  list = g_hash_table_get_keys(remmina_keymap_table);
1050  len = g_list_length(list);
1051 
1052  keys = g_new0(gchar *, (len + 1) * 2 + 1);
1053  keys[0] = g_strdup("");
1054  keys[1] = g_strdup("");
1055  for (i = 0; i < len; i++) {
1056  keys[(i + 1) * 2] = g_strdup((gchar *)g_list_nth_data(list, i));
1057  keys[(i + 1) * 2 + 1] = g_strdup((gchar *)g_list_nth_data(list, i));
1058  }
1059  g_list_free(list);
1060 
1061  return keys;
1062 }
1063 
1065 {
1066  TRACE_CALL(__func__);
1067  /* Paranoid programming */
1068  if (remmina_pref.scale_quality < 0)
1070  return remmina_pref.scale_quality;
1071 }
1072 
1074 {
1075  TRACE_CALL(__func__);
1076  return remmina_pref.ssh_loglevel;
1077 }
1078 
1080 {
1081  TRACE_CALL(__func__);
1083 }
1084 
1086 {
1087  TRACE_CALL(__func__);
1089 }
1090 
1092 {
1093  TRACE_CALL(__func__);
1095 }
1096 
1098 {
1099  TRACE_CALL(__func__);
1101 }
1102 
1104 {
1105  TRACE_CALL(__func__);
1107 }
1108 
1110 {
1111  TRACE_CALL(__func__);
1113 }
1114 
1115 void remmina_pref_set_value(const gchar *key, const gchar *value)
1116 {
1117  TRACE_CALL(__func__);
1118  GKeyFile *gkeyfile;
1119  gsize length;
1120 
1121  gkeyfile = g_key_file_new();
1122  if (g_key_file_load_from_file(gkeyfile, remmina_pref_file, G_KEY_FILE_NONE, NULL)) {
1123  g_key_file_set_string(gkeyfile, "remmina_pref", key, value);
1124  gchar *content = g_key_file_to_data(gkeyfile, &length, NULL);
1125  if (g_file_set_contents(remmina_pref_file, content, length, NULL)) {
1126  g_free(content);
1127  } else {
1128  REMMINA_WARNING("Cannot save Remmina preferences");
1129  REMMINA_WARNING("Key was \"%s\", and value \"%s\"", key, value);
1130  }
1131  g_key_file_free(gkeyfile);
1132  } else {
1133  REMMINA_WARNING("Cannot load Remmina preferences file");
1134  }
1135 }
1136 
1137 gchar *remmina_pref_get_value(const gchar *key)
1138 {
1139  TRACE_CALL(__func__);
1140  GKeyFile *gkeyfile;
1141  gchar *value = NULL;
1142 
1143  gkeyfile = g_key_file_new();
1144  g_key_file_load_from_file(gkeyfile, remmina_pref_file, G_KEY_FILE_NONE, NULL);
1145  value = g_key_file_get_string(gkeyfile, "remmina_pref", key, NULL);
1146  g_key_file_free(gkeyfile);
1147 
1148  return value;
1149 }
1150 
1151 gboolean remmina_pref_get_boolean(const gchar *key)
1152 {
1153  TRACE_CALL(__func__);
1154  GKeyFile *gkeyfile;
1155  gboolean value;
1156 
1157  gkeyfile = g_key_file_new();
1158  g_key_file_load_from_file(gkeyfile, remmina_pref_file, G_KEY_FILE_NONE, NULL);
1159  value = g_key_file_get_boolean(gkeyfile, "remmina_pref", key, NULL);
1160  g_key_file_free(gkeyfile);
1161 
1162  return value;
1163 }
guint shortcutkey_fullscreen
Definition: remmina_pref.h:175
gint floating_toolbar_placement
Definition: remmina_pref.h:224
gboolean hide_searchbar
Definition: remmina_pref.h:155
guint vte_shortcutkey_search_text
Definition: remmina_pref.h:209
-
gint remmina_pref_get_scale_quality(void)
+
gint remmina_pref_get_scale_quality(void)
guint shortcutkey_minimize
Definition: remmina_pref.h:185
static void remmina_pref_gen_secret(void)
Definition: remmina_pref.c:73
gboolean lock_connect
Definition: remmina_pref.h:193
-
gchar ** remmina_pref_keymap_groups(void)
+
gchar ** remmina_pref_keymap_groups(void)
const gchar * default_keystrokes
Definition: remmina_pref.c:59
const gchar * grab_color
Definition: remmina_pref.h:159
guint vte_shortcutkey_increase_font
Definition: remmina_pref.h:207
@@ -104,7 +104,7 @@ $(document).ready(function(){initNavTree('remmina__pref_8c_source.html','');});
gint default_action
Definition: remmina_pref.h:141
gchar * remmina_pref_file
Definition: rcw.c:78
G_BEGIN_DECLS typedef GPtrArray RemminaStringArray
-
gint remmina_pref_get_sshtunnel_port(void)
+
gint remmina_pref_get_sshtunnel_port(void)
gchar * keystrokes
Definition: remmina_pref.h:146
@@ -120,13 +120,13 @@ $(document).ready(function(){initNavTree('remmina__pref_8c_source.html','');}); -
gint remmina_pref_get_ssh_loglevel(void)
+
gint remmina_pref_get_ssh_loglevel(void)
gint auto_scroll_step
Definition: remmina_pref.h:143
guint vte_shortcutkey_copy
Definition: remmina_pref.h:204
static guint remmina_pref_get_keyval_from_str(const gchar *str)
Definition: remmina_pref.c:95
-
gchar * remmina_pref_get_recent(const gchar *protocol)
Definition: remmina_pref.c:966
+
gchar * remmina_pref_get_recent(const gchar *protocol)
Definition: remmina_pref.c:967
@@ -137,8 +137,8 @@ $(document).ready(function(){initNavTree('remmina__pref_8c_source.html','');});
gchar * highlight_foreground
Definition: remmina_pref.h:112
gchar * remmina_string_array_to_string(RemminaStringArray *array)
gint scale_quality
Definition: remmina_pref.h:142
-
void remmina_pref_add_recent(const gchar *protocol, const gchar *server)
Definition: remmina_pref.c:928
-
void remmina_pref_set_value(const gchar *key, const gchar *value)
+
void remmina_pref_add_recent(const gchar *protocol, const gchar *server)
Definition: remmina_pref.c:929
+
void remmina_pref_set_value(const gchar *key, const gchar *value)
gboolean deny_screenshot_clipboard
Definition: remmina_pref.h:138
gchar * resolutions
Definition: remmina_pref.h:145
guint vte_shortcutkey_select_all
Definition: remmina_pref.h:206
@@ -146,20 +146,20 @@ $(document).ready(function(){initNavTree('remmina__pref_8c_source.html','');});
gint main_sort_order
Definition: remmina_pref.h:221
gboolean vte_allow_bold_text
Definition: remmina_pref.h:201
-
gchar * remmina_pref_get_value(const gchar *key)
+
gchar * remmina_pref_get_value(const gchar *key)
gboolean disable_tray_icon
Definition: remmina_pref.h:164
gboolean lock_view_passwords
Definition: remmina_pref.h:195
gint recent_maximum
Definition: remmina_pref.h:144
-
gboolean remmina_pref_get_ssh_parseconfig(void)
+
gboolean remmina_pref_get_ssh_parseconfig(void)
static GHashTable * remmina_keymap_table
Definition: remmina_pref.c:62
gchar * vte_font
Definition: remmina_pref.h:200
guint shortcutkey_multimon
Definition: remmina_pref.h:181
const gchar * screenshot_path
Definition: remmina_pref.h:137
void remmina_string_array_remove_index(RemminaStringArray *array, gint i)
-
guint * remmina_pref_keymap_get_table(const gchar *keymap)
+
guint * remmina_pref_keymap_get_table(const gchar *keymap)
gint unlock_timeout
Definition: remmina_pref.h:192
gboolean confirm_close
Definition: remmina_pref.h:147
@@ -186,13 +186,13 @@ $(document).ready(function(){initNavTree('remmina__pref_8c_source.html','');});
RemminaStringArray * remmina_string_array_new_from_allocated_string(gchar *strs)
gboolean fullscreen
Definition: remmina.c:89
-
gboolean remmina_pref_get_boolean(const gchar *key)
+
gboolean remmina_pref_get_boolean(const gchar *key)
gint view_file_mode
Definition: remmina_pref.h:213
-
gint remmina_pref_get_ssh_tcp_keepcnt(void)
-
void remmina_pref_clear_recent(void)
Definition: remmina_pref.c:985
+
gint remmina_pref_get_ssh_tcp_keepcnt(void)
+
void remmina_pref_clear_recent(void)
Definition: remmina_pref.c:986
const gchar * default_resolutions
Definition: remmina_pref.c:58
guint shortcutkey_nexttab
Definition: remmina_pref.h:178
gboolean applet_hide_count
Definition: remmina_pref.h:163
@@ -200,7 +200,7 @@ $(document).ready(function(){initNavTree('remmina__pref_8c_source.html','');});
gint ssh_tcp_keepidle
Definition: remmina_pref.h:169
gboolean lock_edit
Definition: remmina_pref.h:194
-
guint remmina_pref_keymap_get_keyval(const gchar *keymap, guint keyval)
+
guint remmina_pref_keymap_get_keyval(const gchar *keymap, guint keyval)
gboolean hide_toolbar
Definition: remmina_pref.h:211
void remmina_string_array_remove(RemminaStringArray *array, const gchar *str)
RemminaPref remmina_pref
Definition: rcw.c:79
@@ -217,7 +217,7 @@ $(document).ready(function(){initNavTree('remmina__pref_8c_source.html','');});
guint shortcutkey_toolbar
Definition: remmina_pref.h:187
-
gboolean remmina_pref_save(void)
Definition: remmina_pref.c:777
+
gboolean remmina_pref_save(void)
Definition: remmina_pref.c:778
gchar * remmina_colors_file
gint ssh_tcp_keepcnt
Definition: remmina_pref.h:171
gboolean applet_new_ontop
Definition: remmina_pref.h:162
@@ -232,7 +232,7 @@ $(document).ready(function(){initNavTree('remmina__pref_8c_source.html','');});
gchar * cursor_foreground
Definition: remmina_pref.h:110
gboolean extrahardening
Definition: remmina.c:90
-
gboolean remmina_pref_is_rw(void)
Definition: remmina_pref.c:767
+
gboolean remmina_pref_is_rw(void)
Definition: remmina_pref.c:768
gboolean always_show_notes
Definition: remmina_pref.h:153
void remmina_string_array_add(RemminaStringArray *array, const gchar *str)
@@ -245,10 +245,10 @@ $(document).ready(function(){initNavTree('remmina__pref_8c_source.html','');});
gboolean save_view_mode
Definition: remmina_pref.h:140
gint fullscreen_toolbar_visibility
Definition: remmina_pref.h:158
-
gint remmina_pref_get_ssh_tcp_usrtimeout(void)
-
gint remmina_pref_get_ssh_tcp_keepidle(void)
+
gint remmina_pref_get_ssh_tcp_usrtimeout(void)
+
gint remmina_pref_get_ssh_tcp_keepidle(void)
gboolean grab_color_switch
Definition: remmina_pref.h:160
-
gint remmina_pref_get_ssh_tcp_keepintvl(void)
+
gint remmina_pref_get_ssh_tcp_keepintvl(void)
diff --git a/public/remmina__pref_8h.html b/public/remmina__pref_8h.html index 6e43306ca..fde165fe4 100644 --- a/public/remmina__pref_8h.html +++ b/public/remmina__pref_8h.html @@ -455,7 +455,7 @@ Variables
-

Definition at line 928 of file remmina_pref.c.

+

Definition at line 929 of file remmina_pref.c.

@@ -475,7 +475,7 @@ Variables
-

Definition at line 985 of file remmina_pref.c.

+

Definition at line 986 of file remmina_pref.c.

@@ -525,7 +525,7 @@ Variables
-

Definition at line 1150 of file remmina_pref.c.

+

Definition at line 1151 of file remmina_pref.c.

@@ -545,7 +545,7 @@ Variables
-

Definition at line 966 of file remmina_pref.c.

+

Definition at line 967 of file remmina_pref.c.

@@ -565,7 +565,7 @@ Variables
-

Definition at line 1063 of file remmina_pref.c.

+

Definition at line 1064 of file remmina_pref.c.

@@ -585,7 +585,7 @@ Variables
-

Definition at line 1072 of file remmina_pref.c.

+

Definition at line 1073 of file remmina_pref.c.

@@ -605,7 +605,7 @@ Variables
-

Definition at line 1078 of file remmina_pref.c.

+

Definition at line 1079 of file remmina_pref.c.

@@ -625,7 +625,7 @@ Variables
-

Definition at line 1102 of file remmina_pref.c.

+

Definition at line 1103 of file remmina_pref.c.

@@ -645,7 +645,7 @@ Variables
-

Definition at line 1090 of file remmina_pref.c.

+

Definition at line 1091 of file remmina_pref.c.

@@ -665,7 +665,7 @@ Variables
-

Definition at line 1096 of file remmina_pref.c.

+

Definition at line 1097 of file remmina_pref.c.

@@ -685,7 +685,7 @@ Variables
-

Definition at line 1108 of file remmina_pref.c.

+

Definition at line 1109 of file remmina_pref.c.

@@ -705,7 +705,7 @@ Variables
-

Definition at line 1084 of file remmina_pref.c.

+

Definition at line 1085 of file remmina_pref.c.

@@ -725,7 +725,7 @@ Variables
-

Definition at line 1136 of file remmina_pref.c.

+

Definition at line 1137 of file remmina_pref.c.

@@ -765,7 +765,7 @@ Variables
-

Definition at line 767 of file remmina_pref.c.

+

Definition at line 768 of file remmina_pref.c.

@@ -795,7 +795,7 @@ Variables
-

Definition at line 1021 of file remmina_pref.c.

+

Definition at line 1022 of file remmina_pref.c.

@@ -815,7 +815,7 @@ Variables
-

Definition at line 1011 of file remmina_pref.c.

+

Definition at line 1012 of file remmina_pref.c.

@@ -835,7 +835,7 @@ Variables
-

Definition at line 1040 of file remmina_pref.c.

+

Definition at line 1041 of file remmina_pref.c.

@@ -855,7 +855,7 @@ Variables
-

Definition at line 777 of file remmina_pref.c.

+

Definition at line 778 of file remmina_pref.c.

@@ -885,7 +885,7 @@ Variables
-

Definition at line 1114 of file remmina_pref.c.

+

Definition at line 1115 of file remmina_pref.c.

diff --git a/public/remmina__pref_8h_source.html b/public/remmina__pref_8h_source.html index e2fa1eaea..876adc1e5 100644 --- a/public/remmina__pref_8h_source.html +++ b/public/remmina__pref_8h_source.html @@ -91,19 +91,19 @@ $(document).ready(function(){initNavTree('remmina__pref_8h_source.html','');});
gint floating_toolbar_placement
Definition: remmina_pref.h:224
gboolean hide_searchbar
Definition: remmina_pref.h:155
guint vte_shortcutkey_search_text
Definition: remmina_pref.h:209
-
gboolean remmina_pref_get_boolean(const gchar *key)
+
gboolean remmina_pref_get_boolean(const gchar *key)
gint ssh_loglevel
Definition: remmina_pref.h:166
guint shortcutkey_minimize
Definition: remmina_pref.h:185
gboolean lock_connect
Definition: remmina_pref.h:193
Definition: remmina_pref.h:77
-
gint remmina_pref_get_ssh_tcp_keepcnt(void)
-
void remmina_pref_clear_recent(void)
Definition: remmina_pref.c:985
+
gint remmina_pref_get_ssh_tcp_keepcnt(void)
+
void remmina_pref_clear_recent(void)
Definition: remmina_pref.c:986
const gchar * default_resolutions
Definition: remmina_pref.c:58
gboolean vte_system_colors
Definition: remmina_pref.h:202
const gchar * grab_color
Definition: remmina_pref.h:159
guint vte_shortcutkey_increase_font
Definition: remmina_pref.h:207
-
void remmina_pref_set_value(const gchar *key, const gchar *value)
+
void remmina_pref_set_value(const gchar *key, const gchar *value)
Definition: remmina_pref.h:85
Definition: remmina_pref.h:97
gint default_action
Definition: remmina_pref.h:141
@@ -118,7 +118,7 @@ $(document).ready(function(){initNavTree('remmina__pref_8h_source.html','');});
gboolean use_primary_password
Definition: remmina_pref.h:189
guint shortcutkey_prevtab
Definition: remmina_pref.h:177
gboolean ssh_parseconfig
Definition: remmina_pref.h:167
-
gchar * remmina_pref_get_value(const gchar *key)
+
gchar * remmina_pref_get_value(const gchar *key)
Definition: remmina_pref.h:106
gchar * color0
Definition: remmina_pref.h:115
gint ssh_tcp_keepintvl
Definition: remmina_pref.h:170
@@ -138,9 +138,9 @@ $(document).ready(function(){initNavTree('remmina__pref_8h_source.html','');});
gchar * last_success
Definition: remmina_pref.h:238
Definition: remmina_pref.h:54
guint shortcutkey_autofit
Definition: remmina_pref.h:176
-
gboolean remmina_pref_is_rw(void)
Definition: remmina_pref.c:767
+
gboolean remmina_pref_is_rw(void)
Definition: remmina_pref.c:768
gchar * secret
Definition: remmina_pref.h:230
-
guint remmina_pref_keymap_get_keyval(const gchar *keymap, guint keyval)
+
guint remmina_pref_keymap_get_keyval(const gchar *keymap, guint keyval)
gchar * color12
Definition: remmina_pref.h:127
gint main_width
Definition: remmina_pref.h:217
gchar * highlight_foreground
Definition: remmina_pref.h:112
@@ -166,8 +166,8 @@ $(document).ready(function(){initNavTree('remmina__pref_8h_source.html','');});
Definition: remmina_pref.h:78
Definition: remmina_pref.h:96
const gchar * screenshot_path
Definition: remmina_pref.h:137
-
gint remmina_pref_get_scale_quality(void)
-
gchar ** remmina_pref_keymap_groups(void)
+
gint remmina_pref_get_scale_quality(void)
+
gchar ** remmina_pref_keymap_groups(void)
gint unlock_timeout
Definition: remmina_pref.h:192
Definition: remmina_pref.h:86
gboolean confirm_close
Definition: remmina_pref.h:147
@@ -185,7 +185,7 @@ $(document).ready(function(){initNavTree('remmina__pref_8h_source.html','');});
Definition: remmina_pref.h:80
gint ssh_tcp_usrtimeout
Definition: remmina_pref.h:172
gchar * color13
Definition: remmina_pref.h:128
-
gboolean remmina_pref_save(void)
Definition: remmina_pref.c:777
+
gboolean remmina_pref_save(void)
Definition: remmina_pref.c:778
gboolean small_toolbutton
Definition: remmina_pref.h:212
guint shortcutkey_grab
Definition: remmina_pref.h:182
gboolean always_show_tab
Definition: remmina_pref.h:152
@@ -195,14 +195,14 @@ $(document).ready(function(){initNavTree('remmina__pref_8h_source.html','');});
gboolean main_maximize
Definition: remmina_pref.h:219
Definition: remmina_pref.h:101
const gchar * unlock_repassword
Definition: remmina_pref.h:191
-
gint remmina_pref_get_ssh_tcp_keepintvl(void)
+
gint remmina_pref_get_ssh_tcp_keepintvl(void)
Definition: remmina_pref.h:68
gboolean fullscreen
Definition: remmina.c:89
gchar * color9
Definition: remmina_pref.h:124
gchar * color5
Definition: remmina_pref.h:120
gint view_file_mode
Definition: remmina_pref.h:213
gchar * color7
Definition: remmina_pref.h:122
-
gboolean remmina_pref_get_ssh_parseconfig(void)
+
gboolean remmina_pref_get_ssh_parseconfig(void)
guint shortcutkey_nexttab
Definition: remmina_pref.h:178
gboolean applet_hide_count
Definition: remmina_pref.h:163
gboolean list_refresh_workaround
Definition: remmina_pref.h:150
@@ -211,7 +211,7 @@ $(document).ready(function(){initNavTree('remmina__pref_8h_source.html','');});
gint tab_mode
Definition: remmina_pref.h:157
gboolean hide_toolbar
Definition: remmina_pref.h:211
gchar * color6
Definition: remmina_pref.h:121
-
gint remmina_pref_get_sshtunnel_port(void)
+
gint remmina_pref_get_sshtunnel_port(void)
gboolean trust_all
Definition: remmina_pref.h:198
gint enc_mode
Definition: remmina_pref.h:196
gboolean applet_enable_avahi
Definition: remmina_pref.h:215
@@ -220,8 +220,8 @@ $(document).ready(function(){initNavTree('remmina__pref_8h_source.html','');});
RemminaPref remmina_pref
Definition: rcw.c:79
gchar * color3
Definition: remmina_pref.h:118
guint shortcutkey_toolbar
Definition: remmina_pref.h:187
-
gint remmina_pref_get_ssh_tcp_usrtimeout(void)
-
gint remmina_pref_get_ssh_tcp_keepidle(void)
+
gint remmina_pref_get_ssh_tcp_usrtimeout(void)
+
gint remmina_pref_get_ssh_tcp_keepidle(void)
Definition: remmina_pref.h:55
gchar * color8
Definition: remmina_pref.h:123
gchar * remmina_colors_file
@@ -234,16 +234,16 @@ $(document).ready(function(){initNavTree('remmina__pref_8h_source.html','');});
gint sshtunnel_port
Definition: remmina_pref.h:168
const gchar * datadir_path
Definition: remmina_pref.h:135
gboolean disabletoolbar
Definition: remmina.c:88
-
gchar * remmina_pref_get_recent(const gchar *protocol)
Definition: remmina_pref.c:966
+
gchar * remmina_pref_get_recent(const gchar *protocol)
Definition: remmina_pref.c:967
gchar * color15
Definition: remmina_pref.h:130
gchar * cursor_foreground
Definition: remmina_pref.h:110
gchar * color11
Definition: remmina_pref.h:126
-
guint * remmina_pref_keymap_get_table(const gchar *keymap)
+
guint * remmina_pref_keymap_get_table(const gchar *keymap)
Definition: remmina_pref.h:103
Definition: remmina_pref.h:79
gboolean always_show_notes
Definition: remmina_pref.h:153
Definition: remmina_pref.h:102
-
void remmina_pref_add_recent(const gchar *protocol, const gchar *server)
Definition: remmina_pref.c:928
+
void remmina_pref_add_recent(const gchar *protocol, const gchar *server)
Definition: remmina_pref.c:929
RemminaColorPref color_pref
Definition: remmina_pref.h:235
gint main_height
Definition: remmina_pref.h:218
guint shortcutkey_viewonly
Definition: remmina_pref.h:183
@@ -256,7 +256,7 @@ $(document).ready(function(){initNavTree('remmina__pref_8h_source.html','');});
gchar * color1
Definition: remmina_pref.h:116
Definition: remmina_pref.h:87
gint fullscreen_toolbar_visibility
Definition: remmina_pref.h:158
-
gint remmina_pref_get_ssh_loglevel(void)
+
gint remmina_pref_get_ssh_loglevel(void)
gboolean grab_color_switch
Definition: remmina_pref.h:160
gchar * highlight
Definition: remmina_pref.h:111
diff --git a/public/remmina__pref__dialog_8c_source.html b/public/remmina__pref__dialog_8c_source.html index 48ba80806..bb5d2ee53 100644 --- a/public/remmina__pref__dialog_8c_source.html +++ b/public/remmina__pref__dialog_8c_source.html @@ -165,7 +165,7 @@ $(document).ready(function(){initNavTree('remmina__pref__dialog_8c_source.html',
GtkColorButton * colorbutton_color15
gint scale_quality
Definition: remmina_pref.h:142
gboolean remmina_passwd(GtkWindow *parent, gchar **unlock_password)
-
void remmina_pref_set_value(const gchar *key, const gchar *value)
+
void remmina_pref_set_value(const gchar *key, const gchar *value)
gboolean deny_screenshot_clipboard
Definition: remmina_pref.h:138
gchar * resolutions
Definition: remmina_pref.h:145
guint vte_shortcutkey_select_all
Definition: remmina_pref.h:206
@@ -185,7 +185,7 @@ $(document).ready(function(){initNavTree('remmina__pref__dialog_8c_source.html',
gboolean vte_allow_bold_text
Definition: remmina_pref.h:201
GtkFileChooser * filechooserbutton_options_screenshots_path
GtkEntry * entry_options_ssh_tcp_keepidle
-
gchar * remmina_pref_get_value(const gchar *key)
+
gchar * remmina_pref_get_value(const gchar *key)
gboolean disable_tray_icon
Definition: remmina_pref.h:164
GtkEntry * entry_scrollback_lines
GtkColorButton * colorbutton_color4
@@ -253,7 +253,7 @@ $(document).ready(function(){initNavTree('remmina__pref__dialog_8c_source.html',
GtkButton * button_keyboard_host_key
void remmina_string_list_set_text(const gchar *text, const gboolean clear_data)
GtkColorButton * colorbutton_highlight
-
void remmina_pref_clear_recent(void)
Definition: remmina_pref.c:985
+
void remmina_pref_clear_recent(void)
Definition: remmina_pref.c:986
GtkComboBox * comboboxtext_appearance_tab_interface
guint shortcutkey_nexttab
Definition: remmina_pref.h:178
void remmina_prefdiag_on_grab_color_activated(GtkSwitch *widget, gpointer user_data)
@@ -290,7 +290,7 @@ $(document).ready(function(){initNavTree('remmina__pref__dialog_8c_source.html',
GtkComboBox * comboboxtext_options_double_click
void remmina_pref_on_button_keystrokes_clicked(GtkWidget *widget, gpointer user_data)
-
gboolean remmina_pref_save(void)
Definition: remmina_pref.c:777
+
gboolean remmina_pref_save(void)
Definition: remmina_pref.c:778
gint ssh_tcp_keepcnt
Definition: remmina_pref.h:171
gboolean applet_new_ontop
Definition: remmina_pref.h:162
const gchar * screenshot_name
Definition: remmina_pref.h:139
diff --git a/public/remmina__protocol__widget_8c_source.html b/public/remmina__protocol__widget_8c_source.html index 9af1a6d2e..ec2ac22e2 100644 --- a/public/remmina__protocol__widget_8c_source.html +++ b/public/remmina__protocol__widget_8c_source.html @@ -150,7 +150,7 @@ $(document).ready(function(){initNavTree('remmina__protocol__widget_8c_source.ht
static gboolean remmina_protocol_widget_on_key_release(GtkWidget *widget, GdkEventKey *event, RemminaProtocolWidget *gp)
static void shutdown_loop(MpRunInfo *mpri)
gpointer destroy_func_callback_data
Definition: remmina_ssh.h:181
-
RemminaFile * remmina_file_dup_temp_protocol(RemminaFile *remminafile, const gchar *new_protocol)
Definition: remmina_file.c:897
+
RemminaFile * remmina_file_dup_temp_protocol(RemminaFile *remminafile, const gchar *new_protocol)
Definition: remmina_file.c:899
GtkWidget * rcw_open_from_file_full(RemminaFile *remminafile, GCallback disconnect_cb, gpointer data, guint *handler)
Definition: rcw.c:4499
void remmina_message_panel_setup_auth_x509(RemminaMessagePanel *mp, RemminaMessagePanelCallback response_callback, gpointer response_callback_data)
gint id
Definition: types.h:74
@@ -282,7 +282,7 @@ $(document).ready(function(){initNavTree('remmina__protocol__widget_8c_source.ht
gint remmina_protocol_widget_panel_new_certificate(RemminaProtocolWidget *gp, const gchar *subject, const gchar *issuer, const gchar *fingerprint)
void remmina_protocol_widget_close_connection(RemminaProtocolWidget *gp)
gboolean remmina_protocol_widget_plugin_screenshot(RemminaProtocolWidget *gp, RemminaPluginScreenshotData *rpsd)
-
gboolean remmina_pref_get_boolean(const gchar *key)
+
gboolean remmina_pref_get_boolean(const gchar *key)
void remmina_ssh_tunnel_cancel_accept(RemminaSSHTunnel *tunnel)
void remmina_protocol_widget_grab_focus(RemminaProtocolWidget *gp)
RemminaMessagePanel * connect_message_panel
@@ -359,7 +359,7 @@ $(document).ready(function(){initNavTree('remmina__protocol__widget_8c_source.ht
gboolean remmina_message_panel_field_get_switch_state(RemminaMessagePanel *mp, int entryid)
void remmina_file_set_string(RemminaFile *remminafile, const gchar *setting, const gchar *value)
Definition: remmina_file.c:469
gboolean has_error
-
void remmina_file_save(RemminaFile *remminafile)
Definition: remmina_file.c:728
+
void remmina_file_save(RemminaFile *remminafile)
Definition: remmina_file.c:730
static void remmina_protocol_widget_class_init(RemminaProtocolWidgetClass *klass)
void rco_get_monitor_geometry(RemminaConnectionObject *cnnobj, GdkRectangle *sz)
Definition: rcw.c:1009
gchar * clientkey
diff --git a/public/remmina__sftp__plugin_8c_source.html b/public/remmina__sftp__plugin_8c_source.html index dbe0a3db8..a3cd250e0 100644 --- a/public/remmina__sftp__plugin_8c_source.html +++ b/public/remmina__sftp__plugin_8c_source.html @@ -99,7 +99,7 @@ $(document).ready(function(){initNavTree('remmina__sftp__plugin_8c_source.html',
gchar * error
Definition: remmina_ssh.h:80
Definition: types.h:105
typedefG_BEGIN_DECLS struct _RemminaFile RemminaFile
Definition: types.h:44
-
RemminaFile * remmina_file_dup_temp_protocol(RemminaFile *remminafile, const gchar *new_protocol)
Definition: remmina_file.c:897
+
RemminaFile * remmina_file_dup_temp_protocol(RemminaFile *remminafile, const gchar *new_protocol)
Definition: remmina_file.c:899
Definition: remmina_ssh.h:220
void(* protocol_plugin_set_width)(RemminaProtocolWidget *gp, gint width)
Definition: plugin.h:169
diff --git a/public/remmina__ssh__plugin_8c_source.html b/public/remmina__ssh__plugin_8c_source.html index e2aae555e..6324cde04 100644 --- a/public/remmina__ssh__plugin_8c_source.html +++ b/public/remmina__ssh__plugin_8c_source.html @@ -114,7 +114,7 @@ $(document).ready(function(){initNavTree('remmina__ssh__plugin_8c_source.html','
void remmina_plugin_ssh_vte_decrease_font(GtkMenuItem *menuitem, gpointer vte)
Definition: remmina_pref.h:106
gchar * color0
Definition: remmina_pref.h:115
-
RemminaFile * remmina_file_dup_temp_protocol(RemminaFile *remminafile, const gchar *new_protocol)
Definition: remmina_file.c:897
+
RemminaFile * remmina_file_dup_temp_protocol(RemminaFile *remminafile, const gchar *new_protocol)
Definition: remmina_file.c:899
void(* protocol_plugin_set_width)(RemminaProtocolWidget *gp, gint width)
Definition: plugin.h:169
GtkWidget * search_prev_button
gchar * color14
Definition: remmina_pref.h:129
diff --git a/public/remmina__stats_8c_source.html b/public/remmina__stats_8c_source.html index 4aea1824e..8dad577aa 100644 --- a/public/remmina__stats_8c_source.html +++ b/public/remmina__stats_8c_source.html @@ -119,7 +119,7 @@ $(document).ready(function(){initNavTree('remmina__stats_8c_source.html','');});
gchar * remmina_utils_get_lsb_description()
Print the Distribution description as specified by the lsb_release command.
gchar * remmina_sysinfo_get_gnome_shell_version()
Query DBUS to get GNOME Shell version.
JsonNode * remmina_stats_get_gtk_backend()
-
gboolean remmina_pref_get_boolean(const gchar *key)
+
gboolean remmina_pref_get_boolean(const gchar *key)
JsonNode * remmina_stats_get_profiles()
Add a JSON member profile_count with a child for each protocol used by the user.
static void remmina_profiles_get_data(RemminaFile *remminafile, gpointer user_data)
Given a remmina file, fills a structure containing profiles keys/value tuples.
@@ -135,7 +135,7 @@ $(document).ready(function(){initNavTree('remmina__stats_8c_source.html','');});
const gchar * remmina_utils_get_kernel_arch()
Return the machine hardware name as in "uname -m".
JsonNode * remmina_stats_get_kiosk_mode()
Add a json member KIOSK which shows the status of the kiosk.
GHashTable * proto_date
-
gint remmina_file_manager_iterate(GFunc func, gpointer user_data)
+
gint remmina_file_manager_iterate(GFunc func, gpointer user_data)
JsonNode * remmina_stats_get_version()
diff --git a/public/remmina__unlock_8c_source.html b/public/remmina__unlock_8c_source.html index 98ef40eeb..1fe15018c 100644 --- a/public/remmina__unlock_8c_source.html +++ b/public/remmina__unlock_8c_source.html @@ -92,8 +92,8 @@ $(document).ready(function(){initNavTree('remmina__unlock_8c_source.html','');})
static void remmina_unlock_cancel_clicked(GtkButton *btn, gpointer user_data)
GtkButton * button_unlock
gboolean remmina_passwd(GtkWindow *parent, gchar **unlock_password)
-
void remmina_pref_set_value(const gchar *key, const gchar *value)
-
gchar * remmina_pref_get_value(const gchar *key)
+
void remmina_pref_set_value(const gchar *key, const gchar *value)
+
gchar * remmina_pref_get_value(const gchar *key)
gint remmina_sodium_pwhash_str_verify(const char *key, const char *pass)
GTimer * timer
-- cgit v1.2.3