Remmina - The GTK+ Remote Desktop Client  v1.4.33
Remmina is a remote desktop client written in GTK+, aiming to be useful for system administrators and travellers, who need to work with lots of remote computers in front of either large monitors or tiny netbooks. Remmina supports multiple network protocols in an integrated and consistent user interface. Currently RDP, VNC, NX, XDMCP and SSH are supported.
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, *remmina_pref_path, *user_config_path;
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);
242  remmina_pref_path = g_build_path("/", remmina_dir, filename, NULL);
243  user_config_path = g_build_path("/", g_get_user_config_dir(),
244  "remmina", filename, NULL);
245  remmina_pref_file_do_copy(remmina_pref_path, user_config_path);
246  g_dir_close(dir);
247  g_free(remmina_pref_path);
248  g_free(user_config_path);
249  }
250 
251  /* /usr/local/etc/remmina */
252  const gchar *const *dirs = g_get_system_config_dirs();
253 
254  g_free(remmina_dir), remmina_dir = NULL;
255  for (i = 0; dirs[i] != NULL; ++i) {
256  remmina_dir = g_build_path("/", dirs[i], "remmina", NULL);
257  if (g_file_test(remmina_dir, G_FILE_TEST_IS_DIR)) {
258  dir = g_dir_open(remmina_dir, 0, NULL);
259  while ((filename = g_dir_read_name(dir)) != NULL) {
260  remmina_pref_path = g_build_path("/", remmina_dir, filename, NULL);
261  user_config_path = g_build_path("/", g_get_user_config_dir(),
262  "remmina", filename, NULL);
263  remmina_pref_file_do_copy(remmina_pref_path, user_config_path);
264  g_free(remmina_pref_path);
265  g_free(user_config_path);
266  }
267  g_free(remmina_dir), remmina_dir = NULL;
268  g_dir_close(dir);
269  }
270  }
271 
272  /* The last case we use the home ~/.config/remmina */
273  if (remmina_dir != NULL)
274  g_free(remmina_dir), remmina_dir = NULL;
275  remmina_dir = g_build_path("/", g_get_user_config_dir(),
276  "remmina", NULL);
277 
278  remmina_pref_file = g_strdup_printf("%s/remmina.pref", remmina_dir);
279  /* remmina.colors */
280  remmina_colors_file = g_strdup_printf("%s/%s", remmina_dir, colors_filename);
281 
282  remmina_keymap_file = g_strdup_printf("%s/remmina.keymap", remmina_dir);
283 
284  g_free(remmina_dir);
285 
286  gkeyfile = g_key_file_new();
287 
288  g_key_file_load_from_file(gkeyfile, remmina_pref_file, G_KEY_FILE_NONE, NULL);
289 
290  if (g_key_file_has_key(gkeyfile, "remmina_pref", "save_view_mode", NULL))
291  remmina_pref.save_view_mode = g_key_file_get_boolean(gkeyfile, "remmina_pref", "save_view_mode", NULL);
292  else
294 
295  if (g_key_file_has_key(gkeyfile, "remmina_pref", "confirm_close", NULL))
296  remmina_pref.confirm_close = g_key_file_get_boolean(gkeyfile, "remmina_pref", "confirm_close", NULL);
297  else
299 
300  if (extrahardening)
301  remmina_pref.confirm_close = FALSE;
302 
303  if (g_key_file_has_key(gkeyfile, "remmina_pref", "use_master_password", NULL)) {
304  remmina_pref.use_primary_password = g_key_file_get_boolean(gkeyfile, "remmina_pref", "use_master_password", NULL);
305  } else if (g_key_file_has_key(gkeyfile, "remmina_pref", "use_primary_password", NULL))
306  remmina_pref.use_primary_password = g_key_file_get_boolean(gkeyfile, "remmina_pref", "use_primary_password", NULL);
307  else
309 
310  if (g_key_file_has_key(gkeyfile, "remmina_pref", "unlock_timeout", NULL))
311  remmina_pref.unlock_timeout = g_key_file_get_integer(gkeyfile, "remmina_pref", "unlock_timeout", NULL);
312  else
314 
315  if (g_key_file_has_key(gkeyfile, "remmina_pref", "unlock_password", NULL))
316  remmina_pref.unlock_password = g_key_file_get_string(gkeyfile, "remmina_pref", "unlock_password", NULL);
317  else
318  remmina_pref.unlock_password = g_strdup("");
319 
320  if (g_key_file_has_key(gkeyfile, "remmina_pref", "lock_connect", NULL))
321  remmina_pref.lock_connect = g_key_file_get_boolean(gkeyfile, "remmina_pref", "lock_connect", NULL);
322  else
323  remmina_pref.lock_connect = FALSE;
324 
325  if (g_key_file_has_key(gkeyfile, "remmina_pref", "lock_edit", NULL))
326  remmina_pref.lock_edit = g_key_file_get_boolean(gkeyfile, "remmina_pref", "lock_edit", NULL);
327  else
328  remmina_pref.lock_edit = FALSE;
329 
330 
331  if (g_key_file_has_key(gkeyfile, "remmina_pref", "lock_view_passwords", NULL))
332  remmina_pref.lock_view_passwords = g_key_file_get_boolean(gkeyfile, "remmina_pref", "lock_view_passwords", NULL);
333  else
335 
336  if (g_key_file_has_key(gkeyfile, "remmina_pref", "enc_mode", NULL))
337  remmina_pref.enc_mode = g_key_file_get_integer(gkeyfile, "remmina_pref", "enc_mode", NULL);
338  else
340 
341  if (g_key_file_has_key(gkeyfile, "remmina_pref", "audit", NULL))
342  remmina_pref.audit = g_key_file_get_boolean(gkeyfile, "remmina_pref", "audit", NULL);
343  else
344  remmina_pref.audit = FALSE;
345 
346  if (g_key_file_has_key(gkeyfile, "remmina_pref", "trust_all", NULL))
347  remmina_pref.trust_all = g_key_file_get_boolean(gkeyfile, "remmina_pref", "trust_all", NULL);
348  else
349  remmina_pref.trust_all = FALSE;
350 
351  if (g_key_file_has_key(gkeyfile, "remmina_pref", "fullscreen_on_auto", NULL))
352  remmina_pref.fullscreen_on_auto = g_key_file_get_boolean(gkeyfile, "remmina_pref", "fullscreen_on_auto", NULL);
353  else
355 
356  if (g_key_file_has_key(gkeyfile, "remmina_pref", "floating_toolbar_placement", NULL))
357  remmina_pref.floating_toolbar_placement = g_key_file_get_integer(gkeyfile, "remmina_pref", "floating_toolbar_placement", NULL);
358  else
360 
361  if (g_key_file_has_key(gkeyfile, "remmina_pref", "prevent_snap_welcome_message", NULL))
362  remmina_pref.prevent_snap_welcome_message = g_key_file_get_boolean(gkeyfile, "remmina_pref", "prevent_snap_welcome_message", NULL);
363  else
365 
366  if (g_key_file_has_key(gkeyfile, "remmina_pref", "last_quickconnect_protocol", NULL))
367  remmina_pref.last_quickconnect_protocol = g_key_file_get_string(gkeyfile, "remmina_pref", "last_quickconnect_protocol", NULL);
368  else
370 
371  if (g_key_file_has_key(gkeyfile, "remmina_pref", "toolbar_placement", NULL))
372  remmina_pref.toolbar_placement = g_key_file_get_integer(gkeyfile, "remmina_pref", "toolbar_placement", NULL);
373  else
375 
376  if (g_key_file_has_key(gkeyfile, "remmina_pref", "always_show_tab", NULL))
377  remmina_pref.always_show_tab = g_key_file_get_boolean(gkeyfile, "remmina_pref", "always_show_tab", NULL);
378  else
380 
381  if (extrahardening)
383 
384  if (g_key_file_has_key(gkeyfile, "remmina_pref", "always_show_notes", NULL))
385  remmina_pref.always_show_notes = g_key_file_get_boolean(gkeyfile, "remmina_pref", "always_show_notes", NULL);
386  else
388 
389  if (g_key_file_has_key(gkeyfile, "remmina_pref", "hide_connection_toolbar", NULL))
390  remmina_pref.hide_connection_toolbar = g_key_file_get_boolean(gkeyfile, "remmina_pref",
391  "hide_connection_toolbar", NULL);
392  else
394 
395  if (disabletoolbar)
397 
398  if (g_key_file_has_key(gkeyfile, "remmina_pref", "hide_searchbar", NULL))
399  remmina_pref.hide_searchbar = g_key_file_get_boolean(gkeyfile, "remmina_pref",
400  "hide_searchbar", NULL);
401  else
403 
404  if (extrahardening)
406 
407  if (g_key_file_has_key(gkeyfile, "remmina_pref", "default_action", NULL))
408  remmina_pref.default_action = g_key_file_get_integer(gkeyfile, "remmina_pref", "default_action", NULL);
409  else
411 
412  if (g_key_file_has_key(gkeyfile, "remmina_pref", "scale_quality", NULL))
413  remmina_pref.scale_quality = g_key_file_get_integer(gkeyfile, "remmina_pref", "scale_quality", NULL);
414  else
415  remmina_pref.scale_quality = GDK_INTERP_HYPER;
416 
417  if (g_key_file_has_key(gkeyfile, "remmina_pref", "hide_toolbar", NULL))
418  remmina_pref.hide_toolbar = g_key_file_get_boolean(gkeyfile, "remmina_pref", "hide_toolbar", NULL);
419  else
420  remmina_pref.hide_toolbar = FALSE;
421 
422  if (g_key_file_has_key(gkeyfile, "remmina_pref", "small_toolbutton", NULL))
423  remmina_pref.small_toolbutton = g_key_file_get_boolean(gkeyfile, "remmina_pref", "small_toolbutton", NULL);
424  else
426 
427  if (g_key_file_has_key(gkeyfile, "remmina_pref", "view_file_mode", NULL))
428  remmina_pref.view_file_mode = g_key_file_get_integer(gkeyfile, "remmina_pref", "view_file_mode", NULL);
429  else
431 
432  if (g_key_file_has_key(gkeyfile, "remmina_pref", "resolutions", NULL))
433  remmina_pref.resolutions = g_key_file_get_string(gkeyfile, "remmina_pref", "resolutions", NULL);
434  else
436 
437  if (g_key_file_has_key(gkeyfile, "remmina_pref", "keystrokes", NULL))
438  remmina_pref.keystrokes = g_key_file_get_string(gkeyfile, "remmina_pref", "keystrokes", NULL);
439  else
441 
442  if (g_key_file_has_key(gkeyfile, "remmina_pref", "main_width", NULL))
443  remmina_pref.main_width = MAX(600, g_key_file_get_integer(gkeyfile, "remmina_pref", "main_width", NULL));
444  else
445  remmina_pref.main_width = 600;
446 
447  if (g_key_file_has_key(gkeyfile, "remmina_pref", "main_height", NULL))
448  remmina_pref.main_height = MAX(400, g_key_file_get_integer(gkeyfile, "remmina_pref", "main_height", NULL));
449  else
451 
452  if (g_key_file_has_key(gkeyfile, "remmina_pref", "main_maximize", NULL))
453  remmina_pref.main_maximize = g_key_file_get_boolean(gkeyfile, "remmina_pref", "main_maximize", NULL);
454  else
455  remmina_pref.main_maximize = FALSE;
456 
457  if (g_key_file_has_key(gkeyfile, "remmina_pref", "main_sort_column_id", NULL))
458  remmina_pref.main_sort_column_id = g_key_file_get_integer(gkeyfile, "remmina_pref", "main_sort_column_id",
459  NULL);
460  else
462 
463  if (g_key_file_has_key(gkeyfile, "remmina_pref", "main_sort_order", NULL))
464  remmina_pref.main_sort_order = g_key_file_get_integer(gkeyfile, "remmina_pref", "main_sort_order", NULL);
465  else
467 
468  if (g_key_file_has_key(gkeyfile, "remmina_pref", "expanded_group", NULL))
469  remmina_pref.expanded_group = g_key_file_get_string(gkeyfile, "remmina_pref", "expanded_group", NULL);
470  else
471  remmina_pref.expanded_group = g_strdup("");
472 
473  if (g_key_file_has_key(gkeyfile, "remmina_pref", "toolbar_pin_down", NULL))
474  remmina_pref.toolbar_pin_down = g_key_file_get_boolean(gkeyfile, "remmina_pref", "toolbar_pin_down", NULL);
475  else
477 
478  if (g_key_file_has_key(gkeyfile, "remmina_pref", "ssh_loglevel", NULL))
479  remmina_pref.ssh_loglevel = g_key_file_get_integer(gkeyfile, "remmina_pref", "ssh_loglevel", NULL);
480  else
481  remmina_pref.ssh_loglevel = DEFAULT_SSH_LOGLEVEL;
482 
483  if (g_key_file_has_key(gkeyfile, "remmina_pref", "deny_screenshot_clipboard", NULL))
484  remmina_pref.deny_screenshot_clipboard = g_key_file_get_boolean(gkeyfile, "remmina_pref", "deny_screenshot_clipboard", NULL);
485  else
487 
488  if (g_key_file_has_key(gkeyfile, "remmina_pref", "datadir_path", NULL))
489  remmina_pref.datadir_path = g_key_file_get_string(gkeyfile, "remmina_pref", "datadir_path", NULL);
490  else
491  remmina_pref.datadir_path = g_strdup("");
492 
493  if (g_key_file_has_key(gkeyfile, "remmina_pref", "remmina_file_name", NULL))
494  remmina_pref.remmina_file_name = g_key_file_get_string(gkeyfile, "remmina_pref", "remmina_file_name", NULL);
495  else
496  remmina_pref.remmina_file_name = g_strdup("%G_%P_%N_%h");
497 
498  if (g_key_file_has_key(gkeyfile, "remmina_pref", "screenshot_path", NULL)) {
499  remmina_pref.screenshot_path = g_key_file_get_string(gkeyfile, "remmina_pref", "screenshot_path", NULL);
500  } else {
501  remmina_pref.screenshot_path = g_get_user_special_dir(G_USER_DIRECTORY_PICTURES);
502  if (remmina_pref.screenshot_path == NULL)
503  remmina_pref.screenshot_path = g_get_home_dir();
504  }
505 
506  if (g_key_file_has_key(gkeyfile, "remmina_pref", "screenshot_name", NULL))
507  remmina_pref.screenshot_name = g_key_file_get_string(gkeyfile, "remmina_pref", "screenshot_name", NULL);
508  else
509  remmina_pref.screenshot_name = g_strdup("remmina_%p_%h_%Y%m%d-%H%M%S");
510 
511  if (g_key_file_has_key(gkeyfile, "remmina_pref", "ssh_parseconfig", NULL))
512  remmina_pref.ssh_parseconfig = g_key_file_get_boolean(gkeyfile, "remmina_pref", "ssh_parseconfig", NULL);
513  else
514  remmina_pref.ssh_parseconfig = DEFAULT_SSH_PARSECONFIG;
515 
516  if (g_key_file_has_key(gkeyfile, "remmina_pref", "sshtunnel_port", NULL))
517  remmina_pref.sshtunnel_port = g_key_file_get_integer(gkeyfile, "remmina_pref", "sshtunnel_port", NULL);
518  else
519  remmina_pref.sshtunnel_port = DEFAULT_SSHTUNNEL_PORT;
520 
521  if (g_key_file_has_key(gkeyfile, "remmina_pref", "ssh_tcp_keepidle", NULL))
522  remmina_pref.ssh_tcp_keepidle = g_key_file_get_integer(gkeyfile, "remmina_pref", "ssh_tcp_keepidle", NULL);
523  else
524  remmina_pref.ssh_tcp_keepidle = SSH_SOCKET_TCP_KEEPIDLE;
525 
526  if (g_key_file_has_key(gkeyfile, "remmina_pref", "ssh_tcp_keepintvl", NULL))
527  remmina_pref.ssh_tcp_keepintvl = g_key_file_get_integer(gkeyfile, "remmina_pref", "ssh_tcp_keepintvl", NULL);
528  else
529  remmina_pref.ssh_tcp_keepintvl = SSH_SOCKET_TCP_KEEPINTVL;
530 
531  if (g_key_file_has_key(gkeyfile, "remmina_pref", "ssh_tcp_keepcnt", NULL))
532  remmina_pref.ssh_tcp_keepcnt = g_key_file_get_integer(gkeyfile, "remmina_pref", "ssh_tcp_keepcnt", NULL);
533  else
534  remmina_pref.ssh_tcp_keepcnt = SSH_SOCKET_TCP_KEEPCNT;
535 
536  if (g_key_file_has_key(gkeyfile, "remmina_pref", "ssh_tcp_usrtimeout", NULL))
537  remmina_pref.ssh_tcp_usrtimeout = g_key_file_get_integer(gkeyfile, "remmina_pref", "ssh_tcp_usrtimeout", NULL);
538  else
539  remmina_pref.ssh_tcp_usrtimeout = SSH_SOCKET_TCP_USER_TIMEOUT;
540 
541  if (g_key_file_has_key(gkeyfile, "remmina_pref", "applet_new_ontop", NULL))
542  remmina_pref.applet_new_ontop = g_key_file_get_boolean(gkeyfile, "remmina_pref", "applet_new_ontop", NULL);
543  else
545 
546  if (g_key_file_has_key(gkeyfile, "remmina_pref", "applet_hide_count", NULL))
547  remmina_pref.applet_hide_count = g_key_file_get_boolean(gkeyfile, "remmina_pref", "applet_hide_count", NULL);
548  else
550 
551  if (g_key_file_has_key(gkeyfile, "remmina_pref", "applet_enable_avahi", NULL))
552  remmina_pref.applet_enable_avahi = g_key_file_get_boolean(gkeyfile, "remmina_pref", "applet_enable_avahi",
553  NULL);
554  else
556 
557  if (g_key_file_has_key(gkeyfile, "remmina_pref", "disable_tray_icon", NULL))
558  remmina_pref.disable_tray_icon = g_key_file_get_boolean(gkeyfile, "remmina_pref", "disable_tray_icon", NULL);
559  else
561 
562  if (disabletrayicon)
564 
565  if (g_key_file_has_key(gkeyfile, "remmina_pref", "dark_theme", NULL))
566  remmina_pref.dark_theme = g_key_file_get_boolean(gkeyfile, "remmina_pref", "dark_theme", NULL);
567  else
568  remmina_pref.dark_theme = FALSE;
569 
570  if (g_key_file_has_key(gkeyfile, "remmina_pref", "list_refresh_workaround", NULL))
571  remmina_pref.list_refresh_workaround = g_key_file_get_boolean(gkeyfile, "remmina_pref", "list_refresh_workaround", NULL);
572  else
574 
575  if (g_key_file_has_key(gkeyfile, "remmina_pref", "grab_color_switch", NULL))
576  remmina_pref.grab_color_switch = g_key_file_get_boolean(gkeyfile, "remmina_pref", "grab_color_switch", NULL);
577  else
579 
580  if (g_key_file_has_key(gkeyfile, "remmina_pref", "grab_color", NULL))
581  remmina_pref.grab_color = g_key_file_get_string(gkeyfile, "remmina_pref", "grab_color", NULL);
582  else
583  remmina_pref.grab_color = "#00ff00";
584 
585  if (g_key_file_has_key(gkeyfile, "remmina_pref", "recent_maximum", NULL))
586  remmina_pref.recent_maximum = g_key_file_get_integer(gkeyfile, "remmina_pref", "recent_maximum", NULL);
587  else
589 
590  if (g_key_file_has_key(gkeyfile, "remmina_pref", "default_mode", NULL))
591  remmina_pref.default_mode = g_key_file_get_integer(gkeyfile, "remmina_pref", "default_mode", NULL);
592  else
594 
595  if (fullscreen)
597 
598  if (g_key_file_has_key(gkeyfile, "remmina_pref", "tab_mode", NULL))
599  remmina_pref.tab_mode = g_key_file_get_integer(gkeyfile, "remmina_pref", "tab_mode", NULL);
600  else
602 
603  if (g_key_file_has_key(gkeyfile, "remmina_pref", "fullscreen_toolbar_visibility", NULL))
604  remmina_pref.fullscreen_toolbar_visibility = g_key_file_get_integer(gkeyfile, "remmina_pref", "fullscreen_toolbar_visibility", NULL);
605  else
607 
608  if (disabletoolbar)
610 
611  if (g_key_file_has_key(gkeyfile, "remmina_pref", "auto_scroll_step", NULL))
612  remmina_pref.auto_scroll_step = g_key_file_get_integer(gkeyfile, "remmina_pref", "auto_scroll_step", NULL);
613  else
615 
616  if (g_key_file_has_key(gkeyfile, "remmina_pref", "hostkey", NULL))
617  remmina_pref.hostkey = g_key_file_get_integer(gkeyfile, "remmina_pref", "hostkey", NULL);
618  else
619  remmina_pref.hostkey = GDK_KEY_Control_R;
620 
621  if (g_key_file_has_key(gkeyfile, "remmina_pref", "shortcutkey_fullscreen", NULL))
622  remmina_pref.shortcutkey_fullscreen = g_key_file_get_integer(gkeyfile, "remmina_pref", "shortcutkey_fullscreen",
623  NULL);
624  else
626 
627  if (g_key_file_has_key(gkeyfile, "remmina_pref", "shortcutkey_autofit", NULL))
628  remmina_pref.shortcutkey_autofit = g_key_file_get_integer(gkeyfile, "remmina_pref", "shortcutkey_autofit",
629  NULL);
630  else
631  remmina_pref.shortcutkey_autofit = GDK_KEY_1;
632 
633  if (g_key_file_has_key(gkeyfile, "remmina_pref", "shortcutkey_nexttab", NULL))
634  remmina_pref.shortcutkey_nexttab = g_key_file_get_integer(gkeyfile, "remmina_pref", "shortcutkey_nexttab",
635  NULL);
636  else
637  remmina_pref.shortcutkey_nexttab = GDK_KEY_Right;
638 
639  if (g_key_file_has_key(gkeyfile, "remmina_pref", "shortcutkey_prevtab", NULL))
640  remmina_pref.shortcutkey_prevtab = g_key_file_get_integer(gkeyfile, "remmina_pref", "shortcutkey_prevtab",
641  NULL);
642  else
643  remmina_pref.shortcutkey_prevtab = GDK_KEY_Left;
644 
645  if (g_key_file_has_key(gkeyfile, "remmina_pref", "shortcutkey_scale", NULL))
646  remmina_pref.shortcutkey_scale = g_key_file_get_integer(gkeyfile, "remmina_pref", "shortcutkey_scale", NULL);
647  else
648  remmina_pref.shortcutkey_scale = GDK_KEY_s;
649 
650  if (g_key_file_has_key(gkeyfile, "remmina_pref", "shortcutkey_clipboard", NULL))
651  remmina_pref.shortcutkey_clipboard = g_key_file_get_integer(gkeyfile, "remmina_pref", "shortcutkey_clipboard", NULL);
652  else
654 
655  if (g_key_file_has_key(gkeyfile, "remmina_pref", "shortcutkey_viewonly", NULL))
656  remmina_pref.shortcutkey_viewonly = g_key_file_get_integer(gkeyfile, "remmina_pref", "shortcutkey_viewonly", NULL);
657  else
659 
660  if (g_key_file_has_key(gkeyfile, "remmina_pref", "shortcutkey_multimon", NULL))
661  remmina_pref.shortcutkey_multimon = g_key_file_get_integer(gkeyfile, "remmina_pref", "shortcutkey_multimon", NULL);
662  else
663  remmina_pref.shortcutkey_multimon = GDK_KEY_Page_Up;
664 
665  if (g_key_file_has_key(gkeyfile, "remmina_pref", "shortcutkey_grab", NULL))
666  remmina_pref.shortcutkey_grab = g_key_file_get_integer(gkeyfile, "remmina_pref", "shortcutkey_grab", NULL);
667  else
668  remmina_pref.shortcutkey_grab = GDK_KEY_Control_R;
669 
670  if (g_key_file_has_key(gkeyfile, "remmina_pref", "shortcutkey_minimize", NULL))
671  remmina_pref.shortcutkey_minimize = g_key_file_get_integer(gkeyfile, "remmina_pref", "shortcutkey_minimize", NULL);
672  else
673  remmina_pref.shortcutkey_minimize = GDK_KEY_F9;
674 
675  if (g_key_file_has_key(gkeyfile, "remmina_pref", "shortcutkey_screenshot", NULL))
676  remmina_pref.shortcutkey_screenshot = g_key_file_get_integer(gkeyfile, "remmina_pref", "shortcutkey_screenshot", NULL);
677  else
678  remmina_pref.shortcutkey_screenshot = GDK_KEY_F12;
679 
680  if (g_key_file_has_key(gkeyfile, "remmina_pref", "shortcutkey_disconnect", NULL))
681  remmina_pref.shortcutkey_disconnect = g_key_file_get_integer(gkeyfile, "remmina_pref", "shortcutkey_disconnect",
682  NULL);
683  else
685 
686  if (g_key_file_has_key(gkeyfile, "remmina_pref", "shortcutkey_toolbar", NULL))
687  remmina_pref.shortcutkey_toolbar = g_key_file_get_integer(gkeyfile, "remmina_pref", "shortcutkey_toolbar",
688  NULL);
689  else
690  remmina_pref.shortcutkey_toolbar = GDK_KEY_t;
691 
692  if (g_key_file_has_key(gkeyfile, "remmina_pref", "secret", NULL))
693  remmina_pref.secret = g_key_file_get_string(gkeyfile, "remmina_pref", "secret", NULL);
694  else
695  remmina_pref.secret = NULL;
696 
697  if (g_key_file_has_key(gkeyfile, "remmina_pref", "uid", NULL))
698  remmina_pref.uid = g_key_file_get_string(gkeyfile, "remmina_pref", "uid", NULL);
699  else
700  remmina_pref.uid = NULL;
701 
702  if (g_key_file_has_key(gkeyfile, "remmina_pref", "vte_font", NULL))
703  remmina_pref.vte_font = g_key_file_get_string(gkeyfile, "remmina_pref", "vte_font", NULL);
704  else
706 
707  if (g_key_file_has_key(gkeyfile, "remmina_pref", "vte_allow_bold_text", NULL))
708  remmina_pref.vte_allow_bold_text = g_key_file_get_boolean(gkeyfile, "remmina_pref", "vte_allow_bold_text",
709  NULL);
710  else
712 
713  if (g_key_file_has_key(gkeyfile, "remmina_pref", "vte_lines", NULL))
714  remmina_pref.vte_lines = g_key_file_get_integer(gkeyfile, "remmina_pref", "vte_lines", NULL);
715  else
716  remmina_pref.vte_lines = 512;
717 
718  if (g_key_file_has_key(gkeyfile, "remmina_pref", "vte_shortcutkey_copy", NULL))
719  remmina_pref.vte_shortcutkey_copy = g_key_file_get_integer(gkeyfile, "remmina_pref", "vte_shortcutkey_copy",
720  NULL);
721  else
723 
724  if (g_key_file_has_key(gkeyfile, "remmina_pref", "vte_shortcutkey_paste", NULL))
725  remmina_pref.vte_shortcutkey_paste = g_key_file_get_integer(gkeyfile, "remmina_pref", "vte_shortcutkey_paste",
726  NULL);
727  else
729 
730  if (g_key_file_has_key(gkeyfile, "remmina_pref", "vte_shortcutkey_select_all", NULL))
731  remmina_pref.vte_shortcutkey_select_all = g_key_file_get_integer(gkeyfile, "remmina_pref", "vte_shortcutkey_select_all",
732  NULL);
733  else
735 
736  if (g_key_file_has_key(gkeyfile, "remmina_pref", "vte_shortcutkey_increase_font", NULL))
737  remmina_pref.vte_shortcutkey_increase_font = g_key_file_get_integer(gkeyfile, "remmina_pref", "vte_shortcutkey_increase_font",
738  NULL);
739  else
741 
742  if (g_key_file_has_key(gkeyfile, "remmina_pref", "vte_shortcutkey_decrease_font", NULL))
743  remmina_pref.vte_shortcutkey_decrease_font = g_key_file_get_integer(gkeyfile, "remmina_pref", "vte_shortcutkey_decrease_font",
744  NULL);
745  else
746  remmina_pref.vte_shortcutkey_decrease_font = GDK_KEY_Page_Down;
747 
748  if (g_key_file_has_key(gkeyfile, "remmina_pref", "vte_shortcutkey_search_text", NULL))
749  remmina_pref.vte_shortcutkey_search_text = g_key_file_get_integer(gkeyfile, "remmina_pref", "vte_shortcutkey_search_text",
750  NULL);
751  else
753 
754 
756 
757  /* If we have a color scheme file, we switch to it, GIO will merge it in the
758  * remmina.pref file */
759  if (g_file_test(remmina_colors_file, G_FILE_TEST_IS_REGULAR)) {
760  g_key_file_load_from_file(gkeyfile, remmina_colors_file, G_KEY_FILE_NONE, NULL);
761  g_remove(remmina_colors_file);
762  }
763 
764  /* Default settings */
765  if (!g_key_file_has_key(gkeyfile, "remmina", "name", NULL)) {
766  g_key_file_set_string(gkeyfile, "remmina", "name", "");
767  g_key_file_set_integer(gkeyfile, "remmina", "ignore-tls-errors", 1);
768  g_key_file_set_integer(gkeyfile, "remmina", "enable-plugins", 1);
770  }
771 
772  g_key_file_free(gkeyfile);
773 
774  if (remmina_pref.secret == NULL)
776 
778 }
779 
780 gboolean remmina_pref_is_rw(void)
781 {
782  TRACE_CALL(__func__);
783  if (access(remmina_pref_file, W_OK) == 0)
784  return TRUE;
785  else
786  return FALSE;
787  return FALSE;
788 }
789 
790 gboolean remmina_pref_save(void)
791 {
792  TRACE_CALL(__func__);
793 
794  if (remmina_pref_is_rw() == FALSE) {
795  g_debug("remmina.pref is not writable, returning");
796  return FALSE;
797  }
798  GKeyFile *gkeyfile;
799  GError *error = NULL;
800  g_autofree gchar *content = NULL;
801  gsize length;
802 
803  gkeyfile = g_key_file_new();
804 
805  g_key_file_load_from_file(gkeyfile, remmina_pref_file, G_KEY_FILE_NONE, NULL);
806 
807  g_key_file_set_string(gkeyfile, "remmina_pref", "datadir_path", remmina_pref.datadir_path);
808  g_key_file_set_string(gkeyfile, "remmina_pref", "remmina_file_name", remmina_pref.remmina_file_name);
809  g_key_file_set_string(gkeyfile, "remmina_pref", "screenshot_path", remmina_pref.screenshot_path);
810  g_key_file_set_string(gkeyfile, "remmina_pref", "screenshot_name", remmina_pref.screenshot_name);
811  g_key_file_set_boolean(gkeyfile, "remmina_pref", "deny_screenshot_clipboard", remmina_pref.deny_screenshot_clipboard);
812  g_key_file_set_boolean(gkeyfile, "remmina_pref", "save_view_mode", remmina_pref.save_view_mode);
813  g_key_file_set_boolean(gkeyfile, "remmina_pref", "confirm_close", remmina_pref.confirm_close);
814  if (g_key_file_remove_key(gkeyfile, "remmina_pref", "use_master_password", NULL))
815  REMMINA_DEBUG("use_master_password removed…");
816  else
817  REMMINA_INFO("use_master_password already migrated");
818 #if SODIUM_VERSION_INT >= 90200
819  g_key_file_set_boolean(gkeyfile, "remmina_pref", "use_primary_password", remmina_pref.use_primary_password);
820  g_key_file_set_integer(gkeyfile, "remmina_pref", "unlock_timeout", remmina_pref.unlock_timeout);
821  g_key_file_set_string(gkeyfile, "remmina_pref", "unlock_password", remmina_pref.unlock_password);
822  g_key_file_set_boolean(gkeyfile, "remmina_pref", "lock_connect", remmina_pref.lock_connect);
823  g_key_file_set_boolean(gkeyfile, "remmina_pref", "lock_edit", remmina_pref.lock_edit);
824  g_key_file_set_boolean(gkeyfile, "remmina_pref", "lock_view_passwords", remmina_pref.lock_view_passwords);
825 #else
826  g_key_file_set_boolean(gkeyfile, "remmina_pref", "use_primary_password", FALSE);
827  g_key_file_set_integer(gkeyfile, "remmina_pref", "unlock_timeout", 0);
828  g_key_file_set_string(gkeyfile, "remmina_pref", "unlock_password", g_strdup(""));
829  g_key_file_set_boolean(gkeyfile, "remmina_pref", "lock_connect", FALSE);
830  g_key_file_set_boolean(gkeyfile, "remmina_pref", "lock_edit", FALSE);
831  g_key_file_set_boolean(gkeyfile, "remmina_pref", "lock_view_passwords", FALSE);
832 #endif
833  g_key_file_set_integer(gkeyfile, "remmina_pref", "enc_mode", remmina_pref.enc_mode);
834  g_key_file_set_boolean(gkeyfile, "remmina_pref", "audit", remmina_pref.audit);
835  g_key_file_set_boolean(gkeyfile, "remmina_pref", "trust_all", remmina_pref.trust_all);
836  g_key_file_set_integer(gkeyfile, "remmina_pref", "floating_toolbar_placement", remmina_pref.floating_toolbar_placement);
837  g_key_file_set_integer(gkeyfile, "remmina_pref", "toolbar_placement", remmina_pref.toolbar_placement);
838  g_key_file_set_boolean(gkeyfile, "remmina_pref", "prevent_snap_welcome_message", remmina_pref.prevent_snap_welcome_message);
839  g_key_file_set_string(gkeyfile, "remmina_pref", "last_quickconnect_protocol", remmina_pref.last_quickconnect_protocol);
840  g_key_file_set_boolean(gkeyfile, "remmina_pref", "fullscreen_on_auto", remmina_pref.fullscreen_on_auto);
841  g_key_file_set_boolean(gkeyfile, "remmina_pref", "always_show_tab", remmina_pref.always_show_tab);
842  g_key_file_set_boolean(gkeyfile, "remmina_pref", "always_show_notes", remmina_pref.always_show_notes);
843  g_key_file_set_boolean(gkeyfile, "remmina_pref", "hide_connection_toolbar", remmina_pref.hide_connection_toolbar);
844  g_key_file_set_boolean(gkeyfile, "remmina_pref", "hide_searchbar", remmina_pref.hide_searchbar);
845  g_key_file_set_integer(gkeyfile, "remmina_pref", "default_action", remmina_pref.default_action);
846  g_key_file_set_integer(gkeyfile, "remmina_pref", "scale_quality", remmina_pref.scale_quality);
847  g_key_file_set_integer(gkeyfile, "remmina_pref", "ssh_loglevel", remmina_pref.ssh_loglevel);
848  g_key_file_set_boolean(gkeyfile, "remmina_pref", "ssh_parseconfig", remmina_pref.ssh_parseconfig);
849  g_key_file_set_boolean(gkeyfile, "remmina_pref", "hide_toolbar", remmina_pref.hide_toolbar);
850  g_key_file_set_boolean(gkeyfile, "remmina_pref", "small_toolbutton", remmina_pref.small_toolbutton);
851  g_key_file_set_integer(gkeyfile, "remmina_pref", "view_file_mode", remmina_pref.view_file_mode);
852  g_key_file_set_string(gkeyfile, "remmina_pref", "resolutions", remmina_pref.resolutions);
853  g_key_file_set_string(gkeyfile, "remmina_pref", "keystrokes", remmina_pref.keystrokes);
854  g_key_file_set_integer(gkeyfile, "remmina_pref", "main_width", remmina_pref.main_width);
855  g_key_file_set_integer(gkeyfile, "remmina_pref", "main_height", remmina_pref.main_height);
856  g_key_file_set_boolean(gkeyfile, "remmina_pref", "main_maximize", remmina_pref.main_maximize);
857  g_key_file_set_integer(gkeyfile, "remmina_pref", "main_sort_column_id", remmina_pref.main_sort_column_id);
858  g_key_file_set_integer(gkeyfile, "remmina_pref", "main_sort_order", remmina_pref.main_sort_order);
859  g_key_file_set_string(gkeyfile, "remmina_pref", "expanded_group", remmina_pref.expanded_group);
860  g_key_file_set_boolean(gkeyfile, "remmina_pref", "toolbar_pin_down", remmina_pref.toolbar_pin_down);
861  g_key_file_set_integer(gkeyfile, "remmina_pref", "sshtunnel_port", remmina_pref.sshtunnel_port);
862  g_key_file_set_integer(gkeyfile, "remmina_pref", "ssh_tcp_keepidle", remmina_pref.ssh_tcp_keepidle);
863  g_key_file_set_integer(gkeyfile, "remmina_pref", "ssh_tcp_keepintvl", remmina_pref.ssh_tcp_keepintvl);
864  g_key_file_set_integer(gkeyfile, "remmina_pref", "ssh_tcp_keepcnt", remmina_pref.ssh_tcp_keepcnt);
865  g_key_file_set_integer(gkeyfile, "remmina_pref", "ssh_tcp_usrtimeout", remmina_pref.ssh_tcp_usrtimeout);
866  g_key_file_set_boolean(gkeyfile, "remmina_pref", "applet_new_ontop", remmina_pref.applet_new_ontop);
867  g_key_file_set_boolean(gkeyfile, "remmina_pref", "applet_hide_count", remmina_pref.applet_hide_count);
868  g_key_file_set_boolean(gkeyfile, "remmina_pref", "applet_enable_avahi", remmina_pref.applet_enable_avahi);
869  g_key_file_set_boolean(gkeyfile, "remmina_pref", "disable_tray_icon", remmina_pref.disable_tray_icon);
870  g_key_file_set_boolean(gkeyfile, "remmina_pref", "dark_theme", remmina_pref.dark_theme);
871  g_key_file_set_integer(gkeyfile, "remmina_pref", "recent_maximum", remmina_pref.recent_maximum);
872  g_key_file_set_integer(gkeyfile, "remmina_pref", "default_mode", remmina_pref.default_mode);
873  g_key_file_set_integer(gkeyfile, "remmina_pref", "tab_mode", remmina_pref.tab_mode);
874  g_key_file_set_integer(gkeyfile, "remmina_pref", "fullscreen_toolbar_visibility", remmina_pref.fullscreen_toolbar_visibility);
875  g_key_file_set_integer(gkeyfile, "remmina_pref", "auto_scroll_step", remmina_pref.auto_scroll_step);
876  g_key_file_set_integer(gkeyfile, "remmina_pref", "hostkey", remmina_pref.hostkey);
877  g_key_file_set_integer(gkeyfile, "remmina_pref", "shortcutkey_fullscreen", remmina_pref.shortcutkey_fullscreen);
878  g_key_file_set_integer(gkeyfile, "remmina_pref", "shortcutkey_autofit", remmina_pref.shortcutkey_autofit);
879  g_key_file_set_integer(gkeyfile, "remmina_pref", "shortcutkey_nexttab", remmina_pref.shortcutkey_nexttab);
880  g_key_file_set_integer(gkeyfile, "remmina_pref", "shortcutkey_prevtab", remmina_pref.shortcutkey_prevtab);
881  g_key_file_set_integer(gkeyfile, "remmina_pref", "shortcutkey_scale", remmina_pref.shortcutkey_scale);
882  g_key_file_set_integer(gkeyfile, "remmina_pref", "shortcutkey_clipboard", remmina_pref.shortcutkey_clipboard);
883  g_key_file_set_integer(gkeyfile, "remmina_pref", "shortcutkey_grab", remmina_pref.shortcutkey_grab);
884  g_key_file_set_integer(gkeyfile, "remmina_pref", "shortcutkey_multimon", remmina_pref.shortcutkey_multimon);
885  g_key_file_set_integer(gkeyfile, "remmina_pref", "shortcutkey_viewonly", remmina_pref.shortcutkey_viewonly);
886  g_key_file_set_integer(gkeyfile, "remmina_pref", "shortcutkey_screenshot", remmina_pref.shortcutkey_screenshot);
887  g_key_file_set_integer(gkeyfile, "remmina_pref", "shortcutkey_minimize", remmina_pref.shortcutkey_minimize);
888  g_key_file_set_integer(gkeyfile, "remmina_pref", "shortcutkey_disconnect", remmina_pref.shortcutkey_disconnect);
889  g_key_file_set_integer(gkeyfile, "remmina_pref", "shortcutkey_toolbar", remmina_pref.shortcutkey_toolbar);
890  g_key_file_set_integer(gkeyfile, "remmina_pref", "vte_shortcutkey_copy", remmina_pref.vte_shortcutkey_copy);
891  g_key_file_set_integer(gkeyfile, "remmina_pref", "vte_shortcutkey_paste", remmina_pref.vte_shortcutkey_paste);
892  g_key_file_set_integer(gkeyfile, "remmina_pref", "vte_shortcutkey_select_all", remmina_pref.vte_shortcutkey_select_all);
893  g_key_file_set_integer(gkeyfile, "remmina_pref", "vte_shortcutkey_increase_font", remmina_pref.vte_shortcutkey_increase_font);
894  g_key_file_set_integer(gkeyfile, "remmina_pref", "vte_shortcutkey_decrease_font", remmina_pref.vte_shortcutkey_decrease_font);
895  g_key_file_set_integer(gkeyfile, "remmina_pref", "vte_shortcutkey_search_text", remmina_pref.vte_shortcutkey_search_text);
896  g_key_file_set_string(gkeyfile, "remmina_pref", "vte_font", remmina_pref.vte_font ? remmina_pref.vte_font : "");
897  g_key_file_set_string(gkeyfile, "remmina_pref", "grab_color", remmina_pref.grab_color ? remmina_pref.grab_color : "");
898  g_key_file_set_boolean(gkeyfile, "remmina_pref", "grab_color_switch", remmina_pref.grab_color_switch);
899  g_key_file_set_boolean(gkeyfile, "remmina_pref", "vte_allow_bold_text", remmina_pref.vte_allow_bold_text);
900  g_key_file_set_integer(gkeyfile, "remmina_pref", "vte_lines", remmina_pref.vte_lines);
901  g_key_file_set_string(gkeyfile, "ssh_colors", "background", remmina_pref.color_pref.background ? remmina_pref.color_pref.background : "");
902  g_key_file_set_string(gkeyfile, "ssh_colors", "cursor", remmina_pref.color_pref.cursor ? remmina_pref.color_pref.cursor : "");
903  g_key_file_set_string(gkeyfile, "ssh_colors", "cursor_foreground", remmina_pref.color_pref.cursor_foreground ? remmina_pref.color_pref.cursor_foreground : "");
904  g_key_file_set_string(gkeyfile, "ssh_colors", "highlight", remmina_pref.color_pref.highlight ? remmina_pref.color_pref.highlight : "");
905  g_key_file_set_string(gkeyfile, "ssh_colors", "highlight_foreground", remmina_pref.color_pref.highlight_foreground ? remmina_pref.color_pref.highlight_foreground : "");
906  g_key_file_set_string(gkeyfile, "ssh_colors", "colorBD", remmina_pref.color_pref.colorBD ? remmina_pref.color_pref.colorBD : "");
907  g_key_file_set_string(gkeyfile, "ssh_colors", "foreground", remmina_pref.color_pref.foreground ? remmina_pref.color_pref.foreground : "");
908  g_key_file_set_string(gkeyfile, "ssh_colors", "color0", remmina_pref.color_pref.color0 ? remmina_pref.color_pref.color0 : "");
909  g_key_file_set_string(gkeyfile, "ssh_colors", "color1", remmina_pref.color_pref.color1 ? remmina_pref.color_pref.color1 : "");
910  g_key_file_set_string(gkeyfile, "ssh_colors", "color2", remmina_pref.color_pref.color2 ? remmina_pref.color_pref.color2 : "");
911  g_key_file_set_string(gkeyfile, "ssh_colors", "color3", remmina_pref.color_pref.color3 ? remmina_pref.color_pref.color3 : "");
912  g_key_file_set_string(gkeyfile, "ssh_colors", "color4", remmina_pref.color_pref.color4 ? remmina_pref.color_pref.color4 : "");
913  g_key_file_set_string(gkeyfile, "ssh_colors", "color5", remmina_pref.color_pref.color5 ? remmina_pref.color_pref.color5 : "");
914  g_key_file_set_string(gkeyfile, "ssh_colors", "color6", remmina_pref.color_pref.color6 ? remmina_pref.color_pref.color6 : "");
915  g_key_file_set_string(gkeyfile, "ssh_colors", "color7", remmina_pref.color_pref.color7 ? remmina_pref.color_pref.color7 : "");
916  g_key_file_set_string(gkeyfile, "ssh_colors", "color8", remmina_pref.color_pref.color8 ? remmina_pref.color_pref.color8 : "");
917  g_key_file_set_string(gkeyfile, "ssh_colors", "color9", remmina_pref.color_pref.color9 ? remmina_pref.color_pref.color9 : "");
918  g_key_file_set_string(gkeyfile, "ssh_colors", "color10", remmina_pref.color_pref.color10 ? remmina_pref.color_pref.color10 : "");
919  g_key_file_set_string(gkeyfile, "ssh_colors", "color11", remmina_pref.color_pref.color11 ? remmina_pref.color_pref.color11 : "");
920  g_key_file_set_string(gkeyfile, "ssh_colors", "color12", remmina_pref.color_pref.color12 ? remmina_pref.color_pref.color12 : "");
921  g_key_file_set_string(gkeyfile, "ssh_colors", "color13", remmina_pref.color_pref.color13 ? remmina_pref.color_pref.color13 : "");
922  g_key_file_set_string(gkeyfile, "ssh_colors", "color14", remmina_pref.color_pref.color14 ? remmina_pref.color_pref.color14 : "");
923  g_key_file_set_string(gkeyfile, "ssh_colors", "color15", remmina_pref.color_pref.color15 ? remmina_pref.color_pref.color15 : "");
924 
925  /* Default settings */
926  g_key_file_set_string(gkeyfile, "remmina", "name", "");
927  g_key_file_set_integer(gkeyfile, "remmina", "ignore-tls-errors", 1);
928 
929  content = g_key_file_to_data(gkeyfile, &length, NULL);
930  g_file_set_contents(remmina_pref_file, content, length, &error);
931 
932  if (error != NULL) {
933  g_warning("remmina_pref_save error: %s", error->message);
934  g_clear_error(&error);
935  g_key_file_free(gkeyfile);
936  return FALSE;
937  }
938  g_key_file_free(gkeyfile);
939  return TRUE;
940 }
941 
942 void remmina_pref_add_recent(const gchar *protocol, const gchar *server)
943 {
944  TRACE_CALL(__func__);
945  RemminaStringArray *array;
946  GKeyFile *gkeyfile;
947  gchar key[20];
948  g_autofree gchar *val = NULL;
949  g_autofree gchar *content = NULL;
950  gsize length;
951 
952  if (remmina_pref.recent_maximum <= 0 || server == NULL || server[0] == 0)
953  return;
954 
955  /* Load original value into memory */
956  gkeyfile = g_key_file_new();
957 
958  g_key_file_load_from_file(gkeyfile, remmina_pref_file, G_KEY_FILE_NONE, NULL);
959 
960  g_snprintf(key, sizeof(key), "recent_%s", protocol);
961  array = remmina_string_array_new_from_allocated_string(g_key_file_get_string(gkeyfile, "remmina_pref", key, NULL));
962 
963  /* Add the new value */
964  remmina_string_array_remove(array, server);
965  while (array->len >= remmina_pref.recent_maximum)
967  remmina_string_array_add(array, server);
968 
969  /* Save */
970  val = remmina_string_array_to_string(array);
971  g_key_file_set_string(gkeyfile, "remmina_pref", key, val);
972 
973  content = g_key_file_to_data(gkeyfile, &length, NULL);
974  g_file_set_contents(remmina_pref_file, content, length, NULL);
975 
976  g_key_file_free(gkeyfile);
977 }
978 
979 gchar *
980 remmina_pref_get_recent(const gchar *protocol)
981 {
982  TRACE_CALL(__func__);
983  GKeyFile *gkeyfile;
984  gchar key[20];
985  gchar *val = NULL;
986 
987  gkeyfile = g_key_file_new();
988 
989  g_key_file_load_from_file(gkeyfile, remmina_pref_file, G_KEY_FILE_NONE, NULL);
990 
991  g_snprintf(key, sizeof(key), "recent_%s", protocol);
992  val = g_key_file_get_string(gkeyfile, "remmina_pref", key, NULL);
993 
994  g_key_file_free(gkeyfile);
995 
996  return val;
997 }
998 
1000 {
1001  TRACE_CALL(__func__);
1002  GKeyFile *gkeyfile;
1003  gchar **keys;
1004  gint i;
1005  g_autofree gchar *content = NULL;
1006  gsize length;
1007 
1008  gkeyfile = g_key_file_new();
1009 
1010  g_key_file_load_from_file(gkeyfile, remmina_pref_file, G_KEY_FILE_NONE, NULL);
1011  keys = g_key_file_get_keys(gkeyfile, "remmina_pref", NULL, NULL);
1012  if (keys) {
1013  for (i = 0; keys[i]; i++)
1014  if (strncmp(keys[i], "recent_", 7) == 0)
1015  g_key_file_set_string(gkeyfile, "remmina_pref", keys[i], "");
1016  g_strfreev(keys);
1017  }
1018 
1019  content = g_key_file_to_data(gkeyfile, &length, NULL);
1020  g_file_set_contents(remmina_pref_file, content, length, NULL);
1021 
1022  g_key_file_free(gkeyfile);
1023 }
1024 
1025 guint *remmina_pref_keymap_get_table(const gchar *keymap)
1026 {
1027  TRACE_CALL(__func__);
1028 
1029  if (!keymap || keymap[0] == '\0')
1030  return NULL;
1031 
1032  return (guint *)g_hash_table_lookup(remmina_keymap_table, keymap);
1033 }
1034 
1035 guint remmina_pref_keymap_get_keyval(const gchar *keymap, guint keyval)
1036 {
1037  TRACE_CALL(__func__);
1038  guint *table;
1039  gint i;
1040 
1041  if (!keymap || keymap[0] == '\0')
1042  return keyval;
1043 
1044  table = (guint *)g_hash_table_lookup(remmina_keymap_table, keymap);
1045  if (!table)
1046  return keyval;
1047  for (i = 0; table[i] > 0; i += 2)
1048  if (table[i] == keyval)
1049  return table[i + 1];
1050  return keyval;
1051 }
1052 
1053 gchar **
1055 {
1056  TRACE_CALL(__func__);
1057  GList *list;
1058  guint len;
1059  gchar **keys;
1060  guint i;
1061 
1062  list = g_hash_table_get_keys(remmina_keymap_table);
1063  len = g_list_length(list);
1064 
1065  keys = g_new0(gchar *, (len + 1) * 2 + 1);
1066  keys[0] = g_strdup("");
1067  keys[1] = g_strdup("");
1068  for (i = 0; i < len; i++) {
1069  keys[(i + 1) * 2] = g_strdup((gchar *)g_list_nth_data(list, i));
1070  keys[(i + 1) * 2 + 1] = g_strdup((gchar *)g_list_nth_data(list, i));
1071  }
1072  g_list_free(list);
1073 
1074  return keys;
1075 }
1076 
1078 {
1079  TRACE_CALL(__func__);
1080  /* Paranoid programming */
1081  if (remmina_pref.scale_quality < 0)
1083  return remmina_pref.scale_quality;
1084 }
1085 
1087 {
1088  TRACE_CALL(__func__);
1089  return remmina_pref.ssh_loglevel;
1090 }
1091 
1093 {
1094  TRACE_CALL(__func__);
1096 }
1097 
1099 {
1100  TRACE_CALL(__func__);
1102 }
1103 
1105 {
1106  TRACE_CALL(__func__);
1108 }
1109 
1111 {
1112  TRACE_CALL(__func__);
1114 }
1115 
1117 {
1118  TRACE_CALL(__func__);
1120 }
1121 
1123 {
1124  TRACE_CALL(__func__);
1126 }
1127 
1128 void remmina_pref_set_value(const gchar *key, const gchar *value)
1129 {
1130  TRACE_CALL(__func__);
1131  GKeyFile *gkeyfile;
1132  gsize length;
1133 
1134  gkeyfile = g_key_file_new();
1135  if (g_key_file_load_from_file(gkeyfile, remmina_pref_file, G_KEY_FILE_NONE, NULL)) {
1136  g_key_file_set_string(gkeyfile, "remmina_pref", key, value);
1137  gchar *content = g_key_file_to_data(gkeyfile, &length, NULL);
1138  if (g_file_set_contents(remmina_pref_file, content, length, NULL)) {
1139  g_free(content);
1140  } else {
1141  REMMINA_WARNING("Cannot save Remmina preferences");
1142  REMMINA_WARNING("Key was \"%s\", and value \"%s\"", key, value);
1143  }
1144  g_key_file_free(gkeyfile);
1145  } else {
1146  REMMINA_WARNING("Cannot load Remmina preferences file");
1147  }
1148 }
1149 
1150 gchar *remmina_pref_get_value(const gchar *key)
1151 {
1152  TRACE_CALL(__func__);
1153  GKeyFile *gkeyfile;
1154  gchar *value = NULL;
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_string(gkeyfile, "remmina_pref", key, NULL);
1159  g_key_file_free(gkeyfile);
1160 
1161  return value;
1162 }
1163 
1164 gboolean remmina_pref_get_boolean(const gchar *key)
1165 {
1166  TRACE_CALL(__func__);
1167  GKeyFile *gkeyfile;
1168  gboolean value;
1169 
1170  gkeyfile = g_key_file_new();
1171  g_key_file_load_from_file(gkeyfile, remmina_pref_file, G_KEY_FILE_NONE, NULL);
1172  value = g_key_file_get_boolean(gkeyfile, "remmina_pref", key, NULL);
1173  g_key_file_free(gkeyfile);
1174 
1175  return value;
1176 }
guint shortcutkey_fullscreen
Definition: remmina_pref.h:175
gint floating_toolbar_placement
Definition: remmina_pref.h:225
gboolean hide_searchbar
Definition: remmina_pref.h:155
guint vte_shortcutkey_search_text
Definition: remmina_pref.h:210
gint remmina_pref_get_scale_quality(void)
guint shortcutkey_minimize
Definition: remmina_pref.h:186
static void remmina_pref_gen_secret(void)
Definition: remmina_pref.c:73
gboolean lock_connect
Definition: remmina_pref.h:194
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:208
static const gchar * default_keymap_data
Definition: remmina_pref.c:65
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)
gchar * keystrokes
Definition: remmina_pref.h:146
static gboolean remmina_pref_file_do_copy(const char *src_path, const char *dst_path)
Definition: remmina_pref.c:165
guint shortcutkey_screenshot
Definition: remmina_pref.h:185
guint shortcutkey_prevtab
Definition: remmina_pref.h:177
gboolean use_primary_password
Definition: remmina_pref.h:190
gboolean ssh_parseconfig
Definition: remmina_pref.h:167
gint ssh_tcp_keepintvl
Definition: remmina_pref.h:170
gchar * last_quickconnect_protocol
Definition: remmina_pref.h:228
gint remmina_pref_get_ssh_loglevel(void)
gint auto_scroll_step
Definition: remmina_pref.h:143
guint vte_shortcutkey_copy
Definition: remmina_pref.h:205
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:980
guint shortcutkey_autofit
Definition: remmina_pref.h:176
gchar * secret
Definition: remmina_pref.h:231
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:942
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:207
gint main_sort_order
Definition: remmina_pref.h:222
gboolean vte_allow_bold_text
Definition: remmina_pref.h:202
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:196
gint recent_maximum
Definition: remmina_pref.h:144
gboolean remmina_pref_get_ssh_parseconfig(void)
static GHashTable * remmina_keymap_table
Definition: remmina_pref.c:62
gchar * vte_font
Definition: remmina_pref.h:201
guint shortcutkey_multimon
Definition: remmina_pref.h:182
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)
gint unlock_timeout
Definition: remmina_pref.h:193
gboolean confirm_close
Definition: remmina_pref.h:147
gint toolbar_placement
Definition: remmina_pref.h:226
gboolean prevent_snap_welcome_message
Definition: remmina_pref.h:227
gboolean disabletoolbar
Definition: remmina.c:88
gchar * expanded_group
Definition: remmina_pref.h:223
guint vte_shortcutkey_decrease_font
Definition: remmina_pref.h:209
const gchar * unlock_password
Definition: remmina_pref.h:191
guint vte_shortcutkey_paste
Definition: remmina_pref.h:206
guint shortcutkey_disconnect
Definition: remmina_pref.h:187
gint ssh_tcp_usrtimeout
Definition: remmina_pref.h:172
gboolean small_toolbutton
Definition: remmina_pref.h:213
guint shortcutkey_grab
Definition: remmina_pref.h:183
gboolean always_show_tab
Definition: remmina_pref.h:152
gboolean toolbar_pin_down
Definition: remmina_pref.h:224
gint main_sort_column_id
Definition: remmina_pref.h:221
guint shortcutkey_scale
Definition: remmina_pref.h:181
gboolean main_maximize
Definition: remmina_pref.h:220
RemminaStringArray * remmina_string_array_new_from_allocated_string(gchar *strs)
gboolean fullscreen
Definition: remmina.c:89
guint shortcutkey_clipboard
Definition: remmina_pref.h:178
gboolean remmina_pref_get_boolean(const gchar *key)
gint view_file_mode
Definition: remmina_pref.h:214
gint remmina_pref_get_ssh_tcp_keepcnt(void)
void remmina_pref_clear_recent(void)
Definition: remmina_pref.c:999
const gchar * default_resolutions
Definition: remmina_pref.c:58
guint shortcutkey_nexttab
Definition: remmina_pref.h:179
gboolean applet_hide_count
Definition: remmina_pref.h:163
gboolean list_refresh_workaround
Definition: remmina_pref.h:150
gint ssh_tcp_keepidle
Definition: remmina_pref.h:169
gboolean lock_edit
Definition: remmina_pref.h:195
guint remmina_pref_keymap_get_keyval(const gchar *keymap, guint keyval)
gboolean hide_toolbar
Definition: remmina_pref.h:212
void remmina_string_array_remove(RemminaStringArray *array, const gchar *str)
RemminaPref remmina_pref
Definition: rcw.c:79
gboolean trust_all
Definition: remmina_pref.h:199
gboolean applet_enable_avahi
Definition: remmina_pref.h:216
const gchar * remmina_file_name
Definition: remmina_pref.h:136
gboolean disabletrayicon
Definition: remmina.c:91
void remmina_pref_init(void)
Definition: remmina_pref.c:220
gchar * remmina_keymap_file
Definition: remmina_pref.c:61
guint shortcutkey_toolbar
Definition: remmina_pref.h:188
gboolean remmina_pref_save(void)
Definition: remmina_pref.c:790
gchar * remmina_colors_file
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
gboolean hide_connection_toolbar
Definition: remmina_pref.h:154
static void remmina_pref_init_keymap(void)
Definition: remmina_pref.c:110
gboolean audit
Definition: remmina_pref.h:198
gint sshtunnel_port
Definition: remmina_pref.h:168
const gchar * datadir_path
Definition: remmina_pref.h:135
gchar * cursor_foreground
Definition: remmina_pref.h:110
gboolean extrahardening
Definition: remmina.c:90
gboolean remmina_pref_is_rw(void)
Definition: remmina_pref.c:780
gboolean always_show_notes
Definition: remmina_pref.h:153
void remmina_string_array_add(RemminaStringArray *array, const gchar *str)
RemminaColorPref color_pref
Definition: remmina_pref.h:236
void remmina_pref_file_load_colors(GKeyFile *gkeyfile, RemminaColorPref *color_pref)
Definition: remmina_pref.c:177
guint shortcutkey_viewonly
Definition: remmina_pref.h:184
gboolean fullscreen_on_auto
Definition: remmina_pref.h:151
gboolean dark_theme
Definition: remmina_pref.h:149
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)
gboolean grab_color_switch
Definition: remmina_pref.h:160
gint remmina_pref_get_ssh_tcp_keepintvl(void)