Remmina - The GTK+ Remote Desktop Client  v1.4.2
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-2020 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 
134 #include "config.h"
135 #include <string.h>
136 #include <sys/utsname.h>
137 #include <unistd.h>
138 #include <glib.h>
139 #include <glib/gi18n.h>
140 #include <glib/gstdio.h>
141 #include <gtk/gtk.h>
142 
143 #include "remmina.h"
144 #include "remmina_file.h"
145 #include "remmina_file_manager.h"
146 #include "remmina_icon.h"
147 #include "remmina_log.h"
148 #include "remmina_pref.h"
149 #include "remmina_sysinfo.h"
150 #include "remmina_utils.h"
152 #include "remmina_plugin_manager.h"
153 
154 #ifdef GDK_WINDOWING_WAYLAND
155  #include <gdk/gdkwayland.h>
156 #endif
157 #ifdef GDK_WINDOWING_X11
158  #include <gdk/gdkx.h>
159 #endif
160 #include "remmina_stats.h"
161 
162 struct ProfilesData {
163  GHashTable *proto_count;
164  GHashTable *proto_date;
165  const gchar *protocol;
166  const gchar *pdatestr;
167  gint pcount;
168  gchar datestr;
169 };
170 
172 {
173  TRACE_CALL(__func__);
174  JsonNode *r;
175  GChecksum *chs;
176  const gchar *uname, *hname;
177  const gchar *uid_suffix;
178  gchar *uid_prefix;
179  gchar *uid;
180 
186  /* Generate a new UUID_PREFIX for this installation */
187  uid_prefix = remmina_gen_random_uuid();
192  }
193 
194  uname = g_get_user_name();
195  hname = g_get_host_name();
196  chs = g_checksum_new(G_CHECKSUM_SHA256);
197  g_checksum_update(chs, (const guchar*)uname, strlen(uname));
198  g_checksum_update(chs, (const guchar*)hname, strlen(hname));
199  uid_suffix = g_checksum_get_string(chs);
200 
201  uid = g_strdup_printf("%s-%.10s", remmina_pref.periodic_usage_stats_uuid_prefix, uid_suffix);
202  g_checksum_free(chs);
203 
204  r = json_node_alloc();
205  json_node_init_string(r, uid);
206 
207  g_free(uid);
208 
209  return r;
210 
211 }
212 
214 {
215  TRACE_CALL(__func__);
216  JsonBuilder *b;
217  JsonNode *r;
218 
219  gchar *kernel_name;
220  gchar *kernel_release;
221  gchar *kernel_arch;
222  gchar *id;
223  gchar *description;
224  GHashTable *etc_release;
225  gchar *release;
226  gchar *codename;
227  GHashTableIter iter;
228  gchar *key, *value;
229 
233  b = json_builder_new();
234  json_builder_begin_object(b);
235 
236  json_builder_set_member_name(b, "kernel_name");
237  kernel_name = g_strdup_printf("%s", remmina_utils_get_kernel_name());
238  if (!kernel_name || kernel_name[0] == '\0') {
239  json_builder_add_null_value(b);
240  }else {
241  json_builder_add_string_value(b, kernel_name);
242  }
243  g_free(kernel_name);
244 
245  json_builder_set_member_name(b, "kernel_release");
246  kernel_release = g_strdup_printf("%s", remmina_utils_get_kernel_release());
247  if (!kernel_release || kernel_release[0] == '\0') {
248  json_builder_add_null_value(b);
249  }else {
250  json_builder_add_string_value(b, kernel_release);
251  }
252  g_free(kernel_release);
253 
254  json_builder_set_member_name(b, "kernel_arch");
255  kernel_arch = g_strdup_printf("%s", remmina_utils_get_kernel_arch());
256  if (!kernel_arch || kernel_arch[0] == '\0') {
257  json_builder_add_null_value(b);
258  }else {
259  json_builder_add_string_value(b, kernel_arch);
260  }
261  g_free(kernel_arch);
262 
263  json_builder_set_member_name(b, "lsb_distributor");
265  if (!id || id[0] == '\0') {
266  json_builder_add_null_value(b);
267  }else {
268  json_builder_add_string_value(b, id);
269  }
270  g_free(id);
271 
272  json_builder_set_member_name(b, "lsb_distro_description");
273  description = remmina_utils_get_lsb_description();
274  if (!description || description[0] == '\0') {
275  json_builder_add_null_value(b);
276  }else {
277  json_builder_add_string_value(b, description);
278  }
279  g_free(description);
280 
281  json_builder_set_member_name(b, "lsb_distro_release");
282  release = remmina_utils_get_lsb_release();
283  if (!release || release[0] == '\0') {
284  json_builder_add_null_value(b);
285  }else {
286  json_builder_add_string_value(b, release);
287  }
288  g_free(release);
289 
290  json_builder_set_member_name(b, "lsb_distro_codename");
291  codename = remmina_utils_get_lsb_codename();
292  if (!codename || codename[0] == '\0') {
293  json_builder_add_null_value(b);
294  }else {
295  json_builder_add_string_value(b, codename);
296  }
297  g_free(codename);
298 
299  etc_release = remmina_utils_get_etc_release();
300  json_builder_set_member_name(b, "etc_release");
301  if (etc_release) {
302  json_builder_begin_object(b);
303  g_hash_table_iter_init (&iter, etc_release);
304  while (g_hash_table_iter_next (&iter, (gpointer)&key, (gpointer)&value)) {
305  json_builder_set_member_name(b, key);
306  json_builder_add_string_value(b, value);
307  }
308  json_builder_end_object(b);
309  g_hash_table_remove_all(etc_release);
310  g_hash_table_unref(etc_release);
311  }else {
312  json_builder_add_null_value(b);
313  }
314 
319  json_builder_end_object(b);
320  r = json_builder_get_root(b);
321  g_object_unref(b);
322  return r;
323 }
324 
332 {
333  TRACE_CALL(__func__);
334  JsonBuilder *b;
335  JsonNode *r;
336 
337  gchar *language;
338 
339  language = remmina_utils_get_lang();
340 
341  b = json_builder_new();
342  json_builder_begin_object(b);
343  json_builder_set_member_name(b, "language");
344 
345  json_builder_add_string_value(b, language);
346 
347  json_builder_end_object(b);
348  r = json_builder_get_root(b);
349  g_object_unref(b);
350  return r;
351 
352 }
353 
355 {
356  TRACE_CALL(__func__);
357  JsonBuilder *b;
358  JsonNode *r;
359  gchar *flatpak_info;
360 
364  b = json_builder_new();
365  json_builder_begin_object(b);
366  json_builder_set_member_name(b, "version");
367  json_builder_add_string_value(b, VERSION);
368  json_builder_set_member_name(b, "git_revision");
369  json_builder_add_string_value(b, REMMINA_GIT_REVISION);
370  json_builder_set_member_name(b, "snap_build");
371 #ifdef SNAP_BUILD
372  json_builder_add_int_value(b, 1);
373 #else
374  json_builder_add_int_value(b, 0);
375 #endif
376 
380  json_builder_set_member_name(b, "flatpak_build");
381  /* Flatpak sandbox should contain the file ${XDG_RUNTIME_DIR}/flatpak-info */
382  flatpak_info = g_build_filename(g_get_user_runtime_dir(), "flatpak-info", NULL);
383  if (g_file_test(flatpak_info, G_FILE_TEST_EXISTS)) {
384  json_builder_add_int_value(b, 1);
385  } else {
386  json_builder_add_int_value(b, 0);
387  }
388  g_free(flatpak_info);
389 
390  json_builder_end_object(b);
391  r = json_builder_get_root(b);
392  g_object_unref(b);
393  return r;
394 }
395 
397 {
398  TRACE_CALL(__func__);
399  JsonBuilder *b;
400  JsonNode *r;
401 
406  b = json_builder_new();
407  json_builder_begin_object(b);
408  json_builder_set_member_name(b, "major");
409  json_builder_add_int_value(b, gtk_get_major_version());
410  json_builder_set_member_name(b, "minor");
411  json_builder_add_int_value(b, gtk_get_minor_version());
412  json_builder_set_member_name(b, "micro");
413  json_builder_add_int_value(b, gtk_get_micro_version());
414  json_builder_end_object(b);
415  r = json_builder_get_root(b);
416  g_object_unref(b);
417  return r;
418 
419 }
420 
422 {
423  TRACE_CALL(__func__);
424  JsonNode *r;
425  GdkDisplay *disp;
426  gchar *bkend;
427 
432  disp = gdk_display_get_default();
433 
434 #ifdef GDK_WINDOWING_WAYLAND
435  if (GDK_IS_WAYLAND_DISPLAY(disp)) {
436  bkend = "Wayland";
437  }else
438 #endif
439 #ifdef GDK_WINDOWING_X11
440  if (GDK_IS_X11_DISPLAY(disp)) {
441  bkend = "X11";
442  } else
443 #endif
444  bkend = "n/a";
445 
446  r = json_node_alloc();
447  json_node_init_string(r, bkend);
448 
449  return r;
450 
451 }
452 
454 {
455  TRACE_CALL(__func__);
456  JsonBuilder *b;
457  JsonNode *r;
458  gchar *wmver;
459  gchar *wmname;
460 
461  b = json_builder_new();
462  json_builder_begin_object(b);
463 
464  json_builder_set_member_name(b, "window_manager");
465 
468  if (!wmver || wmver[0] == '\0') {
469  remmina_debug("Gnome Shell not found");
470  }else {
471  remmina_debug("Gnome Shell version: %s\n", wmver);
472  json_builder_add_string_value(b, "Gnome Shell");
473  json_builder_set_member_name(b, "gnome_shell_ver");
474  json_builder_add_string_value(b, wmver);
475  goto end;
476  }
477  g_free(wmver);
478 
479  wmname = remmina_sysinfo_get_wm_name();
480  if (!wmname || wmname[0] == '\0') {
482  remmina_debug("Cannot determine the Window Manger name");
483  json_builder_add_string_value(b, "n/a");
484  }else {
485  remmina_debug("Window Manger names %s", wmname);
486  json_builder_add_string_value(b, wmname);
487  }
488  g_free(wmname);
489 
490  end:
491  json_builder_end_object(b);
492  r = json_builder_get_root(b);
493  g_object_unref(b);
494  return r;
495 }
496 
498 {
499  TRACE_CALL(__func__);
500  JsonBuilder *b;
501  JsonNode *r;
502  gboolean sni;
504  b = json_builder_new();
505  json_builder_begin_object(b);
506 
507  json_builder_set_member_name(b, "appindicator_supported");
509  if (sni) {
511  json_builder_add_int_value(b, 1);
512  json_builder_set_member_name(b, "appindicator_compiled");
513 #ifdef HAVE_LIBAPPINDICATOR
514 
515  json_builder_add_int_value(b, 1);
516 #else
517 
518  json_builder_add_int_value(b, 0);
519 #endif
520  }
522  json_builder_add_int_value(b, 0);
523  json_builder_set_member_name(b, "icon_is_active");
526  json_builder_add_int_value(b, 1);
527  json_builder_set_member_name(b, "appindicator_type");
528 #ifdef HAVE_LIBAPPINDICATOR
529 
530  json_builder_add_string_value(b, "AppIndicator on GtkStatusIcon/xembed");
531 #else
532 
533  json_builder_add_string_value(b, "Remmina icon on GtkStatusIcon/xembed");
534 #endif
535  }else {
537  json_builder_add_int_value(b, 0);
538  }
539  json_builder_end_object(b);
540  r = json_builder_get_root(b);
541  g_object_unref(b);
542  return r;
543 }
544 
551 static void remmina_profiles_get_data(RemminaFile *remminafile, gpointer user_data)
552 {
553  TRACE_CALL(__func__);
554 
555  gint count = 0;
556  gpointer pcount, kpo;
557  gpointer pdate, kdo;
558  gchar *hday, *hmonth, *hyear;
559  gchar *pday, *pmonth, *pyear;
560 
561  GDateTime *prof_gdate;
562  GDateTime *pdata_gdate;
564  struct ProfilesData* pdata;
565  pdata = (struct ProfilesData*)user_data;
566 
567  pdata->protocol = remmina_file_get_string(remminafile, "protocol");
568  //pdata->pdatestr = remmina_file_get_string(remminafile, "last_success");
569  const gchar *last_success = remmina_file_get_string(remminafile, "last_success");
570  g_debug("%s date %s", pdata->protocol, last_success);
571 
572  prof_gdate = pdata_gdate = NULL;
573  if (last_success && last_success[0] != '\0' && strlen(last_success) >= 6) {
574  pyear = g_strdup_printf("%.4s", last_success);
575  pmonth = g_strdup_printf("%.2s", last_success + 4);
576  pday = g_strdup_printf("%.2s", last_success + 6);
577  prof_gdate = g_date_time_new_local(
578  atoi(pyear),
579  atoi(pmonth),
580  atoi(pday), 0, 0, 0);
581  g_free(pyear);
582  g_free(pmonth);
583  g_free(pday);
584  }
585 
586 
587  if (pdata->protocol && pdata->protocol[0] != '\0') {
588  if (g_hash_table_lookup_extended(pdata->proto_count, pdata->protocol, &kpo, &pcount)) {
589  count = GPOINTER_TO_INT(pcount) + 1;
590  }else {
591  count = 1;
592  g_hash_table_insert(pdata->proto_count, g_strdup(pdata->protocol), GINT_TO_POINTER(count));
593  }
594  g_hash_table_replace(pdata->proto_count, g_strdup(pdata->protocol), GINT_TO_POINTER(count));
595  pdate = NULL;
596  if (g_hash_table_lookup_extended(pdata->proto_date, pdata->protocol, &kdo, &pdate)) {
597 
598  pdata_gdate = NULL;
599  if (pdate && strlen(pdate) >= 6) {
600  pdata->pdatestr = g_strdup(pdate);
601  hyear = g_strdup_printf("%.4s", (char*)pdate);
602  hmonth = g_strdup_printf("%.2s", (char*)pdate + 4);
603  hday = g_strdup_printf("%.2s", (char*)pdate + 6);
604  pdata_gdate = g_date_time_new_local(
605  atoi(hyear),
606  atoi(hmonth),
607  atoi(hday), 0, 0, 0);
608  g_free(hyear);
609  g_free(hmonth);
610  g_free(hday);
611  }
612 
614  if (prof_gdate != NULL && pdata_gdate != NULL ) {
615  g_debug("Comparing dates");
616  gint res = g_date_time_compare( pdata_gdate, prof_gdate );
618  if (res < 0 ) {
619  g_debug("hash date is less than profile date. Replacing date in the hashtable");
620  g_hash_table_replace(pdata->proto_date, g_strdup(pdata->protocol), g_strdup(last_success));
621  } else {
622  g_debug("profile date is less than hash date. Replacing date in the hashtable");
623  g_hash_table_replace(pdata->proto_date, g_strdup(pdata->protocol), g_strdup(pdata->pdatestr));
624  }
625 
626  }
628  if (prof_gdate == NULL && pdata_gdate != NULL) {
629  g_debug("prof_gdate is NULL, replacing date in the hashtable");
630  g_hash_table_replace(pdata->proto_date, g_strdup(pdata->protocol), g_strdup(pdata->pdatestr));
631  }
632 
634  if (prof_gdate != NULL && pdata_gdate == NULL) {
635  g_debug("pdata_gdate is NULL, replacing date in the hashtable");
636  g_hash_table_replace(pdata->proto_date, g_strdup(pdata->protocol), g_strdup(last_success));
637  }
639  if ((prof_gdate == NULL && pdata_gdate == NULL) && pdata->pdatestr) {
640  g_debug("All dates are NULL, replacing date in the hashtable");
641  g_hash_table_replace(pdata->proto_date, g_strdup(pdata->protocol), NULL);
642  }
643  }else {
646  if (pdata->pdatestr) {
647  g_hash_table_replace(pdata->proto_date, g_strdup(pdata->protocol), g_strdup(pdata->pdatestr));
648  }else {
650  g_hash_table_replace(pdata->proto_date, g_strdup(pdata->protocol), NULL);
651  }
652  }
653  }
654  g_debug("pdata set to %s protocol with last_success to %s", pdata->protocol, pdata->pdatestr);
655  if (pdata_gdate)
656  g_date_time_unref(pdata_gdate);
657  if (prof_gdate)
658  g_date_time_unref(prof_gdate);
659 }
660 
685 {
686  TRACE_CALL(__func__);
687 
688  JsonBuilder *b;
689  JsonNode *r;
690  gchar *s;
691 
692  gint profiles_count;
693  GHashTableIter pcountiter, pdateiter;
694  gpointer pcountkey, pcountvalue;
695  gpointer pdatekey, pdatevalue;
696 
697  struct ProfilesData *pdata;
698  pdata = g_malloc0(sizeof(struct ProfilesData));
699 
700  b = json_builder_new();
701  json_builder_begin_object(b);
702 
703  json_builder_set_member_name(b, "profile_count");
704 
708  pdata->proto_date = g_hash_table_new_full(g_str_hash, g_str_equal,
709  (GDestroyNotify)g_free, (GDestroyNotify)g_free);
710  pdata->proto_count = g_hash_table_new_full(g_str_hash, g_str_equal,
711  (GDestroyNotify)g_free, NULL);
712 
713  profiles_count = remmina_file_manager_iterate(
715  (gpointer)pdata);
716  g_debug("Number of profiles: %d", profiles_count);
717 
718  json_builder_add_int_value(b, profiles_count);
719 
720  g_hash_table_iter_init(&pcountiter, pdata->proto_count);
721  while (g_hash_table_iter_next(&pcountiter, &pcountkey, &pcountvalue)) {
722  json_builder_set_member_name(b, (gchar*)pcountkey);
723  json_builder_add_int_value(b, GPOINTER_TO_INT(pcountvalue));
724  }
725 
726  g_hash_table_iter_init(&pdateiter, pdata->proto_date);
727  while (g_hash_table_iter_next(&pdateiter, &pdatekey, &pdatevalue)) {
728  s = g_strdup_printf("DATE_%s", (gchar*)pdatekey);
729  g_debug("Protocol date label: %s", s);
730  json_builder_set_member_name(b, s);
731  g_free(s);
732  json_builder_add_string_value(b, (gchar*)pdatevalue);
733  g_debug("Protocol date: %s", (gchar*)pdatevalue);
734  }
735 
736  json_builder_end_object(b);
737  r = json_builder_get_root(b);
738  g_object_unref(b);
739 
740  g_hash_table_remove_all(pdata->proto_date);
741  g_hash_table_unref(pdata->proto_date);
742  g_hash_table_remove_all(pdata->proto_count);
743  g_hash_table_unref(pdata->proto_count);
744 
745  g_free(pdata);
746 
747  return r;
748 }
749 
757 {
758  TRACE_CALL(__func__);
759 
760  JsonBuilder *b;
761  JsonNode *r;
762  RemminaSecretPlugin *secret_plugin;
764 
765  b = json_builder_new();
766  json_builder_begin_object(b);
767 
768  if (secret_plugin && secret_plugin->is_service_available) {
769  json_builder_set_member_name(b, "plugin_name");
770  json_builder_add_string_value(b, secret_plugin->name);
771  }
772  json_builder_end_object(b);
773  r = json_builder_get_root(b);
774  g_object_unref(b);
775 
776  return r;
777 }
778 
786 {
787  TRACE_CALL(__func__);
788 
789  JsonBuilder *b;
790  JsonNode *r;
791 
792  b = json_builder_new();
793  json_builder_begin_object(b);
794 
795  json_builder_set_member_name(b, "master_password_status");
796  if (remmina_pref_get_boolean("use_master_password")) {
797  json_builder_add_string_value(b, "ON");
798  } else {
799  json_builder_add_string_value(b, "OFF");
800  }
801 
802  json_builder_end_object(b);
803  r = json_builder_get_root(b);
804  g_object_unref(b);
805 
806  return r;
807 }
808 
816 {
817  TRACE_CALL(__func__);
818 
819  JsonBuilder *b;
820  JsonNode *r;
821 
822  b = json_builder_new();
823  json_builder_begin_object(b);
824 
825  json_builder_set_member_name(b, "kiosk_status");
826  if (!kioskmode && kioskmode == FALSE) {
827  json_builder_add_string_value(b, "OFF");
828  }else {
829  json_builder_add_string_value(b, "ON");
830  }
831 
832  json_builder_end_object(b);
833  r = json_builder_get_root(b);
834  g_object_unref(b);
835 
836  return r;
837 }
838 
839 
840 
849 {
850  TRACE_CALL(__func__);
851  JsonBuilder *b;
852  JsonNode *n;
853 
854  b = json_builder_new();
855  json_builder_begin_object(b);
856 
857  n = remmina_stats_get_uid();
858  json_builder_set_member_name(b, "UID");
859  json_builder_add_value(b, n);
860 
862  json_builder_set_member_name(b, "REMMINAVERSION");
863  json_builder_add_value(b, n);
864 
866  json_builder_set_member_name(b, "SYSTEM");
867  json_builder_add_value(b, n);
868 
874  json_builder_set_member_name(b, "ENVIRONMENT");
875  json_builder_add_value(b, n);
876 
878  json_builder_set_member_name(b, "GTKVERSION");
879  json_builder_add_value(b, n);
880 
882  json_builder_set_member_name(b, "GTKBACKEND");
883  json_builder_add_value(b, n);
884 
886  json_builder_set_member_name(b, "WINDOWMANAGER");
887  json_builder_add_value(b, n);
888 
890  json_builder_set_member_name(b, "APPINDICATOR");
891  json_builder_add_value(b, n);
892 
894  json_builder_set_member_name(b, "PROFILES");
895  json_builder_add_value(b, n);
896 
898  json_builder_set_member_name(b, "ACTIVESECRETPLUGIN");
899  json_builder_add_value(b, n);
900 
902  json_builder_set_member_name(b, "HASMASTERPASSWORD");
903  json_builder_add_value(b, n);
904 
906  json_builder_set_member_name(b, "KIOSK");
907  json_builder_add_value(b, n);
908 
909 
910  json_builder_end_object(b);
911  n = json_builder_get_root(b);
912  g_object_unref(b);
913 
914  return n;
915 
916 }
const gchar * remmina_file_get_string(RemminaFile *remminafile, const gchar *setting)
Definition: remmina_file.c:449
JsonNode * remmina_stats_get_uid()
const gchar * protocol
typedefG_BEGIN_DECLS struct _RemminaFile RemminaFile
Definition: types.h:41
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.
GHashTable * proto_count
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:376
gboolean(* is_service_available)(void)
Definition: plugin.h:138
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()
void remmina_debug(const gchar *fmt,...)
Print a string in the Remmina Debug Windows and in the terminal.
Definition: remmina_log.c:194
JsonNode * remmina_stats_get_master_password_status()
Add a json member HASMASTERPASSWORD which shows the status of the master password.
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_gen_random_uuid()
Generate a random sting of chars to be used as part of UID for news or stats.
gchar * periodic_usage_stats_uuid_prefix
Definition: remmina_pref.h:202
gchar * remmina_utils_get_lang()
Return the current language defined in the LC_ALL.
const gchar * name
Definition: plugin.h:131
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)
RemminaPref remmina_pref
Definition: rcw.c:73
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_pref_save(void)
Definition: remmina_pref.c:707
gboolean remmina_sysinfo_is_appindicator_available()
JsonNode * remmina_stats_get_indicator()
JsonNode * remmina_stats_get_wm_name()
gboolean kioskmode
Definition: remmina.c:79
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()