mirror of
https://git.proxmox.com/git/fwupd
synced 2025-05-15 03:23:18 +00:00

This allows somebody to mirror the CDN without resigning the metadata files. Fixes: https://github.com/hughsie/fwupd/issues/186
993 lines
25 KiB
C
993 lines
25 KiB
C
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
|
|
*
|
|
* Copyright (C) 2017 Richard Hughes <richard@hughsie.com>
|
|
*
|
|
* Licensed under the GNU Lesser General Public License Version 2.1
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library 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
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include "fwupd-error.h"
|
|
#include "fwupd-remote-private.h"
|
|
|
|
static void fwupd_remote_finalize (GObject *obj);
|
|
|
|
struct _FwupdRemote
|
|
{
|
|
GObject parent_instance;
|
|
FwupdRemoteKind kind;
|
|
FwupdKeyringKind keyring_kind;
|
|
gchar *id;
|
|
gchar *firmware_base_uri;
|
|
gchar *metadata_uri;
|
|
gchar *metadata_uri_sig;
|
|
gchar *username;
|
|
gchar *password;
|
|
gchar *filename;
|
|
gchar *filename_asc;
|
|
gchar *filename_cache;
|
|
gchar *filename_cache_sig;
|
|
gboolean enabled;
|
|
SoupURI *uri;
|
|
SoupURI *uri_asc;
|
|
gint priority;
|
|
guint64 mtime;
|
|
gchar **order_after;
|
|
gchar **order_before;
|
|
};
|
|
|
|
enum {
|
|
PROP_0,
|
|
PROP_ID,
|
|
PROP_ENABLED,
|
|
PROP_LAST
|
|
};
|
|
|
|
G_DEFINE_TYPE (FwupdRemote, fwupd_remote, G_TYPE_OBJECT)
|
|
|
|
static void
|
|
fwupd_remote_set_username (FwupdRemote *self, const gchar *username)
|
|
{
|
|
if (username != NULL && username[0] == '\0')
|
|
username = NULL;
|
|
self->username = g_strdup (username);
|
|
if (self->uri != NULL)
|
|
soup_uri_set_user (self->uri, username);
|
|
if (self->uri_asc != NULL)
|
|
soup_uri_set_user (self->uri_asc, username);
|
|
}
|
|
|
|
static void
|
|
fwupd_remote_set_password (FwupdRemote *self, const gchar *password)
|
|
{
|
|
if (password != NULL && password[0] == '\0')
|
|
password = NULL;
|
|
self->password = g_strdup (password);
|
|
if (self->uri != NULL)
|
|
soup_uri_set_password (self->uri, password);
|
|
if (self->uri_asc != NULL)
|
|
soup_uri_set_password (self->uri_asc, password);
|
|
}
|
|
|
|
static void
|
|
fwupd_remote_set_kind (FwupdRemote *self, FwupdRemoteKind kind)
|
|
{
|
|
self->kind = kind;
|
|
}
|
|
|
|
static void
|
|
fwupd_remote_set_keyring_kind (FwupdRemote *self, FwupdKeyringKind keyring_kind)
|
|
{
|
|
self->keyring_kind = keyring_kind;
|
|
}
|
|
|
|
/* note, this has to be set before url */
|
|
static void
|
|
fwupd_remote_set_id (FwupdRemote *self, const gchar *id)
|
|
{
|
|
g_free (self->id);
|
|
self->id = g_strdup (id);
|
|
g_strdelimit (self->id, ".", '\0');
|
|
}
|
|
|
|
static const gchar *
|
|
fwupd_remote_get_suffix_for_keyring_kind (FwupdKeyringKind keyring_kind)
|
|
{
|
|
if (keyring_kind == FWUPD_KEYRING_KIND_GPG)
|
|
return ".asc";
|
|
if (keyring_kind == FWUPD_KEYRING_KIND_PKCS7)
|
|
return ".p7b";
|
|
return NULL;
|
|
}
|
|
|
|
/* note, this has to be set before username and password */
|
|
static void
|
|
fwupd_remote_set_metadata_uri (FwupdRemote *self, const gchar *metadata_uri)
|
|
{
|
|
const gchar *suffix;
|
|
g_autofree gchar *basename = NULL;
|
|
g_autofree gchar *basename_asc = NULL;
|
|
|
|
/* save this so we can export the object as a GVariant */
|
|
self->metadata_uri = g_strdup (metadata_uri);
|
|
|
|
/* build the URI */
|
|
self->uri = soup_uri_new (metadata_uri);
|
|
if (self->uri == NULL)
|
|
return;
|
|
|
|
/* generate some plausible local filenames */
|
|
basename = g_path_get_basename (soup_uri_get_path (self->uri));
|
|
self->filename = g_strdup_printf ("%s-%s", self->id, basename);
|
|
|
|
/* generate the signature URI too */
|
|
suffix = fwupd_remote_get_suffix_for_keyring_kind (self->keyring_kind);
|
|
if (suffix != NULL) {
|
|
self->metadata_uri_sig = g_strconcat (metadata_uri, suffix, NULL);
|
|
self->uri_asc = fwupd_remote_build_uri (self, self->metadata_uri_sig, NULL);
|
|
basename_asc = g_path_get_basename (soup_uri_get_path (self->uri_asc));
|
|
self->filename_asc = g_strdup_printf ("%s-%s", self->id, basename_asc);
|
|
}
|
|
}
|
|
|
|
/* note, this has to be set after MetadataURI */
|
|
static void
|
|
fwupd_remote_set_firmware_base_uri (FwupdRemote *self, const gchar *firmware_base_uri)
|
|
{
|
|
self->firmware_base_uri = g_strdup (firmware_base_uri);
|
|
}
|
|
|
|
/**
|
|
* fwupd_remote_kind_from_string:
|
|
* @kind: a string, e.g. "download"
|
|
*
|
|
* Converts an printable string to an enumerated type.
|
|
*
|
|
* Returns: a #FwupdRemoteKind, e.g. %FWUPD_REMOTE_KIND_DOWNLOAD
|
|
*
|
|
* Since: 0.9.6
|
|
**/
|
|
FwupdRemoteKind
|
|
fwupd_remote_kind_from_string (const gchar *kind)
|
|
{
|
|
if (g_strcmp0 (kind, "download") == 0)
|
|
return FWUPD_REMOTE_KIND_DOWNLOAD;
|
|
if (g_strcmp0 (kind, "local") == 0)
|
|
return FWUPD_REMOTE_KIND_LOCAL;
|
|
return FWUPD_REMOTE_KIND_UNKNOWN;
|
|
}
|
|
|
|
/**
|
|
* fwupd_remote_kind_to_string:
|
|
* @kind: a #FwupdRemoteKind, e.g. %FWUPD_REMOTE_KIND_DOWNLOAD
|
|
*
|
|
* Converts an enumerated type to a printable string.
|
|
*
|
|
* Returns: a string, e.g. "download"
|
|
*
|
|
* Since: 0.9.6
|
|
**/
|
|
const gchar *
|
|
fwupd_remote_kind_to_string (FwupdRemoteKind kind)
|
|
{
|
|
if (kind == FWUPD_REMOTE_KIND_DOWNLOAD)
|
|
return "download";
|
|
if (kind == FWUPD_REMOTE_KIND_LOCAL)
|
|
return "local";
|
|
return NULL;
|
|
}
|
|
|
|
static void
|
|
fwupd_remote_set_filename_cache (FwupdRemote *self, const gchar *filename)
|
|
{
|
|
const gchar *suffix;
|
|
|
|
g_return_if_fail (FWUPD_IS_REMOTE (self));
|
|
|
|
g_free (self->filename_cache);
|
|
self->filename_cache = g_strdup (filename);
|
|
|
|
/* create for all remote types */
|
|
suffix = fwupd_remote_get_suffix_for_keyring_kind (self->keyring_kind);
|
|
if (suffix != NULL) {
|
|
g_free (self->filename_cache_sig);
|
|
self->filename_cache_sig = g_strconcat (filename, suffix, NULL);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* fwupd_remote_load_from_filename:
|
|
* @self: A #FwupdRemote
|
|
* @filename: A filename
|
|
* @cancellable: the #GCancellable, or %NULL
|
|
* @error: the #GError, or %NULL
|
|
*
|
|
* Sets up the remote ready for use. Most other methods call this
|
|
* for you, and do you only need to call this if you are just watching
|
|
* the self.
|
|
*
|
|
* Returns: %TRUE for success
|
|
*
|
|
* Since: 0.9.3
|
|
**/
|
|
gboolean
|
|
fwupd_remote_load_from_filename (FwupdRemote *self,
|
|
const gchar *filename,
|
|
GCancellable *cancellable,
|
|
GError **error)
|
|
{
|
|
const gchar *group = "fwupd Remote";
|
|
g_autofree gchar *firmware_base_uri = NULL;
|
|
g_autofree gchar *id = NULL;
|
|
g_autofree gchar *keyring_kind = NULL;
|
|
g_autofree gchar *metadata_uri = NULL;
|
|
g_autofree gchar *order_after = NULL;
|
|
g_autofree gchar *order_before = NULL;
|
|
g_autoptr(GKeyFile) kf = NULL;
|
|
|
|
g_return_val_if_fail (FWUPD_IS_REMOTE (self), FALSE);
|
|
g_return_val_if_fail (filename != NULL, FALSE);
|
|
g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
|
|
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
|
|
|
/* set ID */
|
|
id = g_path_get_basename (filename);
|
|
fwupd_remote_set_id (self, id);
|
|
|
|
/* load file */
|
|
kf = g_key_file_new ();
|
|
if (!g_key_file_load_from_file (kf, filename, G_KEY_FILE_NONE, error))
|
|
return FALSE;
|
|
|
|
/* get verification type, falling back to GPG */
|
|
keyring_kind = g_key_file_get_string (kf, group, "Keyring", NULL);
|
|
if (keyring_kind == NULL) {
|
|
self->keyring_kind = FWUPD_KEYRING_KIND_GPG;
|
|
} else {
|
|
self->keyring_kind = fwupd_keyring_kind_from_string (keyring_kind);
|
|
if (self->keyring_kind == FWUPD_KEYRING_KIND_UNKNOWN) {
|
|
g_set_error (error,
|
|
FWUPD_ERROR,
|
|
FWUPD_ERROR_INVALID_FILE,
|
|
"Failed to parse type '%s'",
|
|
keyring_kind);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
/* all remotes need a URI, even if it's file:// to the cache */
|
|
metadata_uri = g_key_file_get_string (kf, group, "MetadataURI", error);
|
|
if (metadata_uri == NULL)
|
|
return FALSE;
|
|
if (g_str_has_prefix (metadata_uri, "file://")) {
|
|
self->kind = FWUPD_REMOTE_KIND_LOCAL;
|
|
} else if (g_str_has_prefix (metadata_uri, "http://") ||
|
|
g_str_has_prefix (metadata_uri, "https://")) {
|
|
self->kind = FWUPD_REMOTE_KIND_DOWNLOAD;
|
|
} else {
|
|
g_set_error (error,
|
|
FWUPD_ERROR,
|
|
FWUPD_ERROR_INVALID_FILE,
|
|
"Failed to parse MetadataURI type '%s'",
|
|
metadata_uri);
|
|
return FALSE;
|
|
}
|
|
|
|
/* extract data */
|
|
self->enabled = g_key_file_get_boolean (kf, group, "Enabled", NULL);
|
|
|
|
/* DOWNLOAD-type remotes */
|
|
if (self->kind == FWUPD_REMOTE_KIND_DOWNLOAD) {
|
|
g_autofree gchar *filename_cache = NULL;
|
|
g_autofree gchar *username = NULL;
|
|
g_autofree gchar *password = NULL;
|
|
|
|
/* the client has to download this and the signature */
|
|
fwupd_remote_set_metadata_uri (self, metadata_uri);
|
|
|
|
/* check the URI was valid */
|
|
if (self->uri == NULL) {
|
|
g_set_error (error,
|
|
FWUPD_ERROR,
|
|
FWUPD_ERROR_INVALID_FILE,
|
|
"Failed to parse URI '%s' in %s",
|
|
metadata_uri, filename);
|
|
return FALSE;
|
|
}
|
|
|
|
/* username and password are optional */
|
|
username = g_key_file_get_string (kf, group, "Username", NULL);
|
|
if (username != NULL)
|
|
fwupd_remote_set_username (self, username);
|
|
password = g_key_file_get_string (kf, group, "Password", NULL);
|
|
if (password != NULL)
|
|
fwupd_remote_set_password (self, password);
|
|
|
|
/* set cache to /var/lib... */
|
|
filename_cache = g_build_filename (LOCALSTATEDIR,
|
|
"lib",
|
|
"fwupd",
|
|
"remotes.d",
|
|
self->id,
|
|
"metadata.xml.gz",
|
|
NULL);
|
|
fwupd_remote_set_filename_cache (self, filename_cache);
|
|
}
|
|
|
|
/* all LOCAL remotes have to include a valid MetadataURI */
|
|
if (self->kind == FWUPD_REMOTE_KIND_LOCAL) {
|
|
const gchar *filename_cache = metadata_uri;
|
|
if (g_str_has_prefix (filename_cache, "file://"))
|
|
filename_cache += 7;
|
|
fwupd_remote_set_filename_cache (self, filename_cache);
|
|
}
|
|
|
|
/* the base URI is optional */
|
|
firmware_base_uri = g_key_file_get_string (kf, group, "FirmwareBaseURI", NULL);
|
|
if (firmware_base_uri != NULL)
|
|
fwupd_remote_set_firmware_base_uri (self, firmware_base_uri);
|
|
|
|
/* dep logic */
|
|
order_before = g_key_file_get_string (kf, group, "OrderBefore", NULL);
|
|
if (order_before != NULL)
|
|
self->order_before = g_strsplit_set (order_before, ",:;", -1);
|
|
order_after = g_key_file_get_string (kf, group, "OrderAfter", NULL);
|
|
if (order_after != NULL)
|
|
self->order_after = g_strsplit_set (order_after, ",:;", -1);
|
|
|
|
/* success */
|
|
return TRUE;
|
|
}
|
|
|
|
/* private */
|
|
gchar **
|
|
fwupd_remote_get_order_after (FwupdRemote *self)
|
|
{
|
|
g_return_val_if_fail (FWUPD_IS_REMOTE (self), NULL);
|
|
return self->order_after;
|
|
}
|
|
|
|
/* private */
|
|
gchar **
|
|
fwupd_remote_get_order_before (FwupdRemote *self)
|
|
{
|
|
g_return_val_if_fail (FWUPD_IS_REMOTE (self), NULL);
|
|
return self->order_before;
|
|
}
|
|
|
|
/**
|
|
* fwupd_remote_get_filename_cache:
|
|
* @self: A #FwupdRemote
|
|
*
|
|
* Gets the path and filename that the remote is using for a cache.
|
|
*
|
|
* Returns: a string, or %NULL for unset
|
|
*
|
|
* Since: 0.9.6
|
|
**/
|
|
const gchar *
|
|
fwupd_remote_get_filename_cache (FwupdRemote *self)
|
|
{
|
|
g_return_val_if_fail (FWUPD_IS_REMOTE (self), NULL);
|
|
return self->filename_cache;
|
|
}
|
|
|
|
/**
|
|
* fwupd_remote_get_filename_cache_sig:
|
|
* @self: A #FwupdRemote
|
|
*
|
|
* Gets the path and filename that the remote is using for a signature cache.
|
|
*
|
|
* Returns: a string, or %NULL for unset
|
|
*
|
|
* Since: 0.9.7
|
|
**/
|
|
const gchar *
|
|
fwupd_remote_get_filename_cache_sig (FwupdRemote *self)
|
|
{
|
|
g_return_val_if_fail (FWUPD_IS_REMOTE (self), NULL);
|
|
return self->filename_cache_sig;
|
|
}
|
|
|
|
/**
|
|
* fwupd_remote_get_priority:
|
|
* @self: A #FwupdRemote
|
|
*
|
|
* Gets the priority of the remote, where bigger numbers are better.
|
|
*
|
|
* Returns: a priority, or 0 for the default value
|
|
*
|
|
* Since: 0.9.5
|
|
**/
|
|
gint
|
|
fwupd_remote_get_priority (FwupdRemote *self)
|
|
{
|
|
g_return_val_if_fail (FWUPD_IS_REMOTE (self), 0);
|
|
return self->priority;
|
|
}
|
|
|
|
/**
|
|
* fwupd_remote_get_kind:
|
|
* @self: A #FwupdRemote
|
|
*
|
|
* Gets the kind of the remote.
|
|
*
|
|
* Returns: a #FwupdRemoteKind, e.g. #FWUPD_REMOTE_KIND_LOCAL
|
|
*
|
|
* Since: 0.9.6
|
|
**/
|
|
FwupdRemoteKind
|
|
fwupd_remote_get_kind (FwupdRemote *self)
|
|
{
|
|
g_return_val_if_fail (FWUPD_IS_REMOTE (self), 0);
|
|
return self->kind;
|
|
}
|
|
|
|
/**
|
|
* fwupd_remote_get_keyring_kind:
|
|
* @self: A #FwupdRemote
|
|
*
|
|
* Gets the keyring kind of the remote.
|
|
*
|
|
* Returns: a #FwupdKeyringKind, e.g. #FWUPD_KEYRING_KIND_GPG
|
|
*
|
|
* Since: 0.9.7
|
|
**/
|
|
FwupdKeyringKind
|
|
fwupd_remote_get_keyring_kind (FwupdRemote *self)
|
|
{
|
|
g_return_val_if_fail (FWUPD_IS_REMOTE (self), 0);
|
|
return self->keyring_kind;
|
|
}
|
|
|
|
/**
|
|
* fwupd_remote_get_age:
|
|
* @self: A #FwupdRemote
|
|
*
|
|
* Gets the age of the remote in seconds.
|
|
*
|
|
* Returns: a age, or %G_MAXUINT64 for unavailable
|
|
*
|
|
* Since: 0.9.5
|
|
**/
|
|
guint64
|
|
fwupd_remote_get_age (FwupdRemote *self)
|
|
{
|
|
guint64 now;
|
|
g_return_val_if_fail (FWUPD_IS_REMOTE (self), 0);
|
|
now = (guint64) g_get_real_time () / G_USEC_PER_SEC;
|
|
if (self->mtime > now)
|
|
return G_MAXUINT64;
|
|
return now - self->mtime;
|
|
}
|
|
|
|
/* private */
|
|
void
|
|
fwupd_remote_set_priority (FwupdRemote *self, gint priority)
|
|
{
|
|
g_return_if_fail (FWUPD_IS_REMOTE (self));
|
|
self->priority = priority;
|
|
}
|
|
|
|
/* private */
|
|
void
|
|
fwupd_remote_set_mtime (FwupdRemote *self, guint64 mtime)
|
|
{
|
|
g_return_if_fail (FWUPD_IS_REMOTE (self));
|
|
self->mtime = mtime;
|
|
}
|
|
|
|
const gchar *
|
|
fwupd_remote_get_filename (FwupdRemote *self)
|
|
{
|
|
g_return_val_if_fail (FWUPD_IS_REMOTE (self), NULL);
|
|
return self->filename;
|
|
}
|
|
|
|
const gchar *
|
|
fwupd_remote_get_username (FwupdRemote *self)
|
|
{
|
|
g_return_val_if_fail (FWUPD_IS_REMOTE (self), NULL);
|
|
return self->username;
|
|
}
|
|
|
|
const gchar *
|
|
fwupd_remote_get_password (FwupdRemote *self)
|
|
{
|
|
g_return_val_if_fail (FWUPD_IS_REMOTE (self), NULL);
|
|
return self->password;
|
|
}
|
|
|
|
const gchar *
|
|
fwupd_remote_get_filename_asc (FwupdRemote *self)
|
|
{
|
|
g_return_val_if_fail (FWUPD_IS_REMOTE (self), NULL);
|
|
return self->filename_asc;
|
|
}
|
|
|
|
/**
|
|
* fwupd_remote_build_uri:
|
|
* @self: A #FwupdRemote
|
|
* @url: the URL to use
|
|
* @error: the #GError, or %NULL
|
|
*
|
|
* Builds a URI for the URL using the username and password set for the remote,
|
|
* including any basename URI substitution.
|
|
*
|
|
* Returns: (transfer full): a #SoupURI, or %NULL for error
|
|
*
|
|
* Since: 0.9.3
|
|
**/
|
|
SoupURI *
|
|
fwupd_remote_build_uri (FwupdRemote *self, const gchar *url, GError **error)
|
|
{
|
|
SoupURI *uri;
|
|
|
|
g_return_val_if_fail (FWUPD_IS_REMOTE (self), NULL);
|
|
g_return_val_if_fail (url != NULL, NULL);
|
|
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
|
|
|
/* create URI, substituting if required */
|
|
if (self->firmware_base_uri != NULL) {
|
|
g_autoptr(SoupURI) uri_tmp = NULL;
|
|
g_autofree gchar *basename = NULL;
|
|
g_autofree gchar *url2 = NULL;
|
|
uri_tmp = soup_uri_new (url);
|
|
if (uri_tmp == NULL) {
|
|
g_set_error (error,
|
|
FWUPD_ERROR,
|
|
FWUPD_ERROR_INVALID_FILE,
|
|
"Failed to parse URI '%s'", url);
|
|
return NULL;
|
|
}
|
|
basename = g_path_get_basename (soup_uri_get_path (uri_tmp));
|
|
url2 = g_build_filename (self->firmware_base_uri, basename, NULL);
|
|
uri = soup_uri_new (url2);
|
|
if (uri == NULL) {
|
|
g_set_error (error,
|
|
FWUPD_ERROR,
|
|
FWUPD_ERROR_INVALID_FILE,
|
|
"Failed to parse URI '%s'", url2);
|
|
return NULL;
|
|
}
|
|
} else {
|
|
uri = soup_uri_new (url);
|
|
if (uri == NULL) {
|
|
g_set_error (error,
|
|
FWUPD_ERROR,
|
|
FWUPD_ERROR_INVALID_FILE,
|
|
"Failed to parse URI '%s'", url);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
/* set the username and password from the metadata URI */
|
|
if (self->uri != NULL) {
|
|
soup_uri_set_user (uri, soup_uri_get_user (self->uri));
|
|
soup_uri_set_password (uri, soup_uri_get_password (self->uri));
|
|
}
|
|
return uri;
|
|
}
|
|
|
|
/**
|
|
* fwupd_remote_build_firmware_uri:
|
|
* @self: A #FwupdRemote
|
|
* @url: the URL to use
|
|
* @error: the #GError, or %NULL
|
|
*
|
|
* Builds a URI for the URL using the username and password set for the remote,
|
|
* including any basename URI substitution.
|
|
*
|
|
* Returns: (transfer full): a URI, or %NULL for error
|
|
*
|
|
* Since: 0.9.7
|
|
**/
|
|
gchar *
|
|
fwupd_remote_build_firmware_uri (FwupdRemote *self, const gchar *url, GError **error)
|
|
{
|
|
g_autoptr(SoupURI) uri = fwupd_remote_build_uri (self, url, error);
|
|
if (uri == NULL)
|
|
return NULL;
|
|
return soup_uri_to_string (uri, FALSE);
|
|
}
|
|
|
|
/**
|
|
* fwupd_remote_get_uri:
|
|
* @self: A #FwupdRemote
|
|
*
|
|
* Gets the URI for the remote metadata.
|
|
*
|
|
* Returns: (transfer none): a #SoupURI, or %NULL for invalid.
|
|
*
|
|
* Since: 0.9.3
|
|
**/
|
|
SoupURI *
|
|
fwupd_remote_get_uri (FwupdRemote *self)
|
|
{
|
|
g_return_val_if_fail (FWUPD_IS_REMOTE (self), NULL);
|
|
return self->uri;
|
|
}
|
|
|
|
/**
|
|
* fwupd_remote_get_uri_asc:
|
|
* @self: A #FwupdRemote
|
|
*
|
|
* Gets the URI for the remote signature.
|
|
*
|
|
* Returns: (transfer none): a #SoupURI, or %NULL for invalid.
|
|
*
|
|
* Since: 0.9.3
|
|
**/
|
|
SoupURI *
|
|
fwupd_remote_get_uri_asc (FwupdRemote *self)
|
|
{
|
|
g_return_val_if_fail (FWUPD_IS_REMOTE (self), NULL);
|
|
return self->uri_asc;
|
|
}
|
|
|
|
/**
|
|
* fwupd_remote_get_metadata_uri:
|
|
* @self: A #FwupdRemote
|
|
*
|
|
* Gets the URI for the remote metadata.
|
|
*
|
|
* Returns: (transfer none): a URI, or %NULL for invalid.
|
|
*
|
|
* Since: 0.9.7
|
|
**/
|
|
const gchar *
|
|
fwupd_remote_get_metadata_uri (FwupdRemote *self)
|
|
{
|
|
g_return_val_if_fail (FWUPD_IS_REMOTE (self), NULL);
|
|
return self->metadata_uri;
|
|
}
|
|
|
|
/**
|
|
* fwupd_remote_get_metadata_uri_sig:
|
|
* @self: A #FwupdRemote
|
|
*
|
|
* Gets the URI for the remote metadata signature.
|
|
*
|
|
* Returns: (transfer none): a URI, or %NULL for invalid.
|
|
*
|
|
* Since: 0.9.7
|
|
**/
|
|
const gchar *
|
|
fwupd_remote_get_metadata_uri_sig (FwupdRemote *self)
|
|
{
|
|
g_return_val_if_fail (FWUPD_IS_REMOTE (self), NULL);
|
|
return self->metadata_uri_sig;
|
|
}
|
|
|
|
/**
|
|
* fwupd_remote_get_firmware_base_uri:
|
|
* @self: A #FwupdRemote
|
|
*
|
|
* Gets the base URI for firmware.
|
|
*
|
|
* Returns: (transfer none): a URI, or %NULL for unset.
|
|
*
|
|
* Since: 0.9.7
|
|
**/
|
|
const gchar *
|
|
fwupd_remote_get_firmware_base_uri (FwupdRemote *self)
|
|
{
|
|
g_return_val_if_fail (FWUPD_IS_REMOTE (self), NULL);
|
|
return self->firmware_base_uri;
|
|
}
|
|
|
|
/**
|
|
* fwupd_remote_get_enabled:
|
|
* @self: A #FwupdRemote
|
|
*
|
|
* Gets if the remote is enabled and should be used.
|
|
*
|
|
* Returns: a #TRUE if the remote is enabled
|
|
*
|
|
* Since: 0.9.3
|
|
**/
|
|
gboolean
|
|
fwupd_remote_get_enabled (FwupdRemote *self)
|
|
{
|
|
g_return_val_if_fail (FWUPD_IS_REMOTE (self), FALSE);
|
|
return self->enabled;
|
|
}
|
|
|
|
/**
|
|
* fwupd_remote_get_id:
|
|
* @self: A #FwupdRemote
|
|
*
|
|
* Gets the remote ID, e.g. "lvfs-testing".
|
|
*
|
|
* Returns: a string, or %NULL if unset
|
|
*
|
|
* Since: 0.9.3
|
|
**/
|
|
const gchar *
|
|
fwupd_remote_get_id (FwupdRemote *self)
|
|
{
|
|
g_return_val_if_fail (FWUPD_IS_REMOTE (self), NULL);
|
|
return self->id;
|
|
}
|
|
|
|
static void
|
|
fwupd_remote_to_variant_builder (FwupdRemote *self, GVariantBuilder *builder)
|
|
{
|
|
if (self->id != NULL) {
|
|
g_variant_builder_add (builder, "{sv}", "Id",
|
|
g_variant_new_string (self->id));
|
|
}
|
|
if (self->username != NULL) {
|
|
g_variant_builder_add (builder, "{sv}", "Username",
|
|
g_variant_new_string (self->username));
|
|
}
|
|
if (self->password != NULL) {
|
|
g_variant_builder_add (builder, "{sv}", "Password",
|
|
g_variant_new_string (self->password));
|
|
}
|
|
if (self->metadata_uri != NULL) {
|
|
g_variant_builder_add (builder, "{sv}", "Url",
|
|
g_variant_new_string (self->metadata_uri));
|
|
}
|
|
if (self->firmware_base_uri != NULL) {
|
|
g_variant_builder_add (builder, "{sv}", "FirmwareBaseUri",
|
|
g_variant_new_string (self->firmware_base_uri));
|
|
}
|
|
if (self->priority != 0) {
|
|
g_variant_builder_add (builder, "{sv}", "Priority",
|
|
g_variant_new_int32 (self->priority));
|
|
}
|
|
if (self->kind != FWUPD_REMOTE_KIND_UNKNOWN) {
|
|
g_variant_builder_add (builder, "{sv}", "Type",
|
|
g_variant_new_uint32 (self->kind));
|
|
}
|
|
if (self->keyring_kind != FWUPD_KEYRING_KIND_UNKNOWN) {
|
|
g_variant_builder_add (builder, "{sv}", "Keyring",
|
|
g_variant_new_uint32 (self->keyring_kind));
|
|
}
|
|
if (self->mtime != 0) {
|
|
g_variant_builder_add (builder, "{sv}", "ModificationTime",
|
|
g_variant_new_uint64 (self->mtime));
|
|
}
|
|
if (self->filename_cache != NULL) {
|
|
g_variant_builder_add (builder, "{sv}", "FilenameCache",
|
|
g_variant_new_string (self->filename_cache));
|
|
}
|
|
g_variant_builder_add (builder, "{sv}", "Enabled",
|
|
g_variant_new_boolean (self->enabled));
|
|
}
|
|
|
|
static void
|
|
fwupd_remote_set_from_variant_iter (FwupdRemote *self, GVariantIter *iter)
|
|
{
|
|
GVariant *value;
|
|
const gchar *key;
|
|
g_autoptr(GVariantIter) iter2 = g_variant_iter_copy (iter);
|
|
g_autoptr(GVariantIter) iter3 = g_variant_iter_copy (iter);
|
|
|
|
/* three passes, as we have to construct Id -> Url -> * */
|
|
while (g_variant_iter_loop (iter, "{sv}", &key, &value)) {
|
|
if (g_strcmp0 (key, "Id") == 0)
|
|
fwupd_remote_set_id (self, g_variant_get_string (value, NULL));
|
|
if (g_strcmp0 (key, "Type") == 0)
|
|
fwupd_remote_set_kind (self, g_variant_get_uint32 (value));
|
|
if (g_strcmp0 (key, "Keyring") == 0)
|
|
fwupd_remote_set_keyring_kind (self, g_variant_get_uint32 (value));
|
|
}
|
|
while (g_variant_iter_loop (iter2, "{sv}", &key, &value)) {
|
|
if (g_strcmp0 (key, "Url") == 0)
|
|
fwupd_remote_set_metadata_uri (self, g_variant_get_string (value, NULL));
|
|
if (g_strcmp0 (key, "FilenameCache") == 0)
|
|
fwupd_remote_set_filename_cache (self, g_variant_get_string (value, NULL));
|
|
}
|
|
while (g_variant_iter_loop (iter3, "{sv}", &key, &value)) {
|
|
if (g_strcmp0 (key, "Username") == 0) {
|
|
fwupd_remote_set_username (self, g_variant_get_string (value, NULL));
|
|
} else if (g_strcmp0 (key, "Password") == 0) {
|
|
fwupd_remote_set_password (self, g_variant_get_string (value, NULL));
|
|
} else if (g_strcmp0 (key, "Enabled") == 0) {
|
|
self->enabled = g_variant_get_boolean (value);
|
|
} else if (g_strcmp0 (key, "Priority") == 0) {
|
|
self->priority = g_variant_get_int32 (value);
|
|
} else if (g_strcmp0 (key, "ModificationTime") == 0) {
|
|
self->mtime = g_variant_get_uint64 (value);
|
|
} else if (g_strcmp0 (key, "FirmwareBaseUri") == 0) {
|
|
fwupd_remote_set_firmware_base_uri (self, g_variant_get_string (value, NULL));
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* fwupd_remote_to_data:
|
|
* @remote: A #FwupdRemote
|
|
* @type_string: The Gvariant type string, e.g. "a{sv}" or "(a{sv})"
|
|
*
|
|
* Creates a GVariant from the remote data.
|
|
*
|
|
* Returns: the GVariant, or %NULL for error
|
|
*
|
|
* Since: 0.9.5
|
|
**/
|
|
GVariant *
|
|
fwupd_remote_to_data (FwupdRemote *self, const gchar *type_string)
|
|
{
|
|
GVariantBuilder builder;
|
|
|
|
g_return_val_if_fail (FWUPD_IS_REMOTE (self), NULL);
|
|
g_return_val_if_fail (type_string != NULL, NULL);
|
|
|
|
/* create an array with all the metadata in */
|
|
g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY);
|
|
fwupd_remote_to_variant_builder (self, &builder);
|
|
|
|
/* supported types */
|
|
if (g_strcmp0 (type_string, "a{sv}") == 0)
|
|
return g_variant_new ("a{sv}", &builder);
|
|
if (g_strcmp0 (type_string, "(a{sv})") == 0)
|
|
return g_variant_new ("(a{sv})", &builder);
|
|
return NULL;
|
|
}
|
|
|
|
static void
|
|
fwupd_remote_get_property (GObject *obj, guint prop_id,
|
|
GValue *value, GParamSpec *pspec)
|
|
{
|
|
FwupdRemote *self = FWUPD_REMOTE (obj);
|
|
|
|
switch (prop_id) {
|
|
case PROP_ENABLED:
|
|
g_value_set_boolean (value, self->enabled);
|
|
break;
|
|
case PROP_ID:
|
|
g_value_set_string (value, self->id);
|
|
break;
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
fwupd_remote_set_property (GObject *obj, guint prop_id,
|
|
const GValue *value, GParamSpec *pspec)
|
|
{
|
|
FwupdRemote *self = FWUPD_REMOTE (obj);
|
|
|
|
switch (prop_id) {
|
|
case PROP_ENABLED:
|
|
self->enabled = g_value_get_boolean (value);
|
|
break;
|
|
case PROP_ID:
|
|
self->id = g_value_get_string (value);
|
|
break;
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
fwupd_remote_class_init (FwupdRemoteClass *klass)
|
|
{
|
|
GParamSpec *pspec;
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
object_class->finalize = fwupd_remote_finalize;
|
|
object_class->get_property = fwupd_remote_get_property;
|
|
object_class->set_property = fwupd_remote_set_property;
|
|
|
|
/**
|
|
* FwupdRemote:id:
|
|
*
|
|
* The remote ID.
|
|
*
|
|
* Since: 0.9.3
|
|
*/
|
|
pspec = g_param_spec_string ("id", NULL, NULL,
|
|
NULL, G_PARAM_READWRITE);
|
|
g_object_class_install_property (object_class, PROP_ID, pspec);
|
|
|
|
/**
|
|
* FwupdRemote:enabled:
|
|
*
|
|
* If the remote is enabled and should be used.
|
|
*
|
|
* Since: 0.9.3
|
|
*/
|
|
pspec = g_param_spec_boolean ("enabled", NULL, NULL,
|
|
FALSE, G_PARAM_READWRITE);
|
|
g_object_class_install_property (object_class, PROP_ENABLED, pspec);
|
|
}
|
|
|
|
static void
|
|
fwupd_remote_init (FwupdRemote *self)
|
|
{
|
|
}
|
|
|
|
static void
|
|
fwupd_remote_finalize (GObject *obj)
|
|
{
|
|
FwupdRemote *self = FWUPD_REMOTE (obj);
|
|
|
|
g_free (self->id);
|
|
g_free (self->metadata_uri);
|
|
g_free (self->firmware_base_uri);
|
|
g_free (self->username);
|
|
g_free (self->password);
|
|
g_free (self->filename);
|
|
g_free (self->filename_asc);
|
|
g_free (self->filename_cache);
|
|
g_free (self->filename_cache_sig);
|
|
g_strfreev (self->order_after);
|
|
g_strfreev (self->order_before);
|
|
if (self->uri != NULL)
|
|
soup_uri_free (self->uri);
|
|
if (self->uri_asc != NULL)
|
|
soup_uri_free (self->uri_asc);
|
|
|
|
G_OBJECT_CLASS (fwupd_remote_parent_class)->finalize (obj);
|
|
}
|
|
|
|
/**
|
|
* fwupd_remote_new_from_data:
|
|
* @data: a #GVariant
|
|
*
|
|
* Creates a new remote using packed data.
|
|
*
|
|
* Returns: a new #FwupdRemote, or %NULL if @data was invalid
|
|
*
|
|
* Since: 0.9.5
|
|
**/
|
|
FwupdRemote *
|
|
fwupd_remote_new_from_data (GVariant *data)
|
|
{
|
|
FwupdRemote *rel = NULL;
|
|
const gchar *type_string;
|
|
g_autoptr(GVariantIter) iter = NULL;
|
|
|
|
type_string = g_variant_get_type_string (data);
|
|
if (g_strcmp0 (type_string, "(a{sv})") == 0) {
|
|
rel = fwupd_remote_new ();
|
|
g_variant_get (data, "(a{sv})", &iter);
|
|
fwupd_remote_set_from_variant_iter (rel, iter);
|
|
fwupd_remote_set_from_variant_iter (rel, iter);
|
|
} else if (g_strcmp0 (type_string, "a{sv}") == 0) {
|
|
rel = fwupd_remote_new ();
|
|
g_variant_get (data, "a{sv}", &iter);
|
|
fwupd_remote_set_from_variant_iter (rel, iter);
|
|
} else {
|
|
g_warning ("type %s not known", type_string);
|
|
}
|
|
return rel;
|
|
}
|
|
|
|
/**
|
|
* fwupd_remote_new:
|
|
*
|
|
* Creates a new fwupd remote.
|
|
*
|
|
* Returns: a new #FwupdRemote
|
|
*
|
|
* Since: 0.9.3
|
|
**/
|
|
FwupdRemote *
|
|
fwupd_remote_new (void)
|
|
{
|
|
FwupdRemote *self;
|
|
self = g_object_new (FWUPD_TYPE_REMOTE, NULL);
|
|
return FWUPD_REMOTE (self);
|
|
}
|