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_stats.c
Go to the documentation of this file.
1 /*
2  * Remmina - The GTK+ Remote Desktop Client
3  * Copyright (C) 2016-2023 Antenore Gatta, Giovanni Panozzo
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  *
20  * In addition, as a special exception, the copyright holders give
21  * permission to link the code of portions of this program with the
22  * OpenSSL library under certain conditions as described in each
23  * individual source file, and distribute linked combinations
24  * including the two.
25  * You must obey the GNU General Public License in all respects
26  * for all of the code used other than OpenSSL. * If you modify
27  * file(s) with this exception, you may extend this exception to your
28  * version of the file(s), but you are not obligated to do so. * If you
29  * do not wish to do so, delete this exception statement from your
30  * version. * If you delete this exception statement from all source
31  * files in the program, then also delete it here.
32  *
33  */
34 
137 #include "config.h"
138 #include <string.h>
139 #include <sys/utsname.h>
140 #include <unistd.h>
141 #include <glib/gi18n.h>
142 #include <glib/gstdio.h>
143 #include <gtk/gtk.h>
144 
145 #include "remmina.h"
146 #include "remmina_file.h"
147 #include "remmina_file_manager.h"
148 #include "remmina_icon.h"
149 #include "remmina_log.h"
150 #include "remmina_pref.h"
151 #include "remmina_sysinfo.h"
152 #include "remmina_utils.h"
154 #include "remmina_plugin_manager.h"
155 
156 #ifdef GDK_WINDOWING_WAYLAND
157  #include <gdk/gdkwayland.h>
158 #endif
159 #ifdef GDK_WINDOWING_X11
160  #include <gdk/gdkx.h>
161 #endif
162 #include "remmina_stats.h"
163 
164 struct ProfilesData {
165  GHashTable *proto_count;
166  GHashTable *proto_date;
167  const gchar *protocol;
168  const gchar *pdatestr;
169  gint pcount;
170  gchar datestr;
171 };
172 
174 {
175  TRACE_CALL(__func__);
176  JsonBuilder *b;
177  JsonNode *r;
178 
179  gchar *kernel_name;
180  gchar *kernel_release;
181  gchar *kernel_arch;
182  gchar *id;
183  gchar *description;
184  GHashTable *etc_release;
185  gchar *release;
186  gchar *codename;
187  GHashTableIter iter;
188  gchar *key, *value;
189 
193  b = json_builder_new();
194  json_builder_begin_object(b);
195 
196  json_builder_set_member_name(b, "kernel_name");
197  kernel_name = g_strdup_printf("%s", remmina_utils_get_kernel_name());
198  if (!kernel_name || kernel_name[0] == '\0') {
199  json_builder_add_null_value(b);
200  }else {
201  json_builder_add_string_value(b, kernel_name);
202  }
203  g_free(kernel_name);
204 
205  json_builder_set_member_name(b, "kernel_release");
206  kernel_release = g_strdup_printf("%s", remmina_utils_get_kernel_release());
207  if (!kernel_release || kernel_release[0] == '\0') {
208  json_builder_add_null_value(b);
209  }else {
210  json_builder_add_string_value(b, kernel_release);
211  }
212  g_free(kernel_release);
213 
214  json_builder_set_member_name(b, "kernel_arch");
215  kernel_arch = g_strdup_printf("%s", remmina_utils_get_kernel_arch());
216  if (!kernel_arch || kernel_arch[0] == '\0') {
217  json_builder_add_null_value(b);
218  }else {
219  json_builder_add_string_value(b, kernel_arch);
220  }
221  g_free(kernel_arch);
222 
223  json_builder_set_member_name(b, "lsb_distributor");
225  if (!id || id[0] == '\0') {
226  json_builder_add_null_value(b);
227  }else {
228  json_builder_add_string_value(b, id);
229  }
230  g_free(id);
231 
232  json_builder_set_member_name(b, "lsb_distro_description");
233  description = remmina_utils_get_lsb_description();
234  if (!description || description[0] == '\0') {
235  json_builder_add_null_value(b);
236  }else {
237  json_builder_add_string_value(b, description);
238  }
239  g_free(description);
240 
241  json_builder_set_member_name(b, "lsb_distro_release");
242  release = remmina_utils_get_lsb_release();
243  if (!release || release[0] == '\0') {
244  json_builder_add_null_value(b);
245  }else {
246  json_builder_add_string_value(b, release);
247  }
248  g_free(release);
249 
250  json_builder_set_member_name(b, "lsb_distro_codename");
251  codename = remmina_utils_get_lsb_codename();
252  if (!codename || codename[0] == '\0') {
253  json_builder_add_null_value(b);
254  }else {
255  json_builder_add_string_value(b, codename);
256  }
257  g_free(codename);
258 
259  etc_release = remmina_utils_get_etc_release();
260  json_builder_set_member_name(b, "etc_release");
261  if (etc_release) {
262  json_builder_begin_object(b);
263  g_hash_table_iter_init (&iter, etc_release);
264  while (g_hash_table_iter_next (&iter, (gpointer)&key, (gpointer)&value)) {
265  json_builder_set_member_name(b, key);
266  json_builder_add_string_value(b, value);
267  }
268  json_builder_end_object(b);
269  g_hash_table_remove_all(etc_release);
270  g_hash_table_unref(etc_release);
271  }else {
272  json_builder_add_null_value(b);
273  }
274 
279  json_builder_end_object(b);
280  r = json_builder_get_root(b);
281  g_object_unref(b);
282  return r;
283 }
284 
292 {
293  TRACE_CALL(__func__);
294  JsonBuilder *b;
295  JsonNode *r;
296 
297  gchar *language;
298 
299  language = remmina_utils_get_lang();
300 
301  b = json_builder_new();
302  json_builder_begin_object(b);
303  json_builder_set_member_name(b, "language");
304 
305  json_builder_add_string_value(b, language);
306 
307  json_builder_end_object(b);
308  r = json_builder_get_root(b);
309  g_object_unref(b);
310  return r;
311 
312 }
313 
315 {
316  TRACE_CALL(__func__);
317  JsonBuilder *b;
318  JsonNode *r;
319  gchar *flatpak_info;
320 
324  b = json_builder_new();
325  json_builder_begin_object(b);
326  json_builder_set_member_name(b, "version");
327  json_builder_add_string_value(b, VERSION);
328  json_builder_set_member_name(b, "git_revision");
329  json_builder_add_string_value(b, REMMINA_GIT_REVISION);
330  json_builder_set_member_name(b, "snap_build");
331 #ifdef SNAP_BUILD
332  json_builder_add_int_value(b, 1);
333 #else
334  json_builder_add_int_value(b, 0);
335 #endif
336 
340  json_builder_set_member_name(b, "flatpak_build");
341  /* Flatpak sandbox should contain the file ${XDG_RUNTIME_DIR}/flatpak-info */
342  flatpak_info = g_build_filename(g_get_user_runtime_dir(), "flatpak-info", NULL);
343  if (g_file_test(flatpak_info, G_FILE_TEST_EXISTS)) {
344  json_builder_add_int_value(b, 1);
345  } else {
346  json_builder_add_int_value(b, 0);
347  }
348  g_free(flatpak_info);
349 
350  json_builder_end_object(b);
351  r = json_builder_get_root(b);
352  g_object_unref(b);
353  return r;
354 }
355 
357 {
358  TRACE_CALL(__func__);
359  JsonBuilder *b;
360  JsonNode *r;
361 
366  b = json_builder_new();
367  json_builder_begin_object(b);
368  json_builder_set_member_name(b, "major");
369  json_builder_add_int_value(b, gtk_get_major_version());
370  json_builder_set_member_name(b, "minor");
371  json_builder_add_int_value(b, gtk_get_minor_version());
372  json_builder_set_member_name(b, "micro");
373  json_builder_add_int_value(b, gtk_get_micro_version());
374  json_builder_end_object(b);
375  r = json_builder_get_root(b);
376  g_object_unref(b);
377  return r;
378 
379 }
380 
382 {
383  TRACE_CALL(__func__);
384  JsonNode *r;
385  GdkDisplay *disp;
386  gchar *bkend;
387 
392  disp = gdk_display_get_default();
393 
394 #ifdef GDK_WINDOWING_WAYLAND
395  if (GDK_IS_WAYLAND_DISPLAY(disp)) {
396  bkend = "Wayland";
397  }else
398 #endif
399 #ifdef GDK_WINDOWING_X11
400  if (GDK_IS_X11_DISPLAY(disp)) {
401  bkend = "X11";
402  } else
403 #endif
404  bkend = "n/a";
405 
406  r = json_node_alloc();
407  json_node_init_string(r, bkend);
408 
409  return r;
410 
411 }
412 
414 {
415  TRACE_CALL(__func__);
416  JsonBuilder *b;
417  JsonNode *r;
418  gchar *wmver;
419  gchar *wmname;
420 
421  b = json_builder_new();
422  json_builder_begin_object(b);
423 
424  json_builder_set_member_name(b, "window_manager");
425 
428  if (!wmver || wmver[0] == '\0') {
429  REMMINA_DEBUG("GNOME Shell not found");
430  }else {
431  REMMINA_DEBUG("GNOME Shell version: %s\n", wmver);
432  json_builder_add_string_value(b, "GNOME Shell");
433  json_builder_set_member_name(b, "gnome_shell_ver");
434  json_builder_add_string_value(b, wmver);
435  goto end;
436  }
437  g_free(wmver);
438 
439  wmname = remmina_sysinfo_get_wm_name();
440  if (!wmname || wmname[0] == '\0') {
442  REMMINA_DEBUG("Cannot determine the window manger name");
443  json_builder_add_string_value(b, "n/a");
444  }else {
445  REMMINA_DEBUG("Window manger names %s", wmname);
446  json_builder_add_string_value(b, wmname);
447  }
448  g_free(wmname);
449 
450  end:
451  json_builder_end_object(b);
452  r = json_builder_get_root(b);
453  g_object_unref(b);
454  return r;
455 }
456 
458 {
459  TRACE_CALL(__func__);
460  JsonBuilder *b;
461  JsonNode *r;
462  gboolean sni;
464  b = json_builder_new();
465  json_builder_begin_object(b);
466 
467  json_builder_set_member_name(b, "appindicator_supported");
469  if (sni) {
471  json_builder_add_int_value(b, 1);
472  json_builder_set_member_name(b, "appindicator_compiled");
473 #ifdef HAVE_LIBAPPINDICATOR
474 
475  json_builder_add_int_value(b, 1);
476 #else
477 
478  json_builder_add_int_value(b, 0);
479 #endif
480  }
482  json_builder_add_int_value(b, 0);
483  json_builder_set_member_name(b, "icon_is_active");
486  json_builder_add_int_value(b, 1);
487  json_builder_set_member_name(b, "appindicator_type");
488 #ifdef HAVE_LIBAPPINDICATOR
489 
490  json_builder_add_string_value(b, "AppIndicator on GtkStatusIcon/xembed");
491 #else
492 
493  json_builder_add_string_value(b, "Remmina icon on GtkStatusIcon/xembed");
494 #endif
495  }else {
497  json_builder_add_int_value(b, 0);
498  }
499  json_builder_end_object(b);
500  r = json_builder_get_root(b);
501  g_object_unref(b);
502  return r;
503 }
504 
511 static void remmina_profiles_get_data(RemminaFile *remminafile, gpointer user_data)
512 {
513  TRACE_CALL(__func__);
514 
515  gint count = 0;
516  gpointer pcount, kpo;
517  gpointer pdate;
518  gchar *hday, *hmonth, *hyear;
519  gchar *pday, *pmonth, *pyear;
520 
521  GDateTime *prof_gdate;
522  GDateTime *pdata_gdate;
524  struct ProfilesData* pdata;
525  pdata = (struct ProfilesData*)user_data;
526 
527  pdata->protocol = remmina_file_get_string(remminafile, "protocol");
528  //pdata->pdatestr = remmina_file_get_string(remminafile, "last_success");
529  const gchar *last_success = remmina_file_get_string(remminafile, "last_success");
530  g_debug("%s date %s", pdata->protocol, last_success);
531 
532  prof_gdate = pdata_gdate = NULL;
533  if (last_success && last_success[0] != '\0' && strlen(last_success) >= 6) {
534  pyear = g_strdup_printf("%.4s", last_success);
535  pmonth = g_strdup_printf("%.2s", last_success + 4);
536  pday = g_strdup_printf("%.2s", last_success + 6);
537  prof_gdate = g_date_time_new_local(
538  atoi(pyear),
539  atoi(pmonth),
540  atoi(pday), 0, 0, 0);
541  g_free(pyear);
542  g_free(pmonth);
543  g_free(pday);
544  }
545 
546 
547  if (pdata->protocol && pdata->protocol[0] != '\0') {
548  if (g_hash_table_lookup_extended(pdata->proto_count, pdata->protocol, &kpo, &pcount)) {
549  count = GPOINTER_TO_INT(pcount) + 1;
550  }else {
551  count = 1;
552  g_hash_table_insert(pdata->proto_count, g_strdup(pdata->protocol), GINT_TO_POINTER(count));
553  }
554  g_hash_table_replace(pdata->proto_count, g_strdup(pdata->protocol), GINT_TO_POINTER(count));
555  pdate = NULL;
556  if (g_hash_table_lookup_extended(pdata->proto_date, pdata->protocol, NULL, &pdate)) {
557 
558  pdata_gdate = NULL;
559  if (pdate && strlen(pdate) >= 6) {
560  pdata->pdatestr = g_strdup(pdate);
561  hyear = g_strdup_printf("%.4s", (char*)pdate);
562  hmonth = g_strdup_printf("%.2s", (char*)pdate + 4);
563  hday = g_strdup_printf("%.2s", (char*)pdate + 6);
564  pdata_gdate = g_date_time_new_local(
565  atoi(hyear),
566  atoi(hmonth),
567  atoi(hday), 0, 0, 0);
568  g_free(hyear);
569  g_free(hmonth);
570  g_free(hday);
571  }
572 
574  if (prof_gdate != NULL && pdata_gdate != NULL ) {
575  g_debug("Comparing dates");
576  gint res = g_date_time_compare( pdata_gdate, prof_gdate );
578  if (res < 0 ) {
579  g_debug("hash date is less than profile date. Replacing date in the hashtable");
580  g_hash_table_replace(pdata->proto_date, g_strdup(pdata->protocol), g_strdup(last_success));
581  } else {
582  g_debug("profile date is less than hash date. Replacing date in the hashtable");
583  g_hash_table_replace(pdata->proto_date, g_strdup(pdata->protocol), g_strdup(pdata->pdatestr));
584  }
585 
586  }
588  if (prof_gdate == NULL && pdata_gdate != NULL) {
589  g_debug("prof_gdate is NULL, replacing date in the hashtable");
590  g_hash_table_replace(pdata->proto_date, g_strdup(pdata->protocol), g_strdup(pdata->pdatestr));
591  }
592 
594  if (prof_gdate != NULL && pdata_gdate == NULL) {
595  g_debug("pdata_gdate is NULL, replacing date in the hashtable");
596  g_hash_table_replace(pdata->proto_date, g_strdup(pdata->protocol), g_strdup(last_success));
597  }
599  if ((prof_gdate == NULL && pdata_gdate == NULL) && pdata->pdatestr) {
600  g_debug("All dates are NULL, replacing date in the hashtable");
601  g_hash_table_replace(pdata->proto_date, g_strdup(pdata->protocol), NULL);
602  }
603  } else {
606  if (pdata->pdatestr) {
607  g_hash_table_replace(pdata->proto_date, g_strdup(pdata->protocol), g_strdup(pdata->pdatestr));
608  }else {
610  g_hash_table_replace(pdata->proto_date, g_strdup(pdata->protocol), NULL);
611  }
612  }
613  }
614  g_debug("pdata set to %s protocol with last_success to %s", pdata->protocol, pdata->pdatestr);
615  if (pdata_gdate)
616  g_date_time_unref(pdata_gdate);
617  if (prof_gdate)
618  g_date_time_unref(prof_gdate);
619 }
620 
645 {
646  TRACE_CALL(__func__);
647 
648  JsonBuilder *b;
649  JsonNode *r;
650  gchar *s;
651 
652  gint profiles_count;
653  GHashTableIter pcountiter, pdateiter;
654  gpointer pcountkey, pcountvalue;
655  gpointer pdatekey, pdatevalue;
656 
657  struct ProfilesData *pdata;
658  pdata = g_malloc0(sizeof(struct ProfilesData));
659 
660  b = json_builder_new();
661  json_builder_begin_object(b);
662 
663  json_builder_set_member_name(b, "profile_count");
664 
668  pdata->proto_date = g_hash_table_new_full(g_str_hash, g_str_equal,
669  (GDestroyNotify)g_free, (GDestroyNotify)g_free);
670  pdata->proto_count = g_hash_table_new_full(g_str_hash, g_str_equal,
671  (GDestroyNotify)g_free, NULL);
672 
673  profiles_count = remmina_file_manager_iterate(
675  (gpointer)pdata);
676  g_debug("Number of profiles: %d", profiles_count);
677 
678  json_builder_add_int_value(b, profiles_count);
679 
680  g_hash_table_iter_init(&pcountiter, pdata->proto_count);
681  while (g_hash_table_iter_next(&pcountiter, &pcountkey, &pcountvalue)) {
682  json_builder_set_member_name(b, (gchar*)pcountkey);
683  json_builder_add_int_value(b, GPOINTER_TO_INT(pcountvalue));
684  }
685 
686  g_hash_table_iter_init(&pdateiter, pdata->proto_date);
687  while (g_hash_table_iter_next(&pdateiter, &pdatekey, &pdatevalue)) {
688  s = g_strdup_printf("DATE_%s", (gchar*)pdatekey);
689  g_debug("Protocol date label: %s", s);
690  json_builder_set_member_name(b, s);
691  g_free(s);
692  json_builder_add_string_value(b, (gchar*)pdatevalue);
693  g_debug("Protocol date: %s", (gchar*)pdatevalue);
694  }
695 
696  json_builder_end_object(b);
697  r = json_builder_get_root(b);
698  g_object_unref(b);
699 
700  g_hash_table_remove_all(pdata->proto_date);
701  g_hash_table_unref(pdata->proto_date);
702  g_hash_table_remove_all(pdata->proto_count);
703  g_hash_table_unref(pdata->proto_count);
704 
705  g_free(pdata);
706 
707  return r;
708 }
709 
717 {
718  TRACE_CALL(__func__);
719 
720  JsonBuilder *b;
721  JsonNode *r;
722  RemminaSecretPlugin *secret_plugin;
724 
725  b = json_builder_new();
726  json_builder_begin_object(b);
727 
728  if (secret_plugin && secret_plugin->is_service_available) {
729  json_builder_set_member_name(b, "plugin_name");
730  json_builder_add_string_value(b, secret_plugin->name);
731  }
732  json_builder_end_object(b);
733  r = json_builder_get_root(b);
734  g_object_unref(b);
735 
736  return r;
737 }
738 
746 {
747  TRACE_CALL(__func__);
748 
749  JsonBuilder *b;
750  JsonNode *r;
751 
752  b = json_builder_new();
753  json_builder_begin_object(b);
754 
755  json_builder_set_member_name(b, "primary_password_status");
756  if (remmina_pref_get_boolean("use_primary_password")) {
757  json_builder_add_string_value(b, "ON");
758  } else {
759  json_builder_add_string_value(b, "OFF");
760  }
761 
762  json_builder_end_object(b);
763  r = json_builder_get_root(b);
764  g_object_unref(b);
765 
766  return r;
767 }
768 
776 {
777  TRACE_CALL(__func__);
778 
779  JsonBuilder *b;
780  JsonNode *r;
781 
782  b = json_builder_new();
783  json_builder_begin_object(b);
784 
785  json_builder_set_member_name(b, "kiosk_status");
786  if (!kioskmode && kioskmode == FALSE) {
787  json_builder_add_string_value(b, "OFF");
788  }else {
789  json_builder_add_string_value(b, "ON");
790  }
791 
792  json_builder_end_object(b);
793  r = json_builder_get_root(b);
794  g_object_unref(b);
795 
796  return r;
797 }
798 
807 {
808  TRACE_CALL(__func__);
809  JsonBuilder *b;
810  JsonNode *n;
811 
812  b = json_builder_new();
813  json_builder_begin_object(b);
814 
816  json_builder_set_member_name(b, "REMMINAVERSION");
817  json_builder_add_value(b, n);
818 
820  json_builder_set_member_name(b, "SYSTEM");
821  json_builder_add_value(b, n);
822 
828  json_builder_set_member_name(b, "ENVIRONMENT");
829  json_builder_add_value(b, n);
830 
832  json_builder_set_member_name(b, "GTKVERSION");
833  json_builder_add_value(b, n);
834 
836  json_builder_set_member_name(b, "GTKBACKEND");
837  json_builder_add_value(b, n);
838 
840  json_builder_set_member_name(b, "WINDOWMANAGER");
841  json_builder_add_value(b, n);
842 
844  json_builder_set_member_name(b, "APPINDICATOR");
845  json_builder_add_value(b, n);
846 
848  json_builder_set_member_name(b, "PROFILES");
849  json_builder_add_value(b, n);
850 
852  json_builder_set_member_name(b, "ACTIVESECRETPLUGIN");
853  json_builder_add_value(b, n);
854 
856  json_builder_set_member_name(b, "HASPRIMARYPASSWORD");
857  json_builder_add_value(b, n);
858 
860  json_builder_set_member_name(b, "KIOSK");
861  json_builder_add_value(b, n);
862 
863 
864  json_builder_end_object(b);
865  n = json_builder_get_root(b);
866  g_object_unref(b);
867 
868  return n;
869 
870 }
const gchar * remmina_file_get_string(RemminaFile *remminafile, const gchar *setting)
Definition: remmina_file.c:516
const gchar * protocol
typedefG_BEGIN_DECLS struct _RemminaFile RemminaFile
Definition: types.h:44
JsonNode * remmina_stats_get_user_env()
Gets the following user environment:
RemminaSecretPlugin * remmina_plugin_manager_get_secret_plugin(void)
gint pcount
Date in string format in the proto_date hash table.
gboolean(* is_service_available)(struct _RemminaSecretPlugin *instance)
Definition: plugin.h:144
GHashTable * proto_count
JsonNode * remmina_stats_get_primary_password_status()
Add a JSON member HASPRIMARYPASSWORD which shows the status of the master password.
gchar * remmina_utils_get_lsb_codename()
Print the Distribution codename as specified by the lsb_release command.
gboolean remmina_icon_is_available(void)
Determine whenever the Remmina icon is available.
Definition: remmina_icon.c:330
gchar * remmina_utils_get_lsb_id()
Print the Distributor as specified by the lsb_release command.
const gchar * remmina_utils_get_kernel_name()
Return the OS name as in "uname -s".
JsonNode * remmina_stats_get_secret_plugin()
Add a JSON member ACTIVESECRETPLUGIN which shows the current secret plugin in use by Remmina...
const gchar * remmina_utils_get_kernel_release()
Return the OS version as in "uname -r".
JsonNode * remmina_stats_get_gtk_version()
JsonNode * remmina_stats_get_os_info()
General utility functions, non-GTK related.
gchar * remmina_utils_get_lsb_release()
Print the Distribution release name as specified by the lsb_release command.
gchar * remmina_utils_get_lang()
Return the current language defined in the LC_ALL.
const gchar * name
Definition: plugin.h:137
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)
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.
JsonNode * remmina_stats_get_all()
Get all statistics in JSON format to send periodically to the PHP server.
gchar * remmina_sysinfo_get_wm_name()
Query environment variables to get the Window manager name.
const gchar * pdatestr
Key in the proto_count hash table.
gboolean remmina_sysinfo_is_appindicator_available()
JsonNode * remmina_stats_get_indicator()
JsonNode * remmina_stats_get_wm_name()
gboolean kioskmode
Definition: remmina.c:87
GHashTable * remmina_utils_get_etc_release()
Print the distribution description if found.
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)
JsonNode * remmina_stats_get_version()