mirror of
https://git.proxmox.com/git/fwupd
synced 2025-08-15 20:08:16 +00:00
Add a 'report-history' command to fwupdmgr
This shares your history with a reporting server, typically the LVFS. NOTE: no data is sent without the user opting-in, and the data sent is shown to the user before upload.
This commit is contained in:
parent
b58104895d
commit
0a7bc97317
183
src/fu-util.c
183
src/fu-util.c
@ -237,6 +237,26 @@ fu_util_prompt_for_number (guint maxnum)
|
|||||||
return answer;
|
return answer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
fu_util_prompt_for_boolean (gboolean def)
|
||||||
|
{
|
||||||
|
do {
|
||||||
|
char buffer[4];
|
||||||
|
if (!fgets (buffer, sizeof (buffer), stdin))
|
||||||
|
continue;
|
||||||
|
if (strlen (buffer) == sizeof (buffer) - 1)
|
||||||
|
continue;
|
||||||
|
if (g_strcmp0 (buffer, "\n") == 0)
|
||||||
|
return def;
|
||||||
|
buffer[0] = g_ascii_toupper (buffer[0]);
|
||||||
|
if (g_strcmp0 (buffer, "Y\n") == 0)
|
||||||
|
return TRUE;
|
||||||
|
if (g_strcmp0 (buffer, "N\n") == 0)
|
||||||
|
return FALSE;
|
||||||
|
} while (TRUE);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
static FwupdDevice *
|
static FwupdDevice *
|
||||||
fu_util_prompt_for_device (FuUtilPrivate *priv, GError **error)
|
fu_util_prompt_for_device (FuUtilPrivate *priv, GError **error)
|
||||||
{
|
{
|
||||||
@ -569,6 +589,163 @@ fu_util_clear_history (FuUtilPrivate *priv, gchar **values, GError **error)
|
|||||||
return fu_history_remove_all (history, error);
|
return fu_history_remove_all (history, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
fu_util_report_history_for_uri (FuUtilPrivate *priv,
|
||||||
|
const gchar *report_uri,
|
||||||
|
GPtrArray *devices,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
guint status_code;
|
||||||
|
g_autofree gchar *data = NULL;
|
||||||
|
g_autoptr(SoupMessage) msg = NULL;
|
||||||
|
|
||||||
|
/* convert to JSON */
|
||||||
|
data = fwupd_build_history_report_json (devices, error);
|
||||||
|
if (data == NULL)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/* ask for permission */
|
||||||
|
fu_util_print_data (_("Target"), report_uri);
|
||||||
|
fu_util_print_data (_("Payload"), data);
|
||||||
|
g_print ("%s [Y|n]: ", _("Proceed with upload?"));
|
||||||
|
if (!fu_util_prompt_for_boolean (TRUE)) {
|
||||||
|
g_set_error_literal (error,
|
||||||
|
FWUPD_ERROR,
|
||||||
|
FWUPD_ERROR_PERMISSION_DENIED,
|
||||||
|
"User declined action");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* POST request */
|
||||||
|
msg = soup_message_new (SOUP_METHOD_POST, report_uri);
|
||||||
|
soup_message_set_request (msg, "application/json; charset=utf-8",
|
||||||
|
SOUP_MEMORY_COPY, data, strlen (data));
|
||||||
|
status_code = soup_session_send_message (priv->soup_session, msg);
|
||||||
|
g_debug ("server returned: %s", msg->response_body->data);
|
||||||
|
if (!SOUP_STATUS_IS_SUCCESSFUL (status_code)) {
|
||||||
|
g_set_error (error,
|
||||||
|
FWUPD_ERROR,
|
||||||
|
FWUPD_ERROR_INVALID_FILE,
|
||||||
|
"Failed to upload to %s: %s",
|
||||||
|
report_uri, soup_status_get_phrase (status_code));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
fu_util_report_history (FuUtilPrivate *priv, gchar **values, GError **error)
|
||||||
|
{
|
||||||
|
g_autoptr(GHashTable) remote_id_uri_map = NULL;
|
||||||
|
g_autoptr(GHashTable) report_map = NULL;
|
||||||
|
g_autoptr(GList) uris = NULL;
|
||||||
|
g_autoptr(GPtrArray) devices = NULL;
|
||||||
|
g_autoptr(GPtrArray) remotes = NULL;
|
||||||
|
|
||||||
|
/* set up networking */
|
||||||
|
if (!fu_util_setup_networking (priv, error))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/* create a map of RemoteID to RemoteURI */
|
||||||
|
remotes = fwupd_client_get_remotes (priv->client, NULL, error);
|
||||||
|
if (remotes == NULL)
|
||||||
|
return FALSE;
|
||||||
|
remote_id_uri_map = g_hash_table_new (g_str_hash, g_str_equal);
|
||||||
|
for (guint i = 0; i < remotes->len; i++) {
|
||||||
|
FwupdRemote *remote = g_ptr_array_index (remotes, i);
|
||||||
|
if (fwupd_remote_get_id (remote) == NULL)
|
||||||
|
continue;
|
||||||
|
if (fwupd_remote_get_report_uri (remote) == NULL)
|
||||||
|
continue;
|
||||||
|
g_debug ("adding %s for %s",
|
||||||
|
fwupd_remote_get_report_uri (remote),
|
||||||
|
fwupd_remote_get_id (remote));
|
||||||
|
g_hash_table_insert (remote_id_uri_map,
|
||||||
|
(gpointer) fwupd_remote_get_id (remote),
|
||||||
|
(gpointer) fwupd_remote_get_report_uri (remote));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get all devices from the history database, then filter them,
|
||||||
|
* adding to a hash map of report-ids */
|
||||||
|
devices = fwupd_client_get_history (priv->client, NULL, error);
|
||||||
|
if (devices == NULL)
|
||||||
|
return FALSE;
|
||||||
|
report_map = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||||
|
g_free, (GDestroyNotify) g_ptr_array_unref);
|
||||||
|
for (guint i = 0; i < devices->len; i++) {
|
||||||
|
FwupdDevice *dev = g_ptr_array_index (devices, i);
|
||||||
|
FwupdRelease *rel = fwupd_device_get_release_default (dev);
|
||||||
|
const gchar *remote_id;
|
||||||
|
const gchar *remote_uri;
|
||||||
|
GPtrArray *devices_tmp;
|
||||||
|
|
||||||
|
/* filter, if not forcing */
|
||||||
|
if ((priv->flags & FWUPD_INSTALL_FLAG_FORCE) == 0) {
|
||||||
|
if (fwupd_device_has_flag (dev, FWUPD_DEVICE_FLAG_REPORTED))
|
||||||
|
continue;
|
||||||
|
if (!fwupd_device_has_flag (dev, FWUPD_DEVICE_FLAG_SUPPORTED))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* find the RemoteURI to use for the device */
|
||||||
|
remote_id = fwupd_release_get_remote_id (rel);
|
||||||
|
if (remote_id == NULL) {
|
||||||
|
g_debug ("%s has no RemoteID", fwupd_device_get_id (dev));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
remote_uri = g_hash_table_lookup (remote_id_uri_map, remote_id);
|
||||||
|
if (remote_uri == NULL) {
|
||||||
|
g_debug ("%s has no RemoteURI", remote_id);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* add this to the hash map */
|
||||||
|
devices_tmp = g_hash_table_lookup (report_map, remote_uri);
|
||||||
|
if (devices_tmp == NULL) {
|
||||||
|
devices_tmp = g_ptr_array_new ();
|
||||||
|
g_hash_table_insert (report_map, g_strdup (remote_uri), devices_tmp);
|
||||||
|
}
|
||||||
|
g_debug ("using %s for %s", remote_uri, fwupd_device_get_id (dev));
|
||||||
|
g_ptr_array_add (devices_tmp, dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* nothing to report */
|
||||||
|
if (g_hash_table_size (report_map) == 0) {
|
||||||
|
g_set_error_literal (error,
|
||||||
|
FWUPD_ERROR,
|
||||||
|
FWUPD_ERROR_NOT_SUPPORTED,
|
||||||
|
"No reports require uploading");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* process each uri */
|
||||||
|
uris = g_hash_table_get_keys (report_map);
|
||||||
|
for (GList *l = uris; l != NULL; l = l->next) {
|
||||||
|
const gchar *uri = l->data;
|
||||||
|
GPtrArray *devices_tmp = g_hash_table_lookup (report_map, uri);
|
||||||
|
if (!fu_util_report_history_for_uri (priv, uri, devices_tmp, error))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* mark each device as reported */
|
||||||
|
for (guint i = 0; i < devices->len; i++) {
|
||||||
|
FwupdDevice *dev = g_ptr_array_index (devices, i);
|
||||||
|
if (fwupd_device_has_flag (dev, FWUPD_DEVICE_FLAG_REPORTED))
|
||||||
|
continue;
|
||||||
|
if (!fwupd_device_has_flag (dev, FWUPD_DEVICE_FLAG_SUPPORTED))
|
||||||
|
continue;
|
||||||
|
g_debug ("setting flag on %s", fwupd_device_get_id (dev));
|
||||||
|
if (!fwupd_client_modify_device (priv->client,
|
||||||
|
fwupd_device_get_id (dev),
|
||||||
|
"Flags", "reported",
|
||||||
|
NULL, error))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
fu_util_get_history (FuUtilPrivate *priv, gchar **values, GError **error)
|
fu_util_get_history (FuUtilPrivate *priv, gchar **values, GError **error)
|
||||||
{
|
{
|
||||||
@ -1716,6 +1893,12 @@ main (int argc, char *argv[])
|
|||||||
/* TRANSLATORS: command description */
|
/* TRANSLATORS: command description */
|
||||||
_("Erase all firmware update history"),
|
_("Erase all firmware update history"),
|
||||||
fu_util_clear_history);
|
fu_util_clear_history);
|
||||||
|
fu_util_add (priv->cmd_array,
|
||||||
|
"report-history",
|
||||||
|
NULL,
|
||||||
|
/* TRANSLATORS: command description */
|
||||||
|
_("Share firmware history with the developers"),
|
||||||
|
fu_util_report_history);
|
||||||
fu_util_add (priv->cmd_array,
|
fu_util_add (priv->cmd_array,
|
||||||
"install",
|
"install",
|
||||||
"FILE [ID]",
|
"FILE [ID]",
|
||||||
|
Loading…
Reference in New Issue
Block a user