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

gitlab.com/Remmina/Remmina.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmake/FindJSONGLIB.cmake44
-rw-r--r--cmake/FindLIBSOUP24.cmake46
-rw-r--r--remmina/CMakeLists.txt18
-rw-r--r--remmina/src/remmina.c4
-rw-r--r--remmina/src/remmina_main.c46
-rw-r--r--remmina/src/remmina_main.h1
-rw-r--r--remmina/src/remmina_pref.c19
-rw-r--r--remmina/src/remmina_pref.h6
-rw-r--r--remmina/src/remmina_stats.c204
-rw-r--r--remmina/src/remmina_stats.h47
-rw-r--r--remmina/src/remmina_stats_sender.c200
-rw-r--r--remmina/src/remmina_stats_sender.h48
-rw-r--r--remmina/ui/remmina_main.glade70
-rw-r--r--snap/snapcraft.yaml.in2
14 files changed, 751 insertions, 4 deletions
diff --git a/cmake/FindJSONGLIB.cmake b/cmake/FindJSONGLIB.cmake
new file mode 100644
index 000000000..1bcfdcf67
--- /dev/null
+++ b/cmake/FindJSONGLIB.cmake
@@ -0,0 +1,44 @@
+# Remmina - The GTK+ Remote Desktop Client
+#
+# Copyright (C) 2011 Marc-Andre Moreau
+# Copyright (C) 2014-2015 Antenore Gatta, Fabio Castelli, Giovanni Panozzo
+# Copyright (C) 2016-2018 Antenore Gatta, Giovanni Panozzo
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301, USA.
+
+include(FindPackageHandleStandardArgs)
+
+pkg_check_modules(PC_JSONGLIB json-glib-1.0)
+
+find_path(JSONGLIB_INCLUDE_DIR NAMES json-glib/json-glib.h
+ HINTS ${PC_JSONGLIB_INCLUDEDIR} ${PC_JSONGLIB_INCLUDE_DIRS}
+)
+
+find_library(JSONGLIB_LIBRARY NAMES json-glib-1.0
+ HINTS ${PC_JSONGLIB_LIBDIR} ${PC_JSONGLIB_LIBRARY_DIRS}
+)
+
+if (JSONGLIB_INCLUDE_DIR AND JSONGLIB_LIBRARY)
+ find_package_handle_standard_args(JSONGLIB DEFAULT_MSG JSONGLIB_LIBRARY JSONGLIB_INCLUDE_DIR)
+endif()
+
+if (JSONGLIB_FOUND)
+ set(JSONGLIB_LIBRARIES ${JSONGLIB_LIBRARY})
+ set(JSONGLIB_INCLUDE_DIRS ${JSONGLIB_INCLUDE_DIR})
+endif()
+
+mark_as_advanced(JSONGLIB_INCLUDE_DIR JSONGLIB_LIBRARY)
+
diff --git a/cmake/FindLIBSOUP24.cmake b/cmake/FindLIBSOUP24.cmake
new file mode 100644
index 000000000..ab84f6229
--- /dev/null
+++ b/cmake/FindLIBSOUP24.cmake
@@ -0,0 +1,46 @@
+# Remmina - The GTK+ Remote Desktop Client
+#
+# Copyright (C) 2011 Marc-Andre Moreau
+# Copyright (C) 2014-2015 Antenore Gatta, Fabio Castelli, Giovanni Panozzo
+# Copyright (C) 2016-2018 Antenore Gatta, Giovanni Panozzo
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301, USA.
+
+include(FindPackageHandleStandardArgs)
+
+pkg_check_modules(PC_LIBSOUP24 libsoup-2.4)
+
+
+find_path(LIBSOUP24_INCLUDE_DIR NAMES libsoup/soup.h
+ HINTS ${PC_LIBSOUP24_INCLUDEDIR} ${PC_LIBSOUP24_INCLUDE_DIRS}
+)
+
+find_library(LIBSOUP24_LIBRARY
+ NAMES soup-2.4
+ HINTS ${PC_LIBSOUP24_LIBDIR} ${PC_LIBSOUP24_LIBRARY_DIRS}
+ )
+
+if (LIBSOUP24_INCLUDE_DIR AND LIBSOUP24_LIBRARY)
+ find_package_handle_standard_args(LIBSOUP24 DEFAULT_MSG LIBSOUP24_LIBRARY LIBSOUP24_INCLUDE_DIR)
+endif()
+
+if (LIBSOUP24_FOUND)
+ set(LIBSOUP24_LIBRARIES ${LIBSOUP24_LIBRARY})
+ set(LIBSOUP24_INCLUDE_DIRS ${LIBSOUP24_INCLUDE_DIR})
+endif()
+
+mark_as_advanced(LIBSOUP24_INCLUDE_DIR LIBSOUP24_LIBRARY)
+
diff --git a/remmina/CMakeLists.txt b/remmina/CMakeLists.txt
index cc35b7401..bb28730b5 100644
--- a/remmina/CMakeLists.txt
+++ b/remmina/CMakeLists.txt
@@ -112,6 +112,10 @@ list(APPEND REMMINA_SRCS
"src/remmina_connection_window.h"
"src/remmina_mpchange.c"
"src/remmina_mpchange.h"
+ "src/remmina_stats.c"
+ "src/remmina_stats.h"
+ "src/remmina_stats_sender.c"
+ "src/remmina_stats_sender.h"
)
add_executable(remmina ${REMMINA_SRCS})
@@ -174,6 +178,20 @@ if(GTK3_FOUND)
include_directories(${APPINDICATOR_INCLUDE_DIRS})
target_link_libraries(remmina ${APPINDICATOR_LIBRARIES})
endif()
+ find_required_package(JSONGLIB)
+ if (JSONGLIB_FOUND)
+ include_directories(${JSONGLIB_INCLUDE_DIRS})
+ target_link_libraries(remmina ${JSONGLIB_LIBRARIES})
+ else()
+ message(FATAL_ERROR "json-glib library not found")
+ endif()
+ find_required_package(LIBSOUP24)
+ if (LIBSOUP24_FOUND)
+ include_directories(${LIBSOUP24_INCLUDE_DIRS})
+ target_link_libraries(remmina ${LIBSOUP24_LIBRARIES})
+ else()
+ message(FATAL_ERROR "libsoup 2.4 library not found")
+ endif()
endif()
find_package(Intl)
diff --git a/remmina/src/remmina.c b/remmina/src/remmina.c
index 8af86bb53..51ac39cca 100644
--- a/remmina/src/remmina.c
+++ b/remmina/src/remmina.c
@@ -53,6 +53,8 @@
#include "remmina_ssh_plugin.h"
#include "remmina_widget_pool.h"
#include "remmina/remmina_trace_calls.h"
+#include "remmina_stats_sender.h"
+
#ifdef HAVE_ERRNO_H
#include <errno.h>
@@ -201,6 +203,8 @@ static void remmina_on_startup(GApplication *app)
gtk_icon_theme_append_search_path(gtk_icon_theme_get_default(),
REMMINA_RUNTIME_DATADIR G_DIR_SEPARATOR_S "icons");
g_application_hold(app);
+
+ remmina_stats_sender_schedule();
}
static gint remmina_on_local_cmdline(GApplication *app, GVariantDict *options, gpointer user_data)
diff --git a/remmina/src/remmina_main.c b/remmina/src/remmina_main.c
index a1d8d7ef6..41af16a2c 100644
--- a/remmina/src/remmina_main.c
+++ b/remmina/src/remmina_main.c
@@ -2,7 +2,7 @@
* Remmina - The GTK+ Remote Desktop Client
* Copyright (C) 2009-2011 Vic Lee
* Copyright (C) 2014-2015 Antenore Gatta, Fabio Castelli, Giovanni Panozzo
- * Copyright (C) 2016-2017 Antenore Gatta, Giovanni Panozzo
+ * Copyright (C) 2016-2018 Antenore Gatta, Giovanni Panozzo
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -56,6 +56,7 @@
#include "remmina_mpchange.h"
#include "remmina_external_tools.h"
#include "remmina/remmina_trace_calls.h"
+#include "remmina_stats_sender.h"
static RemminaMain *remminamain;
@@ -1094,6 +1095,38 @@ static void remmina_main_init(void)
remmina_widget_pool_register(GTK_WIDGET(remminamain->window));
}
+/* Signal handler for "show" on remminamain->window */
+void remmina_main_on_show(GtkWidget *w, gpointer user_data)
+{
+ TRACE_CALL(__func__);
+ if (!remmina_pref.periodic_usage_stats_permission_asked) {
+ gtk_widget_set_visible(GTK_WIDGET(remminamain->box_ustat), TRUE);
+ }
+}
+
+void remmina_main_on_click_ustat_yes(GtkWidget *w, gpointer user_data)
+{
+ remmina_pref.periodic_usage_stats_permission_asked = TRUE;
+ remmina_pref.periodic_usage_stats_permitted = TRUE;
+ remmina_pref_save();
+ gtk_widget_set_visible(GTK_WIDGET(remminamain->box_ustat), FALSE);
+ remmina_stats_sender_schedule();
+}
+
+void remmina_main_on_click_ustat_no(GtkWidget *w, gpointer user_data)
+{
+ remmina_pref.periodic_usage_stats_permission_asked = TRUE;
+ remmina_pref.periodic_usage_stats_permitted = FALSE;
+ remmina_pref_save();
+ gtk_widget_set_visible(GTK_WIDGET(remminamain->box_ustat), FALSE);
+}
+
+static void remmina_main_on_click_test(GtkWidget *w, gpointer user_data)
+{
+ remmina_stats_sender_send();
+}
+
+
/* RemminaMain instance */
GtkWidget* remmina_main_new(void)
{
@@ -1117,6 +1150,7 @@ GtkWidget* remmina_main_new(void)
remminamain->tree_files_list = GTK_TREE_VIEW(GET_OBJECT("tree_files_list"));
remminamain->column_files_list_group = GTK_TREE_VIEW_COLUMN(GET_OBJECT("column_files_list_group"));
remminamain->statusbar_main = GTK_STATUSBAR(GET_OBJECT("statusbar_main"));
+ remminamain->box_ustat = GTK_BOX(GET_OBJECT("box_ustat"));
/* Non widget objects */
remminamain->accelgroup_shortcuts = GTK_ACCEL_GROUP(GET_OBJECT("accelgroup_shortcuts"));
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
@@ -1146,6 +1180,16 @@ GtkWidget* remmina_main_new(void)
remminamain->action_help_wiki = GTK_ACTION(GET_OBJECT("action_help_wiki"));
remminamain->action_help_debug = GTK_ACTION(GET_OBJECT("action_help_debug"));
G_GNUC_END_IGNORE_DEPRECATIONS
+
+ /* Temporary code to test statistics: add a button */
+ GtkHeaderBar *hb = GTK_HEADER_BAR(GET_OBJECT("main_headerbar"));
+ GtkWidget *statbutton = gtk_button_new_with_label("Send test stats");
+ gtk_header_bar_pack_end(hb, statbutton);
+ gtk_widget_show(statbutton);
+ g_signal_connect(G_OBJECT(statbutton), "clicked",
+ G_CALLBACK(remmina_main_on_click_test), NULL);
+
+
/* Connect signals */
gtk_builder_connect_signals(remminamain->builder, NULL);
/* Initialize the window and load the preferences */
diff --git a/remmina/src/remmina_main.h b/remmina/src/remmina_main.h
index dbabf1e71..a680c1b8f 100644
--- a/remmina/src/remmina_main.h
+++ b/remmina/src/remmina_main.h
@@ -59,6 +59,7 @@ typedef struct _RemminaMain {
GtkTreeView *tree_files_list;
GtkTreeViewColumn *column_files_list_group;
GtkStatusbar *statusbar_main;
+ GtkBox *box_ustat;
/* Non widget objects */
GtkAccelGroup *accelgroup_shortcuts;
GtkActionGroup *actiongroup_connection;
diff --git a/remmina/src/remmina_pref.c b/remmina/src/remmina_pref.c
index 14e32ef5d..ce4b1e8d9 100644
--- a/remmina/src/remmina_pref.c
+++ b/remmina/src/remmina_pref.c
@@ -674,6 +674,21 @@ void remmina_pref_init(void)
else
remmina_pref.color15 = "#d5ccba";
+ if (g_key_file_has_key(gkeyfile, "usage_stats", "periodic_usage_stats_permission_asked", NULL))
+ remmina_pref.periodic_usage_stats_permission_asked = g_key_file_get_boolean(gkeyfile, "usage_stats", "periodic_usage_stats_permission_asked", NULL);
+ else
+ remmina_pref.periodic_usage_stats_permission_asked = FALSE;
+
+ if (g_key_file_has_key(gkeyfile, "usage_stats", "periodic_usage_stats_permitted", NULL))
+ remmina_pref.periodic_usage_stats_permitted = g_key_file_get_boolean(gkeyfile, "usage_stats", "periodic_usage_stats_permitted", NULL);
+ else
+ remmina_pref.periodic_usage_stats_permitted = FALSE;
+
+ if (g_key_file_has_key(gkeyfile, "usage_stats", "periodic_usage_stats_last_sent", NULL))
+ remmina_pref.periodic_usage_stats_last_sent = g_key_file_get_int64(gkeyfile, "usage_stats", "periodic_usage_stats_last_sent", NULL);
+ else
+ remmina_pref.periodic_usage_stats_last_sent = 0;
+
g_key_file_free(gkeyfile);
#if 0
@@ -772,6 +787,10 @@ void remmina_pref_save(void)
g_key_file_set_string(gkeyfile, "ssh_colors", "color14", remmina_pref.color14 ? remmina_pref.color14 : "");
g_key_file_set_string(gkeyfile, "ssh_colors", "color15", remmina_pref.color15 ? remmina_pref.color15 : "");
+ g_key_file_set_boolean(gkeyfile, "usage_stats", "periodic_usage_stats_permission_asked", remmina_pref.periodic_usage_stats_permission_asked);
+ g_key_file_set_boolean(gkeyfile, "usage_stats", "periodic_usage_stats_permitted", remmina_pref.periodic_usage_stats_permitted);
+ g_key_file_set_int64(gkeyfile, "usage_stats", "periodic_usage_stats_last_sent", remmina_pref.periodic_usage_stats_last_sent);
+
content = g_key_file_to_data(gkeyfile, &length, NULL);
g_file_set_contents(remmina_pref_file, content, length, NULL);
diff --git a/remmina/src/remmina_pref.h b/remmina/src/remmina_pref.h
index dc701e271..64164a85b 100644
--- a/remmina/src/remmina_pref.h
+++ b/remmina/src/remmina_pref.h
@@ -183,6 +183,12 @@ typedef struct _RemminaPref {
gchar *color14;
gchar *color15;
+ /* Usage stats */
+ gboolean periodic_usage_stats_permission_asked;
+ gboolean periodic_usage_stats_permitted;
+ glong periodic_usage_stats_last_sent;
+
+
} RemminaPref;
#define DEFAULT_SSH_PARSECONFIG TRUE
diff --git a/remmina/src/remmina_stats.c b/remmina/src/remmina_stats.c
new file mode 100644
index 000000000..deeaf7018
--- /dev/null
+++ b/remmina/src/remmina_stats.c
@@ -0,0 +1,204 @@
+/*
+ * Remmina - The GTK+ Remote Desktop Client
+ * Copyright (C) 2009-2011 Vic Lee
+ * Copyright (C) 2014-2015 Antenore Gatta, Fabio Castelli, Giovanni Panozzo
+ * Copyright (C) 2016-2018 Antenore Gatta, Giovanni Panozzo
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL. * If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so. * If you
+ * do not wish to do so, delete this exception statement from your
+ * version. * If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ *
+ */
+
+#include "config.h"
+#include <gtk/gtk.h>
+#include <string.h>
+#include "remmina/remmina_trace_calls.h"
+
+#ifdef GDK_WINDOWING_WAYLAND
+ #include <gdk/gdkwayland.h>
+#endif
+#ifdef GDK_WINDOWING_X11
+ #include <gdk/gdkx.h>
+#endif
+#include "remmina_stats.h"
+
+JsonNode *remmina_stats_get_gtk_version()
+{
+ TRACE_CALL(__func__);
+ JsonBuilder *b;
+ JsonNode *r;
+
+ /* WARNING: this function is usually executed on a dedicated thread,
+ * not on the main thread */
+
+ b = json_builder_new();
+ json_builder_begin_object(b);
+ json_builder_set_member_name(b, "major");
+ json_builder_add_int_value(b, gtk_get_major_version());
+ json_builder_set_member_name(b, "minor");
+ json_builder_add_int_value(b, gtk_get_minor_version());
+ json_builder_set_member_name(b, "micro");
+ json_builder_add_int_value(b, gtk_get_micro_version());
+ json_builder_end_object (b);
+ r = json_builder_get_root(b);
+ g_object_unref(b);
+ return r;
+
+}
+
+JsonNode *remmina_stats_get_gtk_backend()
+{
+ TRACE_CALL(__func__);
+ JsonNode *r;
+ GdkDisplay *disp;
+ gchar *bkend;
+
+ /* WARNING: this function is usually executed on a dedicated thread,
+ * not on the main thread */
+
+ disp = gdk_display_get_default();
+
+#ifdef GDK_WINDOWING_WAYLAND
+ if (GDK_IS_WAYLAND_DISPLAY(disp))
+ {
+ bkend = "Wayland";
+ }
+ else
+#endif
+#ifdef GDK_WINDOWING_X11
+ if (GDK_IS_X11_DISPLAY (disp))
+ {
+ bkend = "X11";
+ }
+ else
+#endif
+ bkend = "Unknown";
+
+ r = json_node_alloc();
+ json_node_init_string(r, bkend);
+
+ return r;
+
+}
+
+JsonNode *remmina_stats_get_uid()
+{
+ TRACE_CALL(__func__);
+ JsonNode *r;
+
+ /* WARNING: this function is usually executed on a dedicated thread,
+ * not on the main thread */
+
+ /* ToDo: Improve UID */
+ GChecksum *chs;
+ const gchar *uname, *hname;
+ const gchar *chss;
+ uname = g_get_user_name();
+ hname = g_get_host_name();
+ chs = g_checksum_new(G_CHECKSUM_SHA256);
+ g_checksum_update(chs, (const guchar*)uname, strlen(uname));
+ g_checksum_update(chs, (const guchar*)hname, strlen(hname));
+ chss = g_checksum_get_string(chs);
+
+ r = json_node_alloc();
+ json_node_init_string(r, chss);
+ g_checksum_free(chs);
+
+ return r;
+
+}
+
+JsonNode *remmina_stats_get_version()
+{
+ TRACE_CALL(__func__);
+ JsonBuilder *b;
+ JsonNode *r;
+
+ /* WARNING: this function is usually executed on a dedicated thread,
+ * not on the main thread */
+
+ b = json_builder_new();
+ json_builder_begin_object(b);
+ json_builder_set_member_name(b, "version");
+ json_builder_add_string_value(b, VERSION);
+ json_builder_set_member_name(b, "git_revision");
+ json_builder_add_string_value(b, REMMINA_GIT_REVISION);
+ json_builder_set_member_name(b, "snap_build");
+#ifdef SNAP_BUILD
+ json_builder_add_int_value(b, 1);
+#else
+ json_builder_add_int_value(b, 0);
+#endif
+ json_builder_end_object (b);
+ r = json_builder_get_root(b);
+ g_object_unref(b);
+ return r;
+
+}
+
+JsonNode *remmina_stats_get_all()
+{
+ /* Get all statistics in json format to send periodically to the PHP server.
+ * Return a pointer to the JSON string.
+ * The caller should free the returned buffer with g_free() */
+
+ /* WARNING: this function is usually executed on a dedicated thread,
+ * not on the main thread */
+
+
+ TRACE_CALL(__func__);
+
+ JsonBuilder *b;
+ JsonNode *n;
+ b = json_builder_new();
+ json_builder_begin_object(b);
+
+ n = remmina_stats_get_uid();
+ json_builder_set_member_name(b, "UID");
+ json_builder_add_value(b, n);
+
+ n = remmina_stats_get_version();
+ json_builder_set_member_name(b, "REMMINAVERSION");
+ json_builder_add_value(b, n);
+
+
+ n = remmina_stats_get_gtk_version();
+ json_builder_set_member_name(b, "GTKVERSION");
+ json_builder_add_value(b, n);
+
+ n = remmina_stats_get_gtk_backend();
+ json_builder_set_member_name(b, "GTKBACKEND");
+ json_builder_add_value(b, n);
+
+ json_builder_end_object(b);
+ n = json_builder_get_root(b);
+ g_object_unref(b);
+
+ return n;
+
+}
diff --git a/remmina/src/remmina_stats.h b/remmina/src/remmina_stats.h
new file mode 100644
index 000000000..b4617da81
--- /dev/null
+++ b/remmina/src/remmina_stats.h
@@ -0,0 +1,47 @@
+/*
+ * Remmina - The GTK+ Remote Desktop Client
+ * Copyright (C) 2009-2011 Vic Lee
+ * Copyright (C) 2014-2015 Antenore Gatta, Fabio Castelli, Giovanni Panozzo
+ * Copyright (C) 2016-2018 Antenore Gatta, Giovanni Panozzo
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL. * If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so. * If you
+ * do not wish to do so, delete this exception statement from your
+ * version. * If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ *
+ */
+
+#pragma once
+
+G_BEGIN_DECLS
+
+#include "json-glib/json-glib.h"
+
+JsonNode *remmina_stats_get_all(void);
+
+G_END_DECLS
+
+
diff --git a/remmina/src/remmina_stats_sender.c b/remmina/src/remmina_stats_sender.c
new file mode 100644
index 000000000..e62a52700
--- /dev/null
+++ b/remmina/src/remmina_stats_sender.c
@@ -0,0 +1,200 @@
+/*
+ * Remmina - The GTK+ Remote Desktop Client
+ * Copyright (C) 2009-2011 Vic Lee
+ * Copyright (C) 2014-2015 Antenore Gatta, Fabio Castelli, Giovanni Panozzo
+ * Copyright (C) 2016-2018 Antenore Gatta, Giovanni Panozzo
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL. * If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so. * If you
+ * do not wish to do so, delete this exception statement from your
+ * version. * If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ *
+ */
+
+#include "config.h"
+#include <gtk/gtk.h>
+#include <string.h>
+#include <libsoup/soup.h>
+#include "remmina/remmina_trace_calls.h"
+#include "remmina_stats.h"
+#include "remmina_pref.h"
+
+#if !JSON_CHECK_VERSION(1,2,0)
+ #define json_node_unref(x) json_node_free(x)
+#endif
+
+/* Timers */
+#define PERIODIC_CHECK_1ST_MS 60000
+#define PERIODIC_CHECK_INTERVAL_MS 600000
+
+#define PERIODIC_UPLOAD_INTERVAL_SEC 604800
+
+#define PERIODIC_UPLOAD_URL "http://s1.casa.panozzo.it/remmina/upload_stats.php"
+
+
+static gint periodic_check_source;
+static gint periodic_check_counter;
+
+#define DEBUG_HTTP_SERVER_RESPONSE
+
+
+static void soup_callback(SoupSession *session, SoupMessage *msg, gpointer user_data)
+{
+ TRACE_CALL(__func__);
+ gchar *s = (gchar *)user_data;
+ SoupBuffer *sb;
+ gboolean passed;
+ GTimeVal t;
+
+ g_free(s);
+
+#ifdef DEBUG_HTTP_SERVER_RESPONSE
+ printf("soup_callback status code is %d\n", msg->status_code);
+#endif
+
+ if (msg->status_code != 200)
+ return;
+
+ passed = FALSE;
+ sb = soup_message_body_flatten(msg->response_body);
+ if (strncmp(sb->data,"200 ", 4) != 0) {
+#ifdef DEBUG_HTTP_SERVER_RESPONSE
+ puts("Error from server side script:");
+ puts(sb->data);
+#endif
+ } else {
+ passed = TRUE;
+ }
+ soup_buffer_free(sb);
+
+ if (passed) {
+ g_get_current_time(&t);
+ remmina_pref.periodic_usage_stats_last_sent = t.tv_sec;
+ remmina_pref_save();
+ }
+
+}
+
+static gboolean remmina_stats_collector_done(gpointer data)
+{
+ TRACE_CALL(__func__);
+ JsonNode *n;
+ JsonGenerator *g;
+ gchar *s;
+ SoupSession *ss;
+ SoupMessage *msg;
+
+ n = (JsonNode *)data;
+ if (n == NULL)
+ return G_SOURCE_REMOVE;
+
+ g = json_generator_new();
+ json_generator_set_root(g, n);
+ s = json_generator_to_data(g, NULL);
+ g_object_unref(g);
+ json_node_unref(n);
+
+ ss = soup_session_new();
+ msg = soup_message_new("POST", PERIODIC_UPLOAD_URL);
+ soup_message_set_request(msg, "application/json",
+ SOUP_MEMORY_COPY, s, strlen (s));
+ soup_session_queue_message(ss, msg, soup_callback, s);
+
+#ifdef DEBUG_HTTP_SERVER_RESPONSE
+ printf("Starting upload to url %s\n", PERIODIC_UPLOAD_URL);
+#endif
+
+ return G_SOURCE_REMOVE;
+}
+
+static gpointer remmina_stats_collector(gpointer data)
+{
+ TRACE_CALL(__func__);
+ JsonNode *n;
+ n = remmina_stats_get_all();
+
+ /* stats collecting is done. Notify main thread calling
+ * remmina_stats_collector_done() */
+ g_idle_add(remmina_stats_collector_done, n);
+
+ return NULL;
+}
+
+void remmina_stats_sender_send()
+{
+ TRACE_CALL(__func__);
+
+ g_thread_new("stats_collector", remmina_stats_collector, NULL);
+
+
+}
+
+
+static gboolean remmina_stats_sender_periodic_check(gpointer user_data)
+{
+ TRACE_CALL(__func__);
+ GTimeVal t;
+ glong next;
+
+ if (!remmina_pref.periodic_usage_stats_permission_asked || !remmina_pref.periodic_usage_stats_permitted)
+ return G_SOURCE_REMOVE;
+
+ /* Calculate "next" upload time based on last sent time */
+ next = remmina_pref.periodic_usage_stats_last_sent + PERIODIC_UPLOAD_INTERVAL_SEC;
+ g_get_current_time(&t);
+ /* If current time is after "next" or clock is going back (but > 1/1/2018), then do send stats */
+ if (t.tv_sec > next || (t.tv_sec < remmina_pref.periodic_usage_stats_last_sent && t.tv_sec > 1514764800)) {
+ remmina_stats_sender_send();
+ } else {
+#ifdef DEBUG_HTTP_SERVER_RESPONSE
+ printf("Doing nothing: next upload is scheduled in %ld seconds\n", (next-t.tv_sec));
+#endif
+ }
+
+ periodic_check_counter ++;
+ if (periodic_check_counter <= 1) {
+ /* Reschedule periodic check less frequently after 1st tick.
+ * Note that PERIODIC_CHECK_INTERVAL_MS becomes also a retry interval in case of
+ * upload failure */
+ periodic_check_source = g_timeout_add_full(G_PRIORITY_LOW, PERIODIC_CHECK_INTERVAL_MS, remmina_stats_sender_periodic_check, NULL, NULL);
+ return G_SOURCE_REMOVE;
+ }
+ return G_SOURCE_CONTINUE;
+}
+
+void remmina_stats_sender_schedule()
+{
+ TRACE_CALL(__func__);
+ /* If permitted, schedule the 1st statistics periodic check */
+ if (remmina_pref.periodic_usage_stats_permission_asked && remmina_pref.periodic_usage_stats_permitted) {
+ periodic_check_counter = 0;
+ periodic_check_source = g_timeout_add_full(G_PRIORITY_LOW, PERIODIC_CHECK_1ST_MS, remmina_stats_sender_periodic_check, NULL, NULL);
+ } else
+ periodic_check_source = 0;
+}
+
+
+
diff --git a/remmina/src/remmina_stats_sender.h b/remmina/src/remmina_stats_sender.h
new file mode 100644
index 000000000..2b2703e17
--- /dev/null
+++ b/remmina/src/remmina_stats_sender.h
@@ -0,0 +1,48 @@
+/*
+ * Remmina - The GTK+ Remote Desktop Client
+ * Copyright (C) 2009-2011 Vic Lee
+ * Copyright (C) 2014-2015 Antenore Gatta, Fabio Castelli, Giovanni Panozzo
+ * Copyright (C) 2016-2018 Antenore Gatta, Giovanni Panozzo
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL. * If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so. * If you
+ * do not wish to do so, delete this exception statement from your
+ * version. * If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ *
+ */
+
+#pragma once
+
+G_BEGIN_DECLS
+
+void remmina_stats_sender_schedule(void);
+
+/* This is only for testing purposes: force a SEND */
+void remmina_stats_sender_send(void);
+
+G_END_DECLS
+
+
diff --git a/remmina/ui/remmina_main.glade b/remmina/ui/remmina_main.glade
index 5722d2468..3c300e4ae 100644
--- a/remmina/ui/remmina_main.glade
+++ b/remmina/ui/remmina_main.glade
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.20.0
+<!-- Generated with glade 3.20.2
Remmina - The GTK+ Remmina Remote Desktop Client
Copyright (C) Antenore Gatta & Giovanni Panozzo 2014-2017
@@ -238,6 +238,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
<signal name="delete-event" handler="remmina_main_on_delete_event" swapped="no"/>
<signal name="destroy" handler="remmina_main_destroy" swapped="no"/>
<signal name="drag-data-received" handler="remmina_main_on_drag_data_received" swapped="no"/>
+ <signal name="show" handler="remmina_main_on_show" swapped="no"/>
<signal name="window-state-event" handler="remmina_main_on_window_state_event" swapped="no"/>
<child>
<object class="GtkBox" id="box_main">
@@ -618,7 +619,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
- <property name="position">2</property>
+ <property name="position">1</property>
</packing>
</child>
<child>
@@ -709,7 +710,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
- <property name="position">3</property>
+ <property name="position">2</property>
</packing>
</child>
<child>
@@ -720,6 +721,69 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box_ustat">
+ <property name="can_focus">False</property>
+ <property name="margin_left">4</property>
+ <property name="margin_right">4</property>
+ <property name="margin_top">4</property>
+ <property name="margin_bottom">4</property>
+ <property name="spacing">5</property>
+ <child>
+ <object class="GtkLabel" id="ustat_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Do you allow Remmina to send periodic anonymous usage statistics to its developers?</property>
+ <property name="wrap">True</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="ustat_no">
+ <property name="label">gtk-no</property>
+ <property name="width_request">60</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="valign">center</property>
+ <property name="use_stock">True</property>
+ <signal name="clicked" handler="remmina_main_on_click_ustat_no" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="ustat_yes">
+ <property name="label">gtk-yes</property>
+ <property name="width_request">70</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="valign">center</property>
+ <property name="use_stock">True</property>
+ <signal name="clicked" handler="remmina_main_on_click_ustat_yes" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="padding">3</property>
<property name="position">4</property>
</packing>
</child>
diff --git a/snap/snapcraft.yaml.in b/snap/snapcraft.yaml.in
index 30364b2d9..989d7fe87 100644
--- a/snap/snapcraft.yaml.in
+++ b/snap/snapcraft.yaml.in
@@ -99,6 +99,8 @@ parts:
- libgcrypt20-dev
- libgnome-keyring-dev
- libgtk-3-dev
+ - libjson-glib-dev
+ - libsoup2.4-dev
- libspice-client-gtk-3.0-dev
- libspice-protocol-dev
- libtelepathy-glib-dev