|
|
02512f |
From f135d985e80c85e1578cd60eeb79bd974788031f Mon Sep 17 00:00:00 2001
|
|
|
02512f |
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
|
|
|
02512f |
Date: Wed, 14 Feb 2018 20:52:37 +0800
|
|
|
02512f |
Subject: [PATCH] sharing: Enable settings widget for gnome-remote-desktop
|
|
|
02512f |
|
|
|
02512f |
Enable support for manipulating GNOME Remote Desktop settings. Settings
|
|
|
02512f |
are done via the org.gnome.desktop.remote-desktop.vnc schema.
|
|
|
02512f |
Configuring the VNC password is done via libsecret, thus libsecret is
|
|
|
02512f |
added as a dependency.
|
|
|
02512f |
---
|
|
|
02512f |
meson.build | 1 +
|
|
|
02512f |
panels/sharing/cc-gnome-remote-desktop.c | 171 +++++++++++++++++++++++
|
|
|
02512f |
panels/sharing/cc-gnome-remote-desktop.h | 49 +++++++
|
|
|
02512f |
panels/sharing/cc-sharing-panel.c | 62 +++++++-
|
|
|
02512f |
panels/sharing/meson.build | 3 +-
|
|
|
02512f |
5 files changed, 282 insertions(+), 4 deletions(-)
|
|
|
02512f |
create mode 100644 panels/sharing/cc-gnome-remote-desktop.c
|
|
|
02512f |
create mode 100644 panels/sharing/cc-gnome-remote-desktop.h
|
|
|
02512f |
|
|
|
02512f |
diff --git a/meson.build b/meson.build
|
|
|
02512f |
index 84e04334c..3017b180a 100644
|
|
|
02512f |
--- a/meson.build
|
|
|
02512f |
+++ b/meson.build
|
|
|
02512f |
@@ -109,6 +109,7 @@ pulse_mainloop_dep = dependency('libpulse-mainloop-glib', version: pulse_req_ver
|
|
|
02512f |
upower_glib_dep = dependency('upower-glib', version: '>= 0.99.6')
|
|
|
02512f |
x11_dep = dependency('x11')
|
|
|
02512f |
xi_dep = dependency('xi', version: '>= 1.2')
|
|
|
02512f |
+libsecret_dep = dependency('libsecret-1')
|
|
|
02512f |
|
|
|
02512f |
m_dep = cc.find_library('m')
|
|
|
02512f |
|
|
|
02512f |
diff --git a/panels/sharing/cc-gnome-remote-desktop.c b/panels/sharing/cc-gnome-remote-desktop.c
|
|
|
02512f |
new file mode 100644
|
|
|
02512f |
index 000000000..8420fddca
|
|
|
02512f |
--- /dev/null
|
|
|
02512f |
+++ b/panels/sharing/cc-gnome-remote-desktop.c
|
|
|
02512f |
@@ -0,0 +1,171 @@
|
|
|
02512f |
+/*
|
|
|
02512f |
+ * Copyright (C) 2018 Red Hat, Inc.
|
|
|
02512f |
+ *
|
|
|
02512f |
+ * This program is free software; you can redistribute it and/or modify
|
|
|
02512f |
+ * it under the terms of the GNU General Public License as published by
|
|
|
02512f |
+ * the Free Software Foundation; either version 2 of the License, or
|
|
|
02512f |
+ * (at your option) any later version.
|
|
|
02512f |
+ *
|
|
|
02512f |
+ * This program is distributed in the hope that it will be useful,
|
|
|
02512f |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
02512f |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
02512f |
+ * GNU General Public License for more details.
|
|
|
02512f |
+ *
|
|
|
02512f |
+ * You should have received a copy of the GNU General Public License
|
|
|
02512f |
+ * along with this program; if not, write to the Free Software
|
|
|
02512f |
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
|
02512f |
+ *
|
|
|
02512f |
+ */
|
|
|
02512f |
+
|
|
|
02512f |
+#include "config.h"
|
|
|
02512f |
+
|
|
|
02512f |
+#include "cc-gnome-remote-desktop.h"
|
|
|
02512f |
+
|
|
|
02512f |
+const SecretSchema *
|
|
|
02512f |
+cc_grd_vnc_password_get_schema (void)
|
|
|
02512f |
+{
|
|
|
02512f |
+ static const SecretSchema grd_vnc_password_schema = {
|
|
|
02512f |
+ .name = "org.gnome.RemoteDesktop.VncPassword",
|
|
|
02512f |
+ .flags = SECRET_SCHEMA_NONE,
|
|
|
02512f |
+ .attributes = {
|
|
|
02512f |
+ { "password", SECRET_SCHEMA_ATTRIBUTE_STRING },
|
|
|
02512f |
+ { "NULL", 0 },
|
|
|
02512f |
+ },
|
|
|
02512f |
+ };
|
|
|
02512f |
+
|
|
|
02512f |
+ return &grd_vnc_password_schema;
|
|
|
02512f |
+}
|
|
|
02512f |
+
|
|
|
02512f |
+gboolean
|
|
|
02512f |
+cc_grd_get_is_auth_method_prompt (GValue *value,
|
|
|
02512f |
+ GVariant *variant,
|
|
|
02512f |
+ gpointer user_data)
|
|
|
02512f |
+{
|
|
|
02512f |
+ const char * auth_method;
|
|
|
02512f |
+
|
|
|
02512f |
+ auth_method = g_variant_get_string (variant, NULL);
|
|
|
02512f |
+
|
|
|
02512f |
+ if (g_strcmp0 (auth_method, "prompt") == 0)
|
|
|
02512f |
+ {
|
|
|
02512f |
+ g_value_set_boolean (value, TRUE);
|
|
|
02512f |
+ }
|
|
|
02512f |
+ else if (g_strcmp0 (auth_method, "password") == 0)
|
|
|
02512f |
+ {
|
|
|
02512f |
+ g_value_set_boolean (value, FALSE);
|
|
|
02512f |
+ }
|
|
|
02512f |
+ else
|
|
|
02512f |
+ {
|
|
|
02512f |
+ g_warning ("Unhandled VNC auth method %s", auth_method);
|
|
|
02512f |
+ g_value_set_boolean (value, FALSE);
|
|
|
02512f |
+ }
|
|
|
02512f |
+
|
|
|
02512f |
+ return TRUE;
|
|
|
02512f |
+}
|
|
|
02512f |
+
|
|
|
02512f |
+GVariant *
|
|
|
02512f |
+cc_grd_set_is_auth_method_prompt (const GValue *value,
|
|
|
02512f |
+ const GVariantType *type,
|
|
|
02512f |
+ gpointer user_data)
|
|
|
02512f |
+{
|
|
|
02512f |
+ char *auth_method;
|
|
|
02512f |
+
|
|
|
02512f |
+ if (g_value_get_boolean (value))
|
|
|
02512f |
+ auth_method = "prompt";
|
|
|
02512f |
+ else
|
|
|
02512f |
+ auth_method = "password";
|
|
|
02512f |
+
|
|
|
02512f |
+ return g_variant_new_string (auth_method);
|
|
|
02512f |
+}
|
|
|
02512f |
+
|
|
|
02512f |
+gboolean
|
|
|
02512f |
+cc_grd_get_is_auth_method_password (GValue *value,
|
|
|
02512f |
+ GVariant *variant,
|
|
|
02512f |
+ gpointer user_data)
|
|
|
02512f |
+{
|
|
|
02512f |
+ const char *auth_method;
|
|
|
02512f |
+
|
|
|
02512f |
+ auth_method = g_variant_get_string (variant, NULL);
|
|
|
02512f |
+
|
|
|
02512f |
+ if (g_strcmp0 (auth_method, "prompt") == 0)
|
|
|
02512f |
+ {
|
|
|
02512f |
+ g_value_set_boolean (value, FALSE);
|
|
|
02512f |
+ }
|
|
|
02512f |
+ else if (g_strcmp0 (auth_method, "password") == 0)
|
|
|
02512f |
+ {
|
|
|
02512f |
+ g_value_set_boolean (value, TRUE);
|
|
|
02512f |
+ }
|
|
|
02512f |
+ else
|
|
|
02512f |
+ {
|
|
|
02512f |
+ g_warning ("Unhandled VNC auth method %s", auth_method);
|
|
|
02512f |
+ g_value_set_boolean (value, FALSE);
|
|
|
02512f |
+ }
|
|
|
02512f |
+
|
|
|
02512f |
+ return TRUE;
|
|
|
02512f |
+}
|
|
|
02512f |
+
|
|
|
02512f |
+GVariant *
|
|
|
02512f |
+cc_grd_set_is_auth_method_password (const GValue *value,
|
|
|
02512f |
+ const GVariantType *type,
|
|
|
02512f |
+ gpointer user_data)
|
|
|
02512f |
+{
|
|
|
02512f |
+ char *auth_method;
|
|
|
02512f |
+
|
|
|
02512f |
+ if (g_value_get_boolean (value))
|
|
|
02512f |
+ auth_method = "password";
|
|
|
02512f |
+ else
|
|
|
02512f |
+ auth_method = "prompt";
|
|
|
02512f |
+
|
|
|
02512f |
+ return g_variant_new_string (auth_method);
|
|
|
02512f |
+}
|
|
|
02512f |
+
|
|
|
02512f |
+static void
|
|
|
02512f |
+on_password_stored (GObject *source,
|
|
|
02512f |
+ GAsyncResult *result,
|
|
|
02512f |
+ gpointer user_data)
|
|
|
02512f |
+{
|
|
|
02512f |
+ GtkEntry *entry = GTK_ENTRY (user_data);
|
|
|
02512f |
+ GError *error = NULL;
|
|
|
02512f |
+
|
|
|
02512f |
+ if (!secret_password_store_finish (result, &error))
|
|
|
02512f |
+ {
|
|
|
02512f |
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
|
|
02512f |
+ {
|
|
|
02512f |
+ g_warning ("Failed to store VNC password: %s", error->message);
|
|
|
02512f |
+ g_object_set_data (G_OBJECT (entry),
|
|
|
02512f |
+ "vnc-password-cancellable", NULL);
|
|
|
02512f |
+ }
|
|
|
02512f |
+ g_error_free (error);
|
|
|
02512f |
+ }
|
|
|
02512f |
+ else
|
|
|
02512f |
+ {
|
|
|
02512f |
+ g_object_set_data (G_OBJECT (entry),
|
|
|
02512f |
+ "vnc-password-cancellable", NULL);
|
|
|
02512f |
+ }
|
|
|
02512f |
+}
|
|
|
02512f |
+
|
|
|
02512f |
+void
|
|
|
02512f |
+cc_grd_on_vnc_password_entry_notify_text (GtkEntry *entry,
|
|
|
02512f |
+ GParamSpec *pspec,
|
|
|
02512f |
+ gpointer user_data)
|
|
|
02512f |
+{
|
|
|
02512f |
+ GCancellable *cancellable;
|
|
|
02512f |
+ const char *password;
|
|
|
02512f |
+
|
|
|
02512f |
+ cancellable = g_object_get_data (G_OBJECT (entry), "vnc-password-cancellable");
|
|
|
02512f |
+ if (cancellable)
|
|
|
02512f |
+ g_cancellable_cancel (cancellable);
|
|
|
02512f |
+
|
|
|
02512f |
+ cancellable = g_cancellable_new ();
|
|
|
02512f |
+ g_object_set_data_full (G_OBJECT (entry),
|
|
|
02512f |
+ "vnc-password-cancellable",
|
|
|
02512f |
+ cancellable, g_object_unref);
|
|
|
02512f |
+
|
|
|
02512f |
+ password = gtk_entry_get_text (entry);
|
|
|
02512f |
+
|
|
|
02512f |
+ secret_password_store (CC_GRD_VNC_PASSWORD_SCHEMA,
|
|
|
02512f |
+ SECRET_COLLECTION_DEFAULT,
|
|
|
02512f |
+ "GNOME Remote Desktop VNC password",
|
|
|
02512f |
+ password,
|
|
|
02512f |
+ cancellable, on_password_stored, entry,
|
|
|
02512f |
+ NULL);
|
|
|
02512f |
+}
|
|
|
02512f |
diff --git a/panels/sharing/cc-gnome-remote-desktop.h b/panels/sharing/cc-gnome-remote-desktop.h
|
|
|
02512f |
new file mode 100644
|
|
|
02512f |
index 000000000..2a4819986
|
|
|
02512f |
--- /dev/null
|
|
|
02512f |
+++ b/panels/sharing/cc-gnome-remote-desktop.h
|
|
|
02512f |
@@ -0,0 +1,49 @@
|
|
|
02512f |
+/*
|
|
|
02512f |
+ * Copyright (C) 2018 Red Hat, Inc.
|
|
|
02512f |
+ *
|
|
|
02512f |
+ * This program is free software; you can redistribute it and/or modify
|
|
|
02512f |
+ * it under the terms of the GNU General Public License as published by
|
|
|
02512f |
+ * the Free Software Foundation; either version 2 of the License, or
|
|
|
02512f |
+ * (at your option) any later version.
|
|
|
02512f |
+ *
|
|
|
02512f |
+ * This program is distributed in the hope that it will be useful,
|
|
|
02512f |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
02512f |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
02512f |
+ * GNU General Public License for more details.
|
|
|
02512f |
+ *
|
|
|
02512f |
+ * You should have received a copy of the GNU General Public License
|
|
|
02512f |
+ * along with this program; if not, write to the Free Software
|
|
|
02512f |
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
|
02512f |
+ *
|
|
|
02512f |
+ */
|
|
|
02512f |
+
|
|
|
02512f |
+#ifndef CC_GNOME_REMOTE_DESKTOP_H
|
|
|
02512f |
+#define CC_GNOME_REMOTE_DESKTOP_H
|
|
|
02512f |
+
|
|
|
02512f |
+#include <gtk/gtk.h>
|
|
|
02512f |
+#include <libsecret/secret.h>
|
|
|
02512f |
+
|
|
|
02512f |
+const SecretSchema * cc_grd_vnc_password_get_schema (void);
|
|
|
02512f |
+#define CC_GRD_VNC_PASSWORD_SCHEMA cc_grd_vnc_password_get_schema ()
|
|
|
02512f |
+
|
|
|
02512f |
+gboolean cc_grd_get_is_auth_method_prompt (GValue *value,
|
|
|
02512f |
+ GVariant *variant,
|
|
|
02512f |
+ gpointer user_data);
|
|
|
02512f |
+
|
|
|
02512f |
+GVariant * cc_grd_set_is_auth_method_prompt (const GValue *value,
|
|
|
02512f |
+ const GVariantType *type,
|
|
|
02512f |
+ gpointer user_data);
|
|
|
02512f |
+
|
|
|
02512f |
+gboolean cc_grd_get_is_auth_method_password (GValue *value,
|
|
|
02512f |
+ GVariant *variant,
|
|
|
02512f |
+ gpointer user_data);
|
|
|
02512f |
+
|
|
|
02512f |
+GVariant * cc_grd_set_is_auth_method_password (const GValue *value,
|
|
|
02512f |
+ const GVariantType *type,
|
|
|
02512f |
+ gpointer user_data);
|
|
|
02512f |
+
|
|
|
02512f |
+void cc_grd_on_vnc_password_entry_notify_text (GtkEntry *entry,
|
|
|
02512f |
+ GParamSpec *pspec,
|
|
|
02512f |
+ gpointer user_data);
|
|
|
02512f |
+
|
|
|
02512f |
+#endif /* CC_GNOME_REMOTE_DESKTOP_H */
|
|
|
02512f |
diff --git a/panels/sharing/cc-sharing-panel.c b/panels/sharing/cc-sharing-panel.c
|
|
|
02512f |
index 8b35c9a31..adcbcdc86 100644
|
|
|
02512f |
--- a/panels/sharing/cc-sharing-panel.c
|
|
|
02512f |
+++ b/panels/sharing/cc-sharing-panel.c
|
|
|
02512f |
@@ -30,6 +30,7 @@
|
|
|
02512f |
#include "cc-media-sharing.h"
|
|
|
02512f |
#include "cc-sharing-networks.h"
|
|
|
02512f |
#include "cc-sharing-switch.h"
|
|
|
02512f |
+#include "cc-gnome-remote-desktop.h"
|
|
|
02512f |
#include "org.gnome.SettingsDaemon.Sharing.h"
|
|
|
02512f |
|
|
|
02512f |
#ifdef GDK_WINDOWING_WAYLAND
|
|
|
02512f |
@@ -66,6 +67,13 @@ _gtk_builder_get_widget (GtkBuilder *builder,
|
|
|
02512f |
#define VINO_SCHEMA_ID "org.gnome.Vino"
|
|
|
02512f |
#define FILE_SHARING_SCHEMA_ID "org.gnome.desktop.file-sharing"
|
|
|
02512f |
#define GNOME_REMOTE_DESKTOP_SCHEMA_ID "org.gnome.desktop.remote-desktop"
|
|
|
02512f |
+#define GNOME_REMOTE_DESKTOP_VNC_SCHEMA_ID "org.gnome.desktop.remote-desktop.vnc"
|
|
|
02512f |
+
|
|
|
02512f |
+typedef enum
|
|
|
02512f |
+{
|
|
|
02512f |
+ GRD_VNC_AUTH_METHOD_PROMPT,
|
|
|
02512f |
+ GRD_VNC_AUTH_METHOD_PASSWORD
|
|
|
02512f |
+} GrdVncAuthMethod;
|
|
|
02512f |
|
|
|
02512f |
struct _CcSharingPanelPrivate
|
|
|
02512f |
{
|
|
|
02512f |
@@ -1077,11 +1085,56 @@ static void
|
|
|
02512f |
cc_sharing_panel_setup_screen_sharing_dialog_gnome_remote_desktop (CcSharingPanel *self)
|
|
|
02512f |
{
|
|
|
02512f |
CcSharingPanelPrivate *priv = self->priv;
|
|
|
02512f |
- GtkWidget *networks, *w;
|
|
|
02512f |
+ GSettings *vnc_settings;
|
|
|
02512f |
+ GtkWidget *networks, *box, *w;
|
|
|
02512f |
+
|
|
|
02512f |
+ cc_sharing_panel_bind_switch_to_widgets (WID ("require-password-radiobutton"),
|
|
|
02512f |
+ WID ("password-grid"),
|
|
|
02512f |
+ NULL);
|
|
|
02512f |
+
|
|
|
02512f |
+ cc_sharing_panel_setup_label_with_hostname (self,
|
|
|
02512f |
+ WID ("screen-sharing-label"));
|
|
|
02512f |
+
|
|
|
02512f |
+ g_object_bind_property (WID ("show-password-checkbutton"), "active",
|
|
|
02512f |
+ WID ("remote-control-password-entry"), "visibility",
|
|
|
02512f |
+ G_BINDING_SYNC_CREATE);
|
|
|
02512f |
+
|
|
|
02512f |
+ /* make sure the password entry is hidden by default */
|
|
|
02512f |
+ g_signal_connect (priv->screen_sharing_dialog, "show",
|
|
|
02512f |
+ G_CALLBACK (screen_sharing_show_cb), self);
|
|
|
02512f |
+
|
|
|
02512f |
+ g_signal_connect (priv->screen_sharing_dialog, "hide",
|
|
|
02512f |
+ G_CALLBACK (screen_sharing_hide_cb), self);
|
|
|
02512f |
+
|
|
|
02512f |
+ /* accept at most 8 bytes in password entry */
|
|
|
02512f |
+ g_signal_connect (WID ("remote-control-password-entry"), "insert-text",
|
|
|
02512f |
+ G_CALLBACK (screen_sharing_password_insert_text_cb), self);
|
|
|
02512f |
+
|
|
|
02512f |
+ /* Bind settings to widgets */
|
|
|
02512f |
+ vnc_settings = g_settings_new (GNOME_REMOTE_DESKTOP_VNC_SCHEMA_ID);
|
|
|
02512f |
+ g_settings_bind (vnc_settings, "view-only",
|
|
|
02512f |
+ WID ("remote-control-checkbutton"), "active",
|
|
|
02512f |
+ G_SETTINGS_BIND_DEFAULT | G_SETTINGS_BIND_INVERT_BOOLEAN);
|
|
|
02512f |
+ g_settings_bind_with_mapping (vnc_settings, "auth-method",
|
|
|
02512f |
+ WID ("approve-connections-radiobutton"), "active",
|
|
|
02512f |
+ G_SETTINGS_BIND_DEFAULT,
|
|
|
02512f |
+ cc_grd_get_is_auth_method_prompt,
|
|
|
02512f |
+ cc_grd_set_is_auth_method_prompt,
|
|
|
02512f |
+ NULL, NULL);
|
|
|
02512f |
+ g_settings_bind_with_mapping (vnc_settings, "auth-method",
|
|
|
02512f |
+ WID ("require-password-radiobutton"), "active",
|
|
|
02512f |
+ G_SETTINGS_BIND_DEFAULT,
|
|
|
02512f |
+ cc_grd_get_is_auth_method_password,
|
|
|
02512f |
+ cc_grd_set_is_auth_method_password,
|
|
|
02512f |
+ NULL, NULL);
|
|
|
02512f |
+ g_signal_connect (WID ("remote-control-password-entry"),
|
|
|
02512f |
+ "notify::text",
|
|
|
02512f |
+ G_CALLBACK (cc_grd_on_vnc_password_entry_notify_text),
|
|
|
02512f |
+ self);
|
|
|
02512f |
|
|
|
02512f |
networks = cc_sharing_networks_new (self->priv->sharing_proxy, "gnome-remote-desktop");
|
|
|
02512f |
- gtk_widget_hide (WID ("remote-control-box"));
|
|
|
02512f |
- gtk_grid_attach (GTK_GRID (WID ("grid3")), networks, 0, 1, 2, 1);
|
|
|
02512f |
+ box = WID ("remote-control-box");
|
|
|
02512f |
+ gtk_box_pack_end (GTK_BOX (box), networks, TRUE, TRUE, 0);
|
|
|
02512f |
gtk_widget_show (networks);
|
|
|
02512f |
|
|
|
02512f |
w = cc_sharing_switch_new (networks);
|
|
|
02512f |
@@ -1116,6 +1169,9 @@ check_remote_desktop_available (CcSharingPanel *self)
|
|
|
02512f |
if (!cc_sharing_panel_check_schema_available (self, GNOME_REMOTE_DESKTOP_SCHEMA_ID))
|
|
|
02512f |
return;
|
|
|
02512f |
|
|
|
02512f |
+ if (!cc_sharing_panel_check_schema_available (self, GNOME_REMOTE_DESKTOP_VNC_SCHEMA_ID))
|
|
|
02512f |
+ return;
|
|
|
02512f |
+
|
|
|
02512f |
priv->remote_desktop_name_watch = g_bus_watch_name (G_BUS_TYPE_SESSION,
|
|
|
02512f |
"org.gnome.Mutter.RemoteDesktop",
|
|
|
02512f |
G_BUS_NAME_WATCHER_FLAGS_NONE,
|
|
|
02512f |
diff --git a/panels/sharing/meson.build b/panels/sharing/meson.build
|
|
|
02512f |
index 5caac36c0..1565a089a 100644
|
|
|
02512f |
--- a/panels/sharing/meson.build
|
|
|
02512f |
+++ b/panels/sharing/meson.build
|
|
|
02512f |
@@ -43,6 +43,7 @@ sources = files(
|
|
|
02512f |
'cc-remote-login.c',
|
|
|
02512f |
'cc-sharing-networks.c',
|
|
|
02512f |
'cc-sharing-switch.c',
|
|
|
02512f |
+ 'cc-gnome-remote-desktop.c',
|
|
|
02512f |
'file-share-properties.c',
|
|
|
02512f |
'vino-preferences.c'
|
|
|
02512f |
)
|
|
|
02512f |
@@ -79,7 +80,7 @@ panels_libs += static_library(
|
|
|
02512f |
cappletname,
|
|
|
02512f |
sources: sources,
|
|
|
02512f |
include_directories: top_inc,
|
|
|
02512f |
- dependencies: common_deps,
|
|
|
02512f |
+ dependencies: [common_deps, libsecret_dep],
|
|
|
02512f |
c_args: cflags
|
|
|
02512f |
)
|
|
|
02512f |
|
|
|
02512f |
--
|
|
|
02512f |
2.17.1
|
|
|
02512f |
|