mirror of
https://github.com/flatpak/flatpak.git
synced 2026-03-26 19:04:56 -04:00
common: Move functions for dealing with AppStream XML to their own file
This seems like an obvious set of functionality to be grouped together in service of the wider goal of making flatpak-utils smaller and more manageable. Signed-off-by: Simon McVittie <smcv@collabora.com>
This commit is contained in:
@@ -28,6 +28,7 @@
|
||||
#include "flatpak-tty-utils-private.h"
|
||||
#include "flatpak-utils-private.h"
|
||||
#include "flatpak-dir-private.h"
|
||||
#include "flatpak-xml-utils-private.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
||||
@@ -57,6 +57,7 @@
|
||||
#include "flatpak-utils-base-private.h"
|
||||
#include "flatpak-variant-private.h"
|
||||
#include "flatpak-variant-impl-private.h"
|
||||
#include "flatpak-xml-utils-private.h"
|
||||
#include "libglnx.h"
|
||||
#include "system-helper/flatpak-system-helper.h"
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "flatpak-utils-private.h"
|
||||
#include "flatpak-uri-private.h"
|
||||
#include "flatpak-dir-private.h"
|
||||
#include "flatpak-xml-utils-private.h"
|
||||
#include "flatpak-zstd-decompressor-private.h"
|
||||
|
||||
#define MAX_JSON_SIZE (1024 * 1024)
|
||||
|
||||
@@ -554,58 +554,12 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC (FlatpakRepoTransaction, flatpak_repo_transaction_
|
||||
|
||||
#define AUTOLOCK(name) G_GNUC_UNUSED __attribute__((cleanup (flatpak_auto_unlock_helper))) GMutex * G_PASTE (auto_unlock, __LINE__) = flatpak_auto_lock_helper (&G_LOCK_NAME (name))
|
||||
|
||||
typedef struct FlatpakXml FlatpakXml;
|
||||
|
||||
struct FlatpakXml
|
||||
{
|
||||
gchar *element_name; /* NULL == text */
|
||||
char **attribute_names;
|
||||
char **attribute_values;
|
||||
char *text;
|
||||
FlatpakXml *parent;
|
||||
FlatpakXml *first_child;
|
||||
FlatpakXml *last_child;
|
||||
FlatpakXml *next_sibling;
|
||||
};
|
||||
|
||||
FlatpakXml *flatpak_xml_new (const gchar *element_name);
|
||||
FlatpakXml *flatpak_xml_new_text (const gchar *text);
|
||||
void flatpak_xml_add (FlatpakXml *parent,
|
||||
FlatpakXml *node);
|
||||
void flatpak_xml_free (FlatpakXml *node);
|
||||
FlatpakXml *flatpak_xml_parse (GInputStream * in,
|
||||
gboolean compressed,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
void flatpak_xml_to_string (FlatpakXml *node,
|
||||
GString *res);
|
||||
FlatpakXml *flatpak_xml_unlink (FlatpakXml *node,
|
||||
FlatpakXml *prev_sibling);
|
||||
FlatpakXml *flatpak_xml_find (FlatpakXml *node,
|
||||
const char *type,
|
||||
FlatpakXml **prev_child_out);
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (FlatpakXml, flatpak_xml_free);
|
||||
|
||||
FlatpakXml *flatpak_appstream_xml_new (void);
|
||||
gboolean flatpak_appstream_xml_migrate (FlatpakXml *source,
|
||||
FlatpakXml *dest,
|
||||
const char *ref,
|
||||
const char *id,
|
||||
GKeyFile *metadata);
|
||||
gboolean flatpak_appstream_xml_root_to_data (FlatpakXml *appstream_root,
|
||||
GBytes **uncompressed,
|
||||
GBytes **compressed,
|
||||
GError **error);
|
||||
gboolean flatpak_repo_generate_appstream (OstreeRepo *repo,
|
||||
const char **gpg_key_ids,
|
||||
const char *gpg_homedir,
|
||||
guint64 timestamp,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
void flatpak_appstream_xml_filter (FlatpakXml *appstream,
|
||||
GRegex *allow_refs,
|
||||
GRegex *deny_refs);
|
||||
|
||||
char * flatpak_filter_glob_to_regexp (const char *glob, gboolean runtime_only, GError **error);
|
||||
gboolean flatpak_parse_filters (const char *data,
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
#include "flatpak-utils-base-private.h"
|
||||
#include "flatpak-utils-private.h"
|
||||
#include "flatpak-variant-impl-private.h"
|
||||
#include "flatpak-xml-utils-private.h"
|
||||
#include "libglnx.h"
|
||||
#include "valgrind-private.h"
|
||||
|
||||
@@ -4963,164 +4964,6 @@ flatpak_mtree_ensure_dir_metadata (OstreeRepo *repo,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
validate_component (FlatpakXml *component,
|
||||
const char *ref,
|
||||
const char *id,
|
||||
char **tags,
|
||||
const char *runtime,
|
||||
const char *sdk)
|
||||
{
|
||||
FlatpakXml *bundle, *text, *prev, *id_node, *id_text_node, *metadata, *value;
|
||||
g_autofree char *id_text = NULL;
|
||||
int i;
|
||||
|
||||
if (g_strcmp0 (component->element_name, "component") != 0)
|
||||
return FALSE;
|
||||
|
||||
id_node = flatpak_xml_find (component, "id", NULL);
|
||||
if (id_node == NULL)
|
||||
return FALSE;
|
||||
|
||||
id_text_node = flatpak_xml_find (id_node, NULL, NULL);
|
||||
if (id_text_node == NULL || id_text_node->text == NULL)
|
||||
return FALSE;
|
||||
|
||||
id_text = g_strstrip (g_strdup (id_text_node->text));
|
||||
|
||||
/* Drop .desktop file suffix (unless the actual app id ends with .desktop) */
|
||||
if (g_str_has_suffix (id_text, ".desktop") &&
|
||||
!g_str_has_suffix (id, ".desktop"))
|
||||
id_text[strlen (id_text) - strlen (".desktop")] = 0;
|
||||
|
||||
if (!g_str_has_prefix (id_text, id))
|
||||
{
|
||||
g_warning ("Invalid id %s", id_text);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
while ((bundle = flatpak_xml_find (component, "bundle", &prev)) != NULL)
|
||||
flatpak_xml_free (flatpak_xml_unlink (bundle, prev));
|
||||
|
||||
bundle = flatpak_xml_new ("bundle");
|
||||
bundle->attribute_names = g_new0 (char *, 2 * 4);
|
||||
bundle->attribute_values = g_new0 (char *, 2 * 4);
|
||||
bundle->attribute_names[0] = g_strdup ("type");
|
||||
bundle->attribute_values[0] = g_strdup ("flatpak");
|
||||
|
||||
i = 1;
|
||||
if (runtime && !g_str_has_prefix (runtime, "runtime/"))
|
||||
{
|
||||
bundle->attribute_names[i] = g_strdup ("runtime");
|
||||
bundle->attribute_values[i] = g_strdup (runtime);
|
||||
i++;
|
||||
}
|
||||
|
||||
if (sdk)
|
||||
{
|
||||
bundle->attribute_names[i] = g_strdup ("sdk");
|
||||
bundle->attribute_values[i] = g_strdup (sdk);
|
||||
i++;
|
||||
}
|
||||
|
||||
text = flatpak_xml_new (NULL);
|
||||
text->text = g_strdup (ref);
|
||||
flatpak_xml_add (bundle, text);
|
||||
|
||||
flatpak_xml_add (component, flatpak_xml_new_text (" "));
|
||||
flatpak_xml_add (component, bundle);
|
||||
flatpak_xml_add (component, flatpak_xml_new_text ("\n "));
|
||||
|
||||
if (tags != NULL && tags[0] != NULL)
|
||||
{
|
||||
metadata = flatpak_xml_find (component, "metadata", NULL);
|
||||
if (metadata == NULL)
|
||||
{
|
||||
metadata = flatpak_xml_new ("metadata");
|
||||
metadata->attribute_names = g_new0 (char *, 1);
|
||||
metadata->attribute_values = g_new0 (char *, 1);
|
||||
|
||||
flatpak_xml_add (component, flatpak_xml_new_text (" "));
|
||||
flatpak_xml_add (component, metadata);
|
||||
flatpak_xml_add (component, flatpak_xml_new_text ("\n "));
|
||||
}
|
||||
|
||||
value = flatpak_xml_new ("value");
|
||||
value->attribute_names = g_new0 (char *, 2);
|
||||
value->attribute_values = g_new0 (char *, 2);
|
||||
value->attribute_names[0] = g_strdup ("key");
|
||||
value->attribute_values[0] = g_strdup ("X-Flatpak-Tags");
|
||||
flatpak_xml_add (metadata, flatpak_xml_new_text ("\n "));
|
||||
flatpak_xml_add (metadata, value);
|
||||
flatpak_xml_add (metadata, flatpak_xml_new_text ("\n "));
|
||||
|
||||
text = flatpak_xml_new (NULL);
|
||||
text->text = g_strjoinv (",", tags);
|
||||
flatpak_xml_add (value, text);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
flatpak_appstream_xml_migrate (FlatpakXml *source,
|
||||
FlatpakXml *dest,
|
||||
const char *ref,
|
||||
const char *id,
|
||||
GKeyFile *metadata)
|
||||
{
|
||||
FlatpakXml *source_components;
|
||||
FlatpakXml *dest_components;
|
||||
FlatpakXml *component;
|
||||
FlatpakXml *prev_component;
|
||||
gboolean migrated = FALSE;
|
||||
g_auto(GStrv) tags = NULL;
|
||||
g_autofree const char *runtime = NULL;
|
||||
g_autofree const char *sdk = NULL;
|
||||
const char *group;
|
||||
|
||||
if (source->first_child == NULL ||
|
||||
source->first_child->next_sibling != NULL ||
|
||||
g_strcmp0 (source->first_child->element_name, "components") != 0)
|
||||
return FALSE;
|
||||
|
||||
if (g_str_has_prefix (ref, "app/"))
|
||||
group = FLATPAK_METADATA_GROUP_APPLICATION;
|
||||
else
|
||||
group = FLATPAK_METADATA_GROUP_RUNTIME;
|
||||
|
||||
tags = g_key_file_get_string_list (metadata, group, FLATPAK_METADATA_KEY_TAGS,
|
||||
NULL, NULL);
|
||||
runtime = g_key_file_get_string (metadata, group,
|
||||
FLATPAK_METADATA_KEY_RUNTIME, NULL);
|
||||
sdk = g_key_file_get_string (metadata, group, FLATPAK_METADATA_KEY_SDK, NULL);
|
||||
|
||||
source_components = source->first_child;
|
||||
dest_components = dest->first_child;
|
||||
|
||||
component = source_components->first_child;
|
||||
prev_component = NULL;
|
||||
while (component != NULL)
|
||||
{
|
||||
FlatpakXml *next = component->next_sibling;
|
||||
|
||||
if (validate_component (component, ref, id, tags, runtime, sdk))
|
||||
{
|
||||
flatpak_xml_add (dest_components,
|
||||
flatpak_xml_unlink (component, prev_component));
|
||||
migrated = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
prev_component = component;
|
||||
}
|
||||
|
||||
component = next;
|
||||
}
|
||||
|
||||
return migrated;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
copy_icon (const char *id,
|
||||
GFile *icons_dir,
|
||||
@@ -5262,114 +5105,6 @@ extract_appstream (OstreeRepo *repo,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
FlatpakXml *
|
||||
flatpak_appstream_xml_new (void)
|
||||
{
|
||||
FlatpakXml *appstream_root = NULL;
|
||||
FlatpakXml *appstream_components;
|
||||
|
||||
appstream_root = flatpak_xml_new ("root");
|
||||
appstream_components = flatpak_xml_new ("components");
|
||||
flatpak_xml_add (appstream_root, appstream_components);
|
||||
flatpak_xml_add (appstream_components, flatpak_xml_new_text ("\n "));
|
||||
|
||||
appstream_components->attribute_names = g_new0 (char *, 3);
|
||||
appstream_components->attribute_values = g_new0 (char *, 3);
|
||||
appstream_components->attribute_names[0] = g_strdup ("version");
|
||||
appstream_components->attribute_values[0] = g_strdup ("0.8");
|
||||
appstream_components->attribute_names[1] = g_strdup ("origin");
|
||||
appstream_components->attribute_values[1] = g_strdup ("flatpak");
|
||||
|
||||
return appstream_root;
|
||||
}
|
||||
|
||||
gboolean
|
||||
flatpak_appstream_xml_root_to_data (FlatpakXml *appstream_root,
|
||||
GBytes **uncompressed,
|
||||
GBytes **compressed,
|
||||
GError **error)
|
||||
{
|
||||
g_autoptr(GString) xml = NULL;
|
||||
g_autoptr(GZlibCompressor) compressor = NULL;
|
||||
g_autoptr(GOutputStream) out2 = NULL;
|
||||
g_autoptr(GOutputStream) out = NULL;
|
||||
|
||||
flatpak_xml_add (appstream_root->first_child, flatpak_xml_new_text ("\n"));
|
||||
|
||||
xml = g_string_new ("");
|
||||
flatpak_xml_to_string (appstream_root, xml);
|
||||
|
||||
if (compressed)
|
||||
{
|
||||
compressor = g_zlib_compressor_new (G_ZLIB_COMPRESSOR_FORMAT_GZIP, -1);
|
||||
out = g_memory_output_stream_new_resizable ();
|
||||
out2 = g_converter_output_stream_new (out, G_CONVERTER (compressor));
|
||||
if (!g_output_stream_write_all (out2, xml->str, xml->len,
|
||||
NULL, NULL, error))
|
||||
return FALSE;
|
||||
if (!g_output_stream_close (out2, NULL, error))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (uncompressed)
|
||||
*uncompressed = g_string_free_to_bytes (g_steal_pointer (&xml));
|
||||
|
||||
if (compressed)
|
||||
*compressed = g_memory_output_stream_steal_as_bytes (G_MEMORY_OUTPUT_STREAM (out));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
flatpak_appstream_xml_filter (FlatpakXml *appstream,
|
||||
GRegex *allow_refs,
|
||||
GRegex *deny_refs)
|
||||
{
|
||||
FlatpakXml *components;
|
||||
FlatpakXml *component;
|
||||
FlatpakXml *prev_component, *old;
|
||||
|
||||
for (components = appstream->first_child;
|
||||
components != NULL;
|
||||
components = components->next_sibling)
|
||||
{
|
||||
if (g_strcmp0 (components->element_name, "components") != 0)
|
||||
continue;
|
||||
|
||||
|
||||
prev_component = NULL;
|
||||
component = components->first_child;
|
||||
while (component != NULL)
|
||||
{
|
||||
FlatpakXml *bundle;
|
||||
gboolean allow = FALSE;
|
||||
|
||||
if (g_strcmp0 (component->element_name, "component") == 0)
|
||||
{
|
||||
bundle = flatpak_xml_find (component, "bundle", NULL);
|
||||
if (bundle && bundle->first_child && bundle->first_child->text)
|
||||
allow = flatpak_filters_allow_ref (allow_refs, deny_refs, bundle->first_child->text);
|
||||
}
|
||||
|
||||
if (allow)
|
||||
{
|
||||
prev_component = component;
|
||||
component = component->next_sibling;
|
||||
}
|
||||
else
|
||||
{
|
||||
old = component;
|
||||
|
||||
/* prev_component is same as before */
|
||||
component = component->next_sibling;
|
||||
|
||||
flatpak_xml_unlink (old, prev_component);
|
||||
flatpak_xml_free (old);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* This is similar to ostree_repo_list_refs(), but returns only valid flatpak
|
||||
* refs, as FlatpakDecomposed. */
|
||||
static GHashTable *
|
||||
@@ -6125,274 +5860,6 @@ flatpak_list_extensions (GKeyFile *metakey,
|
||||
return g_list_sort (g_list_reverse (res), flatpak_extension_compare);
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
FlatpakXml *current;
|
||||
} XmlData;
|
||||
|
||||
FlatpakXml *
|
||||
flatpak_xml_new (const gchar *element_name)
|
||||
{
|
||||
FlatpakXml *node = g_new0 (FlatpakXml, 1);
|
||||
|
||||
node->element_name = g_strdup (element_name);
|
||||
return node;
|
||||
}
|
||||
|
||||
FlatpakXml *
|
||||
flatpak_xml_new_text (const gchar *text)
|
||||
{
|
||||
FlatpakXml *node = g_new0 (FlatpakXml, 1);
|
||||
|
||||
node->text = g_strdup (text);
|
||||
return node;
|
||||
}
|
||||
|
||||
void
|
||||
flatpak_xml_add (FlatpakXml *parent, FlatpakXml *node)
|
||||
{
|
||||
node->parent = parent;
|
||||
|
||||
if (parent->first_child == NULL)
|
||||
parent->first_child = node;
|
||||
else
|
||||
parent->last_child->next_sibling = node;
|
||||
parent->last_child = node;
|
||||
}
|
||||
|
||||
static void
|
||||
xml_start_element (GMarkupParseContext *context,
|
||||
const gchar *element_name,
|
||||
const gchar **attribute_names,
|
||||
const gchar **attribute_values,
|
||||
gpointer user_data,
|
||||
GError **error)
|
||||
{
|
||||
XmlData *data = user_data;
|
||||
FlatpakXml *node;
|
||||
|
||||
node = flatpak_xml_new (element_name);
|
||||
node->attribute_names = g_strdupv ((char **) attribute_names);
|
||||
node->attribute_values = g_strdupv ((char **) attribute_values);
|
||||
|
||||
flatpak_xml_add (data->current, node);
|
||||
data->current = node;
|
||||
}
|
||||
|
||||
static void
|
||||
xml_end_element (GMarkupParseContext *context,
|
||||
const gchar *element_name,
|
||||
gpointer user_data,
|
||||
GError **error)
|
||||
{
|
||||
XmlData *data = user_data;
|
||||
|
||||
data->current = data->current->parent;
|
||||
}
|
||||
|
||||
static void
|
||||
xml_text (GMarkupParseContext *context,
|
||||
const gchar *text,
|
||||
gsize text_len,
|
||||
gpointer user_data,
|
||||
GError **error)
|
||||
{
|
||||
XmlData *data = user_data;
|
||||
FlatpakXml *node;
|
||||
|
||||
node = flatpak_xml_new (NULL);
|
||||
node->text = g_strndup (text, text_len);
|
||||
flatpak_xml_add (data->current, node);
|
||||
}
|
||||
|
||||
static void
|
||||
xml_passthrough (GMarkupParseContext *context,
|
||||
const gchar *passthrough_text,
|
||||
gsize text_len,
|
||||
gpointer user_data,
|
||||
GError **error)
|
||||
{
|
||||
}
|
||||
|
||||
static GMarkupParser xml_parser = {
|
||||
xml_start_element,
|
||||
xml_end_element,
|
||||
xml_text,
|
||||
xml_passthrough,
|
||||
NULL
|
||||
};
|
||||
|
||||
void
|
||||
flatpak_xml_free (FlatpakXml *node)
|
||||
{
|
||||
FlatpakXml *child;
|
||||
|
||||
if (node == NULL)
|
||||
return;
|
||||
|
||||
child = node->first_child;
|
||||
while (child != NULL)
|
||||
{
|
||||
FlatpakXml *next = child->next_sibling;
|
||||
flatpak_xml_free (child);
|
||||
child = next;
|
||||
}
|
||||
|
||||
g_free (node->element_name);
|
||||
g_free (node->text);
|
||||
g_strfreev (node->attribute_names);
|
||||
g_strfreev (node->attribute_values);
|
||||
g_free (node);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
flatpak_xml_to_string (FlatpakXml *node, GString *res)
|
||||
{
|
||||
int i;
|
||||
FlatpakXml *child;
|
||||
|
||||
if (node->parent == NULL)
|
||||
g_string_append (res, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
|
||||
|
||||
if (node->element_name)
|
||||
{
|
||||
if (node->parent != NULL)
|
||||
{
|
||||
g_string_append (res, "<");
|
||||
g_string_append (res, node->element_name);
|
||||
if (node->attribute_names)
|
||||
{
|
||||
for (i = 0; node->attribute_names[i] != NULL; i++)
|
||||
{
|
||||
g_string_append_printf (res, " %s=\"%s\"",
|
||||
node->attribute_names[i],
|
||||
node->attribute_values[i]);
|
||||
}
|
||||
}
|
||||
if (node->first_child == NULL)
|
||||
g_string_append (res, "/>");
|
||||
else
|
||||
g_string_append (res, ">");
|
||||
}
|
||||
|
||||
child = node->first_child;
|
||||
while (child != NULL)
|
||||
{
|
||||
flatpak_xml_to_string (child, res);
|
||||
child = child->next_sibling;
|
||||
}
|
||||
if (node->parent != NULL)
|
||||
{
|
||||
if (node->first_child != NULL)
|
||||
g_string_append_printf (res, "</%s>", node->element_name);
|
||||
}
|
||||
}
|
||||
else if (node->text)
|
||||
{
|
||||
g_autofree char *escaped = g_markup_escape_text (node->text, -1);
|
||||
g_string_append (res, escaped);
|
||||
}
|
||||
}
|
||||
|
||||
FlatpakXml *
|
||||
flatpak_xml_unlink (FlatpakXml *node,
|
||||
FlatpakXml *prev_sibling)
|
||||
{
|
||||
FlatpakXml *parent = node->parent;
|
||||
|
||||
if (parent == NULL)
|
||||
return node;
|
||||
|
||||
if (parent->first_child == node)
|
||||
parent->first_child = node->next_sibling;
|
||||
|
||||
if (parent->last_child == node)
|
||||
parent->last_child = prev_sibling;
|
||||
|
||||
if (prev_sibling)
|
||||
prev_sibling->next_sibling = node->next_sibling;
|
||||
|
||||
node->parent = NULL;
|
||||
node->next_sibling = NULL;
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
FlatpakXml *
|
||||
flatpak_xml_find (FlatpakXml *node,
|
||||
const char *type,
|
||||
FlatpakXml **prev_child_out)
|
||||
{
|
||||
FlatpakXml *child = NULL;
|
||||
FlatpakXml *prev_child = NULL;
|
||||
|
||||
child = node->first_child;
|
||||
prev_child = NULL;
|
||||
while (child != NULL)
|
||||
{
|
||||
FlatpakXml *next = child->next_sibling;
|
||||
|
||||
if (g_strcmp0 (child->element_name, type) == 0)
|
||||
{
|
||||
if (prev_child_out)
|
||||
*prev_child_out = prev_child;
|
||||
return child;
|
||||
}
|
||||
|
||||
prev_child = child;
|
||||
child = next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
FlatpakXml *
|
||||
flatpak_xml_parse (GInputStream *in,
|
||||
gboolean compressed,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
g_autoptr(GInputStream) real_in = NULL;
|
||||
g_autoptr(FlatpakXml) xml_root = NULL;
|
||||
XmlData data = { 0 };
|
||||
char buffer[32 * 1024];
|
||||
gssize len;
|
||||
g_autoptr(GMarkupParseContext) ctx = NULL;
|
||||
|
||||
if (compressed)
|
||||
{
|
||||
g_autoptr(GZlibDecompressor) decompressor = NULL;
|
||||
decompressor = g_zlib_decompressor_new (G_ZLIB_COMPRESSOR_FORMAT_GZIP);
|
||||
real_in = g_converter_input_stream_new (in, G_CONVERTER (decompressor));
|
||||
}
|
||||
else
|
||||
{
|
||||
real_in = g_object_ref (in);
|
||||
}
|
||||
|
||||
xml_root = flatpak_xml_new ("root");
|
||||
data.current = xml_root;
|
||||
|
||||
ctx = g_markup_parse_context_new (&xml_parser,
|
||||
G_MARKUP_PREFIX_ERROR_POSITION,
|
||||
&data,
|
||||
NULL);
|
||||
|
||||
while ((len = g_input_stream_read (real_in, buffer, sizeof (buffer),
|
||||
cancellable, error)) > 0)
|
||||
{
|
||||
if (!g_markup_parse_context_parse (ctx, buffer, len, error))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (len < 0)
|
||||
return NULL;
|
||||
|
||||
return g_steal_pointer (&xml_root);
|
||||
}
|
||||
|
||||
#define OSTREE_STATIC_DELTA_META_ENTRY_FORMAT "(uayttay)"
|
||||
#define OSTREE_STATIC_DELTA_FALLBACK_FORMAT "(yaytt)"
|
||||
#define OSTREE_STATIC_DELTA_SUPERBLOCK_FORMAT "(a{sv}tayay" OSTREE_COMMIT_GVARIANT_STRING "aya" OSTREE_STATIC_DELTA_META_ENTRY_FORMAT "a" OSTREE_STATIC_DELTA_FALLBACK_FORMAT ")"
|
||||
|
||||
67
common/flatpak-xml-utils-private.h
Normal file
67
common/flatpak-xml-utils-private.h
Normal file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright © 2014 Red Hat, Inc
|
||||
*
|
||||
* This program 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "libglnx.h"
|
||||
|
||||
typedef struct FlatpakXml FlatpakXml;
|
||||
|
||||
struct FlatpakXml
|
||||
{
|
||||
gchar *element_name; /* NULL == text */
|
||||
char **attribute_names;
|
||||
char **attribute_values;
|
||||
char *text;
|
||||
FlatpakXml *parent;
|
||||
FlatpakXml *first_child;
|
||||
FlatpakXml *last_child;
|
||||
FlatpakXml *next_sibling;
|
||||
};
|
||||
|
||||
FlatpakXml *flatpak_xml_new (const gchar *element_name);
|
||||
FlatpakXml *flatpak_xml_new_text (const gchar *text);
|
||||
void flatpak_xml_add (FlatpakXml *parent,
|
||||
FlatpakXml *node);
|
||||
void flatpak_xml_free (FlatpakXml *node);
|
||||
FlatpakXml *flatpak_xml_parse (GInputStream * in,
|
||||
gboolean compressed,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
void flatpak_xml_to_string (FlatpakXml *node,
|
||||
GString *res);
|
||||
FlatpakXml *flatpak_xml_unlink (FlatpakXml *node,
|
||||
FlatpakXml *prev_sibling);
|
||||
FlatpakXml *flatpak_xml_find (FlatpakXml *node,
|
||||
const char *type,
|
||||
FlatpakXml **prev_child_out);
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (FlatpakXml, flatpak_xml_free);
|
||||
|
||||
FlatpakXml *flatpak_appstream_xml_new (void);
|
||||
gboolean flatpak_appstream_xml_migrate (FlatpakXml *source,
|
||||
FlatpakXml *dest,
|
||||
const char *ref,
|
||||
const char *id,
|
||||
GKeyFile *metadata);
|
||||
gboolean flatpak_appstream_xml_root_to_data (FlatpakXml *appstream_root,
|
||||
GBytes **uncompressed,
|
||||
GBytes **compressed,
|
||||
GError **error);
|
||||
void flatpak_appstream_xml_filter (FlatpakXml *appstream,
|
||||
GRegex *allow_refs,
|
||||
GRegex *deny_refs);
|
||||
560
common/flatpak-xml-utils.c
Normal file
560
common/flatpak-xml-utils.c
Normal file
@@ -0,0 +1,560 @@
|
||||
/* vi:set et sw=2 sts=2 cin cino=t0,f0,(0,{s,>2s,n-s,^-s,e-s:
|
||||
* Copyright © 1995-1998 Free Software Foundation, Inc.
|
||||
* Copyright © 2014-2019 Red Hat, Inc
|
||||
*
|
||||
* This program 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors:
|
||||
* Alexander Larsson <alexl@redhat.com>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "flatpak-xml-utils-private.h"
|
||||
|
||||
#include "flatpak-run-private.h"
|
||||
#include "flatpak-utils-private.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
FlatpakXml *current;
|
||||
} XmlData;
|
||||
|
||||
FlatpakXml *
|
||||
flatpak_xml_new (const gchar *element_name)
|
||||
{
|
||||
FlatpakXml *node = g_new0 (FlatpakXml, 1);
|
||||
|
||||
node->element_name = g_strdup (element_name);
|
||||
return node;
|
||||
}
|
||||
|
||||
FlatpakXml *
|
||||
flatpak_xml_new_text (const gchar *text)
|
||||
{
|
||||
FlatpakXml *node = g_new0 (FlatpakXml, 1);
|
||||
|
||||
node->text = g_strdup (text);
|
||||
return node;
|
||||
}
|
||||
|
||||
void
|
||||
flatpak_xml_add (FlatpakXml *parent, FlatpakXml *node)
|
||||
{
|
||||
node->parent = parent;
|
||||
|
||||
if (parent->first_child == NULL)
|
||||
parent->first_child = node;
|
||||
else
|
||||
parent->last_child->next_sibling = node;
|
||||
parent->last_child = node;
|
||||
}
|
||||
|
||||
static void
|
||||
xml_start_element (GMarkupParseContext *context,
|
||||
const gchar *element_name,
|
||||
const gchar **attribute_names,
|
||||
const gchar **attribute_values,
|
||||
gpointer user_data,
|
||||
GError **error)
|
||||
{
|
||||
XmlData *data = user_data;
|
||||
FlatpakXml *node;
|
||||
|
||||
node = flatpak_xml_new (element_name);
|
||||
node->attribute_names = g_strdupv ((char **) attribute_names);
|
||||
node->attribute_values = g_strdupv ((char **) attribute_values);
|
||||
|
||||
flatpak_xml_add (data->current, node);
|
||||
data->current = node;
|
||||
}
|
||||
|
||||
static void
|
||||
xml_end_element (GMarkupParseContext *context,
|
||||
const gchar *element_name,
|
||||
gpointer user_data,
|
||||
GError **error)
|
||||
{
|
||||
XmlData *data = user_data;
|
||||
|
||||
data->current = data->current->parent;
|
||||
}
|
||||
|
||||
static void
|
||||
xml_text (GMarkupParseContext *context,
|
||||
const gchar *text,
|
||||
gsize text_len,
|
||||
gpointer user_data,
|
||||
GError **error)
|
||||
{
|
||||
XmlData *data = user_data;
|
||||
FlatpakXml *node;
|
||||
|
||||
node = flatpak_xml_new (NULL);
|
||||
node->text = g_strndup (text, text_len);
|
||||
flatpak_xml_add (data->current, node);
|
||||
}
|
||||
|
||||
static void
|
||||
xml_passthrough (GMarkupParseContext *context,
|
||||
const gchar *passthrough_text,
|
||||
gsize text_len,
|
||||
gpointer user_data,
|
||||
GError **error)
|
||||
{
|
||||
}
|
||||
|
||||
static GMarkupParser xml_parser = {
|
||||
xml_start_element,
|
||||
xml_end_element,
|
||||
xml_text,
|
||||
xml_passthrough,
|
||||
NULL
|
||||
};
|
||||
|
||||
void
|
||||
flatpak_xml_free (FlatpakXml *node)
|
||||
{
|
||||
FlatpakXml *child;
|
||||
|
||||
if (node == NULL)
|
||||
return;
|
||||
|
||||
child = node->first_child;
|
||||
while (child != NULL)
|
||||
{
|
||||
FlatpakXml *next = child->next_sibling;
|
||||
flatpak_xml_free (child);
|
||||
child = next;
|
||||
}
|
||||
|
||||
g_free (node->element_name);
|
||||
g_free (node->text);
|
||||
g_strfreev (node->attribute_names);
|
||||
g_strfreev (node->attribute_values);
|
||||
g_free (node);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
flatpak_xml_to_string (FlatpakXml *node, GString *res)
|
||||
{
|
||||
int i;
|
||||
FlatpakXml *child;
|
||||
|
||||
if (node->parent == NULL)
|
||||
g_string_append (res, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
|
||||
|
||||
if (node->element_name)
|
||||
{
|
||||
if (node->parent != NULL)
|
||||
{
|
||||
g_string_append (res, "<");
|
||||
g_string_append (res, node->element_name);
|
||||
if (node->attribute_names)
|
||||
{
|
||||
for (i = 0; node->attribute_names[i] != NULL; i++)
|
||||
{
|
||||
g_string_append_printf (res, " %s=\"%s\"",
|
||||
node->attribute_names[i],
|
||||
node->attribute_values[i]);
|
||||
}
|
||||
}
|
||||
if (node->first_child == NULL)
|
||||
g_string_append (res, "/>");
|
||||
else
|
||||
g_string_append (res, ">");
|
||||
}
|
||||
|
||||
child = node->first_child;
|
||||
while (child != NULL)
|
||||
{
|
||||
flatpak_xml_to_string (child, res);
|
||||
child = child->next_sibling;
|
||||
}
|
||||
if (node->parent != NULL)
|
||||
{
|
||||
if (node->first_child != NULL)
|
||||
g_string_append_printf (res, "</%s>", node->element_name);
|
||||
}
|
||||
}
|
||||
else if (node->text)
|
||||
{
|
||||
g_autofree char *escaped = g_markup_escape_text (node->text, -1);
|
||||
g_string_append (res, escaped);
|
||||
}
|
||||
}
|
||||
|
||||
FlatpakXml *
|
||||
flatpak_xml_unlink (FlatpakXml *node,
|
||||
FlatpakXml *prev_sibling)
|
||||
{
|
||||
FlatpakXml *parent = node->parent;
|
||||
|
||||
if (parent == NULL)
|
||||
return node;
|
||||
|
||||
if (parent->first_child == node)
|
||||
parent->first_child = node->next_sibling;
|
||||
|
||||
if (parent->last_child == node)
|
||||
parent->last_child = prev_sibling;
|
||||
|
||||
if (prev_sibling)
|
||||
prev_sibling->next_sibling = node->next_sibling;
|
||||
|
||||
node->parent = NULL;
|
||||
node->next_sibling = NULL;
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
FlatpakXml *
|
||||
flatpak_xml_find (FlatpakXml *node,
|
||||
const char *type,
|
||||
FlatpakXml **prev_child_out)
|
||||
{
|
||||
FlatpakXml *child = NULL;
|
||||
FlatpakXml *prev_child = NULL;
|
||||
|
||||
child = node->first_child;
|
||||
prev_child = NULL;
|
||||
while (child != NULL)
|
||||
{
|
||||
FlatpakXml *next = child->next_sibling;
|
||||
|
||||
if (g_strcmp0 (child->element_name, type) == 0)
|
||||
{
|
||||
if (prev_child_out)
|
||||
*prev_child_out = prev_child;
|
||||
return child;
|
||||
}
|
||||
|
||||
prev_child = child;
|
||||
child = next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
FlatpakXml *
|
||||
flatpak_xml_parse (GInputStream *in,
|
||||
gboolean compressed,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
g_autoptr(GInputStream) real_in = NULL;
|
||||
g_autoptr(FlatpakXml) xml_root = NULL;
|
||||
XmlData data = { 0 };
|
||||
char buffer[32 * 1024];
|
||||
gssize len;
|
||||
g_autoptr(GMarkupParseContext) ctx = NULL;
|
||||
|
||||
if (compressed)
|
||||
{
|
||||
g_autoptr(GZlibDecompressor) decompressor = NULL;
|
||||
decompressor = g_zlib_decompressor_new (G_ZLIB_COMPRESSOR_FORMAT_GZIP);
|
||||
real_in = g_converter_input_stream_new (in, G_CONVERTER (decompressor));
|
||||
}
|
||||
else
|
||||
{
|
||||
real_in = g_object_ref (in);
|
||||
}
|
||||
|
||||
xml_root = flatpak_xml_new ("root");
|
||||
data.current = xml_root;
|
||||
|
||||
ctx = g_markup_parse_context_new (&xml_parser,
|
||||
G_MARKUP_PREFIX_ERROR_POSITION,
|
||||
&data,
|
||||
NULL);
|
||||
|
||||
while ((len = g_input_stream_read (real_in, buffer, sizeof (buffer),
|
||||
cancellable, error)) > 0)
|
||||
{
|
||||
if (!g_markup_parse_context_parse (ctx, buffer, len, error))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (len < 0)
|
||||
return NULL;
|
||||
|
||||
return g_steal_pointer (&xml_root);
|
||||
}
|
||||
|
||||
FlatpakXml *
|
||||
flatpak_appstream_xml_new (void)
|
||||
{
|
||||
FlatpakXml *appstream_root = NULL;
|
||||
FlatpakXml *appstream_components;
|
||||
|
||||
appstream_root = flatpak_xml_new ("root");
|
||||
appstream_components = flatpak_xml_new ("components");
|
||||
flatpak_xml_add (appstream_root, appstream_components);
|
||||
flatpak_xml_add (appstream_components, flatpak_xml_new_text ("\n "));
|
||||
|
||||
appstream_components->attribute_names = g_new0 (char *, 3);
|
||||
appstream_components->attribute_values = g_new0 (char *, 3);
|
||||
appstream_components->attribute_names[0] = g_strdup ("version");
|
||||
appstream_components->attribute_values[0] = g_strdup ("0.8");
|
||||
appstream_components->attribute_names[1] = g_strdup ("origin");
|
||||
appstream_components->attribute_values[1] = g_strdup ("flatpak");
|
||||
|
||||
return appstream_root;
|
||||
}
|
||||
|
||||
gboolean
|
||||
flatpak_appstream_xml_root_to_data (FlatpakXml *appstream_root,
|
||||
GBytes **uncompressed,
|
||||
GBytes **compressed,
|
||||
GError **error)
|
||||
{
|
||||
g_autoptr(GString) xml = NULL;
|
||||
g_autoptr(GZlibCompressor) compressor = NULL;
|
||||
g_autoptr(GOutputStream) out2 = NULL;
|
||||
g_autoptr(GOutputStream) out = NULL;
|
||||
|
||||
flatpak_xml_add (appstream_root->first_child, flatpak_xml_new_text ("\n"));
|
||||
|
||||
xml = g_string_new ("");
|
||||
flatpak_xml_to_string (appstream_root, xml);
|
||||
|
||||
if (compressed)
|
||||
{
|
||||
compressor = g_zlib_compressor_new (G_ZLIB_COMPRESSOR_FORMAT_GZIP, -1);
|
||||
out = g_memory_output_stream_new_resizable ();
|
||||
out2 = g_converter_output_stream_new (out, G_CONVERTER (compressor));
|
||||
if (!g_output_stream_write_all (out2, xml->str, xml->len,
|
||||
NULL, NULL, error))
|
||||
return FALSE;
|
||||
if (!g_output_stream_close (out2, NULL, error))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (uncompressed)
|
||||
*uncompressed = g_string_free_to_bytes (g_steal_pointer (&xml));
|
||||
|
||||
if (compressed)
|
||||
*compressed = g_memory_output_stream_steal_as_bytes (G_MEMORY_OUTPUT_STREAM (out));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
flatpak_appstream_xml_filter (FlatpakXml *appstream,
|
||||
GRegex *allow_refs,
|
||||
GRegex *deny_refs)
|
||||
{
|
||||
FlatpakXml *components;
|
||||
FlatpakXml *component;
|
||||
FlatpakXml *prev_component, *old;
|
||||
|
||||
for (components = appstream->first_child;
|
||||
components != NULL;
|
||||
components = components->next_sibling)
|
||||
{
|
||||
if (g_strcmp0 (components->element_name, "components") != 0)
|
||||
continue;
|
||||
|
||||
|
||||
prev_component = NULL;
|
||||
component = components->first_child;
|
||||
while (component != NULL)
|
||||
{
|
||||
FlatpakXml *bundle;
|
||||
gboolean allow = FALSE;
|
||||
|
||||
if (g_strcmp0 (component->element_name, "component") == 0)
|
||||
{
|
||||
bundle = flatpak_xml_find (component, "bundle", NULL);
|
||||
if (bundle && bundle->first_child && bundle->first_child->text)
|
||||
allow = flatpak_filters_allow_ref (allow_refs, deny_refs, bundle->first_child->text);
|
||||
}
|
||||
|
||||
if (allow)
|
||||
{
|
||||
prev_component = component;
|
||||
component = component->next_sibling;
|
||||
}
|
||||
else
|
||||
{
|
||||
old = component;
|
||||
|
||||
/* prev_component is same as before */
|
||||
component = component->next_sibling;
|
||||
|
||||
flatpak_xml_unlink (old, prev_component);
|
||||
flatpak_xml_free (old);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
validate_component (FlatpakXml *component,
|
||||
const char *ref,
|
||||
const char *id,
|
||||
char **tags,
|
||||
const char *runtime,
|
||||
const char *sdk)
|
||||
{
|
||||
FlatpakXml *bundle, *text, *prev, *id_node, *id_text_node, *metadata, *value;
|
||||
g_autofree char *id_text = NULL;
|
||||
int i;
|
||||
|
||||
if (g_strcmp0 (component->element_name, "component") != 0)
|
||||
return FALSE;
|
||||
|
||||
id_node = flatpak_xml_find (component, "id", NULL);
|
||||
if (id_node == NULL)
|
||||
return FALSE;
|
||||
|
||||
id_text_node = flatpak_xml_find (id_node, NULL, NULL);
|
||||
if (id_text_node == NULL || id_text_node->text == NULL)
|
||||
return FALSE;
|
||||
|
||||
id_text = g_strstrip (g_strdup (id_text_node->text));
|
||||
|
||||
/* Drop .desktop file suffix (unless the actual app id ends with .desktop) */
|
||||
if (g_str_has_suffix (id_text, ".desktop") &&
|
||||
!g_str_has_suffix (id, ".desktop"))
|
||||
id_text[strlen (id_text) - strlen (".desktop")] = 0;
|
||||
|
||||
if (!g_str_has_prefix (id_text, id))
|
||||
{
|
||||
g_warning ("Invalid id %s", id_text);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
while ((bundle = flatpak_xml_find (component, "bundle", &prev)) != NULL)
|
||||
flatpak_xml_free (flatpak_xml_unlink (bundle, prev));
|
||||
|
||||
bundle = flatpak_xml_new ("bundle");
|
||||
bundle->attribute_names = g_new0 (char *, 2 * 4);
|
||||
bundle->attribute_values = g_new0 (char *, 2 * 4);
|
||||
bundle->attribute_names[0] = g_strdup ("type");
|
||||
bundle->attribute_values[0] = g_strdup ("flatpak");
|
||||
|
||||
i = 1;
|
||||
if (runtime && !g_str_has_prefix (runtime, "runtime/"))
|
||||
{
|
||||
bundle->attribute_names[i] = g_strdup ("runtime");
|
||||
bundle->attribute_values[i] = g_strdup (runtime);
|
||||
i++;
|
||||
}
|
||||
|
||||
if (sdk)
|
||||
{
|
||||
bundle->attribute_names[i] = g_strdup ("sdk");
|
||||
bundle->attribute_values[i] = g_strdup (sdk);
|
||||
i++;
|
||||
}
|
||||
|
||||
text = flatpak_xml_new (NULL);
|
||||
text->text = g_strdup (ref);
|
||||
flatpak_xml_add (bundle, text);
|
||||
|
||||
flatpak_xml_add (component, flatpak_xml_new_text (" "));
|
||||
flatpak_xml_add (component, bundle);
|
||||
flatpak_xml_add (component, flatpak_xml_new_text ("\n "));
|
||||
|
||||
if (tags != NULL && tags[0] != NULL)
|
||||
{
|
||||
metadata = flatpak_xml_find (component, "metadata", NULL);
|
||||
if (metadata == NULL)
|
||||
{
|
||||
metadata = flatpak_xml_new ("metadata");
|
||||
metadata->attribute_names = g_new0 (char *, 1);
|
||||
metadata->attribute_values = g_new0 (char *, 1);
|
||||
|
||||
flatpak_xml_add (component, flatpak_xml_new_text (" "));
|
||||
flatpak_xml_add (component, metadata);
|
||||
flatpak_xml_add (component, flatpak_xml_new_text ("\n "));
|
||||
}
|
||||
|
||||
value = flatpak_xml_new ("value");
|
||||
value->attribute_names = g_new0 (char *, 2);
|
||||
value->attribute_values = g_new0 (char *, 2);
|
||||
value->attribute_names[0] = g_strdup ("key");
|
||||
value->attribute_values[0] = g_strdup ("X-Flatpak-Tags");
|
||||
flatpak_xml_add (metadata, flatpak_xml_new_text ("\n "));
|
||||
flatpak_xml_add (metadata, value);
|
||||
flatpak_xml_add (metadata, flatpak_xml_new_text ("\n "));
|
||||
|
||||
text = flatpak_xml_new (NULL);
|
||||
text->text = g_strjoinv (",", tags);
|
||||
flatpak_xml_add (value, text);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
flatpak_appstream_xml_migrate (FlatpakXml *source,
|
||||
FlatpakXml *dest,
|
||||
const char *ref,
|
||||
const char *id,
|
||||
GKeyFile *metadata)
|
||||
{
|
||||
FlatpakXml *source_components;
|
||||
FlatpakXml *dest_components;
|
||||
FlatpakXml *component;
|
||||
FlatpakXml *prev_component;
|
||||
gboolean migrated = FALSE;
|
||||
g_auto(GStrv) tags = NULL;
|
||||
g_autofree const char *runtime = NULL;
|
||||
g_autofree const char *sdk = NULL;
|
||||
const char *group;
|
||||
|
||||
if (source->first_child == NULL ||
|
||||
source->first_child->next_sibling != NULL ||
|
||||
g_strcmp0 (source->first_child->element_name, "components") != 0)
|
||||
return FALSE;
|
||||
|
||||
if (g_str_has_prefix (ref, "app/"))
|
||||
group = FLATPAK_METADATA_GROUP_APPLICATION;
|
||||
else
|
||||
group = FLATPAK_METADATA_GROUP_RUNTIME;
|
||||
|
||||
tags = g_key_file_get_string_list (metadata, group, FLATPAK_METADATA_KEY_TAGS,
|
||||
NULL, NULL);
|
||||
runtime = g_key_file_get_string (metadata, group,
|
||||
FLATPAK_METADATA_KEY_RUNTIME, NULL);
|
||||
sdk = g_key_file_get_string (metadata, group, FLATPAK_METADATA_KEY_SDK, NULL);
|
||||
|
||||
source_components = source->first_child;
|
||||
dest_components = dest->first_child;
|
||||
|
||||
component = source_components->first_child;
|
||||
prev_component = NULL;
|
||||
while (component != NULL)
|
||||
{
|
||||
FlatpakXml *next = component->next_sibling;
|
||||
|
||||
if (validate_component (component, ref, id, tags, runtime, sdk))
|
||||
{
|
||||
flatpak_xml_add (dest_components,
|
||||
flatpak_xml_unlink (component, prev_component));
|
||||
migrated = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
prev_component = component;
|
||||
}
|
||||
|
||||
component = next;
|
||||
}
|
||||
|
||||
return migrated;
|
||||
}
|
||||
@@ -197,6 +197,7 @@ sources = [
|
||||
'flatpak-utils-http.c',
|
||||
'flatpak-utils.c',
|
||||
'flatpak-uri.c',
|
||||
'flatpak-xml-utils.c',
|
||||
'flatpak-zstd-decompressor.c',
|
||||
]
|
||||
|
||||
|
||||
Reference in New Issue
Block a user