Coverage Report

Created: 2026-01-10 07:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/fwupd/libfwupd/fwupd-release.c
Line
Count
Source
1
/*
2
 * Copyright 2015 Richard Hughes <richard@hughsie.com>
3
 *
4
 * SPDX-License-Identifier: LGPL-2.1-or-later
5
 */
6
7
#include "config.h"
8
9
#include <gio/gio.h>
10
#include <string.h>
11
12
#include "fwupd-codec.h"
13
#include "fwupd-common-private.h"
14
#include "fwupd-enums-private.h"
15
#include "fwupd-error.h"
16
#include "fwupd-json-array.h"
17
#include "fwupd-release.h"
18
#include "fwupd-report.h"
19
20
/**
21
 * FwupdRelease:
22
 *
23
 * A firmware release with a specific version.
24
 *
25
 * Devices can have more than one release, and the releases are typically
26
 * ordered by their version.
27
 *
28
 * See also: [class@FwupdDevice]
29
 */
30
31
static void
32
fwupd_release_finalize(GObject *object);
33
34
typedef struct {
35
  GPtrArray *checksums;  /* (nullable) (element-type utf-8) */
36
  GPtrArray *tags;       /* (nullable) (element-type utf-8) */
37
  GPtrArray *categories; /* (nullable) (element-type utf-8) */
38
  GPtrArray *issues;     /* (nullable) (element-type utf-8) */
39
  GHashTable *metadata;  /* (nullable) (element-type utf-8 utf-8) */
40
  gchar *description;
41
  gchar *filename;
42
  gchar *protocol;
43
  gchar *homepage;
44
  gchar *details_url;
45
  gchar *source_url;
46
  gchar *sbom_url;
47
  gchar *appstream_id;
48
  gchar *id;
49
  gchar *detach_caption;
50
  gchar *detach_image;
51
  gchar *license;
52
  gchar *name;
53
  gchar *name_variant_suffix;
54
  gchar *summary;
55
  gchar *branch;
56
  GPtrArray *locations; /* (nullable) (element-type utf-8) */
57
  gchar *vendor;
58
  gchar *version;
59
  gchar *remote_id;
60
  guint64 size;
61
  guint64 created;
62
  guint32 install_duration;
63
  FwupdReleaseFlags flags;
64
  FwupdReleaseUrgency urgency;
65
  gchar *update_message;
66
  gchar *update_image;
67
  GPtrArray *reports; /* (nullable) (element-type FwupdReport) */
68
} FwupdReleasePrivate;
69
70
enum { PROP_0, PROP_REMOTE_ID, PROP_LAST };
71
72
static void
73
fwupd_release_codec_iface_init(FwupdCodecInterface *iface);
74
75
0
G_DEFINE_TYPE_EXTENDED(FwupdRelease,
76
0
           fwupd_release,
77
0
           G_TYPE_OBJECT,
78
0
           0,
79
0
           G_ADD_PRIVATE(FwupdRelease)
80
0
         G_IMPLEMENT_INTERFACE(FWUPD_TYPE_CODEC, fwupd_release_codec_iface_init));
81
0
82
0
#define GET_PRIVATE(o) (fwupd_release_get_instance_private(o))
83
84
/**
85
 * fwupd_release_get_remote_id:
86
 * @self: a #FwupdRelease
87
 *
88
 * Gets the remote ID that can be used for downloading.
89
 *
90
 * Returns: the ID, or %NULL if unset
91
 *
92
 * Since: 0.9.3
93
 **/
94
const gchar *
95
fwupd_release_get_remote_id(FwupdRelease *self)
96
0
{
97
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
98
0
  g_return_val_if_fail(FWUPD_IS_RELEASE(self), NULL);
99
0
  return priv->remote_id;
100
0
}
101
102
/**
103
 * fwupd_release_set_remote_id:
104
 * @self: a #FwupdRelease
105
 * @remote_id: the release ID, e.g. `USB:foo`
106
 *
107
 * Sets the remote ID that can be used for downloading.
108
 *
109
 * Since: 0.9.3
110
 **/
111
void
112
fwupd_release_set_remote_id(FwupdRelease *self, const gchar *remote_id)
113
0
{
114
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
115
0
  g_return_if_fail(FWUPD_IS_RELEASE(self));
116
117
  /* not changed */
118
0
  if (g_strcmp0(priv->remote_id, remote_id) == 0)
119
0
    return;
120
121
0
  g_free(priv->remote_id);
122
0
  priv->remote_id = g_strdup(remote_id);
123
0
  g_object_notify(G_OBJECT(self), "remote-id");
124
0
}
125
126
/**
127
 * fwupd_release_get_version:
128
 * @self: a #FwupdRelease
129
 *
130
 * Gets the update version.
131
 *
132
 * Returns: the update version, or %NULL if unset
133
 *
134
 * Since: 0.9.3
135
 **/
136
const gchar *
137
fwupd_release_get_version(FwupdRelease *self)
138
0
{
139
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
140
0
  g_return_val_if_fail(FWUPD_IS_RELEASE(self), NULL);
141
0
  return priv->version;
142
0
}
143
144
/**
145
 * fwupd_release_set_version:
146
 * @self: a #FwupdRelease
147
 * @version: (nullable): the update version, e.g. `1.2.4`
148
 *
149
 * Sets the update version.
150
 *
151
 * Since: 0.9.3
152
 **/
153
void
154
fwupd_release_set_version(FwupdRelease *self, const gchar *version)
155
0
{
156
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
157
0
  g_return_if_fail(FWUPD_IS_RELEASE(self));
158
159
  /* not changed */
160
0
  if (g_strcmp0(priv->version, version) == 0)
161
0
    return;
162
163
0
  g_free(priv->version);
164
0
  priv->version = g_strdup(version);
165
0
}
166
167
/**
168
 * fwupd_release_get_filename:
169
 * @self: a #FwupdRelease
170
 *
171
 * Gets the update filename.
172
 *
173
 * Returns: the update filename, or %NULL if unset
174
 *
175
 * Since: 0.9.3
176
 **/
177
const gchar *
178
fwupd_release_get_filename(FwupdRelease *self)
179
0
{
180
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
181
0
  g_return_val_if_fail(FWUPD_IS_RELEASE(self), NULL);
182
0
  return priv->filename;
183
0
}
184
185
/**
186
 * fwupd_release_set_filename:
187
 * @self: a #FwupdRelease
188
 * @filename: (nullable): the update filename on disk
189
 *
190
 * Sets the update filename.
191
 *
192
 * Since: 0.9.3
193
 **/
194
void
195
fwupd_release_set_filename(FwupdRelease *self, const gchar *filename)
196
0
{
197
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
198
0
  g_return_if_fail(FWUPD_IS_RELEASE(self));
199
200
  /* not changed */
201
0
  if (g_strcmp0(priv->filename, filename) == 0)
202
0
    return;
203
204
0
  g_free(priv->filename);
205
0
  priv->filename = g_strdup(filename);
206
0
}
207
208
/**
209
 * fwupd_release_get_update_message:
210
 * @self: a #FwupdRelease
211
 *
212
 * Gets the update message.
213
 *
214
 * Returns: the update message, or %NULL if unset
215
 *
216
 * Since: 1.2.4
217
 **/
218
const gchar *
219
fwupd_release_get_update_message(FwupdRelease *self)
220
0
{
221
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
222
0
  g_return_val_if_fail(FWUPD_IS_RELEASE(self), NULL);
223
0
  return priv->update_message;
224
0
}
225
226
/**
227
 * fwupd_release_set_update_message:
228
 * @self: a #FwupdRelease
229
 * @update_message: (nullable): the update message string
230
 *
231
 * Sets the update message.
232
 *
233
 * Since: 1.2.4
234
 **/
235
void
236
fwupd_release_set_update_message(FwupdRelease *self, const gchar *update_message)
237
0
{
238
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
239
0
  g_return_if_fail(FWUPD_IS_RELEASE(self));
240
241
  /* not changed */
242
0
  if (g_strcmp0(priv->update_message, update_message) == 0)
243
0
    return;
244
245
0
  g_free(priv->update_message);
246
0
  priv->update_message = g_strdup(update_message);
247
0
}
248
249
/**
250
 * fwupd_release_get_update_image:
251
 * @self: a #FwupdRelease
252
 *
253
 * Gets the update image.
254
 *
255
 * Returns: the update image URL, or %NULL if unset
256
 *
257
 * Since: 1.4.5
258
 **/
259
const gchar *
260
fwupd_release_get_update_image(FwupdRelease *self)
261
0
{
262
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
263
0
  g_return_val_if_fail(FWUPD_IS_RELEASE(self), NULL);
264
0
  return priv->update_image;
265
0
}
266
267
/**
268
 * fwupd_release_set_update_image:
269
 * @self: a #FwupdRelease
270
 * @update_image: (nullable): the update image URL
271
 *
272
 * Sets the update image.
273
 *
274
 * Since: 1.4.5
275
 **/
276
void
277
fwupd_release_set_update_image(FwupdRelease *self, const gchar *update_image)
278
0
{
279
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
280
0
  g_return_if_fail(FWUPD_IS_RELEASE(self));
281
282
  /* not changed */
283
0
  if (g_strcmp0(priv->update_image, update_image) == 0)
284
0
    return;
285
286
0
  g_free(priv->update_image);
287
0
  priv->update_image = g_strdup(update_image);
288
0
}
289
290
/**
291
 * fwupd_release_get_protocol:
292
 * @self: a #FwupdRelease
293
 *
294
 * Gets the update protocol.
295
 *
296
 * Returns: the update protocol, or %NULL if unset
297
 *
298
 * Since: 1.2.2
299
 **/
300
const gchar *
301
fwupd_release_get_protocol(FwupdRelease *self)
302
0
{
303
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
304
0
  g_return_val_if_fail(FWUPD_IS_RELEASE(self), NULL);
305
0
  return priv->protocol;
306
0
}
307
308
/**
309
 * fwupd_release_set_protocol:
310
 * @self: a #FwupdRelease
311
 * @protocol: (nullable): the update protocol, e.g. `org.usb.dfu`
312
 *
313
 * Sets the update protocol.
314
 *
315
 * Since: 1.2.2
316
 **/
317
void
318
fwupd_release_set_protocol(FwupdRelease *self, const gchar *protocol)
319
0
{
320
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
321
0
  g_return_if_fail(FWUPD_IS_RELEASE(self));
322
323
  /* not changed */
324
0
  if (g_strcmp0(priv->protocol, protocol) == 0)
325
0
    return;
326
327
0
  g_free(priv->protocol);
328
0
  priv->protocol = g_strdup(protocol);
329
0
}
330
331
static void
332
fwupd_release_ensure_issues(FwupdRelease *self)
333
0
{
334
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
335
0
  if (priv->issues == NULL)
336
0
    priv->issues = g_ptr_array_new_with_free_func(g_free);
337
0
}
338
339
/**
340
 * fwupd_release_get_issues:
341
 * @self: a #FwupdRelease
342
 *
343
 * Gets the list of issues fixed in this release.
344
 *
345
 * Returns: (element-type utf8) (transfer none): the issues, which may be empty
346
 *
347
 * Since: 1.3.2
348
 **/
349
GPtrArray *
350
fwupd_release_get_issues(FwupdRelease *self)
351
0
{
352
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
353
0
  g_return_val_if_fail(FWUPD_IS_RELEASE(self), NULL);
354
0
  fwupd_release_ensure_issues(self);
355
0
  return priv->issues;
356
0
}
357
358
/**
359
 * fwupd_release_add_issue:
360
 * @self: a #FwupdRelease
361
 * @issue: (not nullable): the update issue, e.g. `CVE-2019-12345`
362
 *
363
 * Adds an resolved issue to this release.
364
 *
365
 * Since: 1.3.2
366
 **/
367
void
368
fwupd_release_add_issue(FwupdRelease *self, const gchar *issue)
369
0
{
370
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
371
0
  g_return_if_fail(FWUPD_IS_RELEASE(self));
372
0
  g_return_if_fail(issue != NULL);
373
0
  fwupd_release_ensure_issues(self);
374
0
  for (guint i = 0; i < priv->issues->len; i++) {
375
0
    const gchar *issue_tmp = g_ptr_array_index(priv->issues, i);
376
0
    if (g_strcmp0(issue_tmp, issue) == 0)
377
0
      return;
378
0
  }
379
0
  g_ptr_array_add(priv->issues, g_strdup(issue));
380
0
}
381
382
static void
383
fwupd_release_ensure_categories(FwupdRelease *self)
384
0
{
385
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
386
0
  if (priv->categories == NULL)
387
0
    priv->categories = g_ptr_array_new_with_free_func(g_free);
388
0
}
389
390
/**
391
 * fwupd_release_get_categories:
392
 * @self: a #FwupdRelease
393
 *
394
 * Gets the release categories.
395
 *
396
 * Returns: (element-type utf8) (transfer none): the categories, which may be empty
397
 *
398
 * Since: 1.2.7
399
 **/
400
GPtrArray *
401
fwupd_release_get_categories(FwupdRelease *self)
402
0
{
403
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
404
0
  g_return_val_if_fail(FWUPD_IS_RELEASE(self), NULL);
405
0
  fwupd_release_ensure_categories(self);
406
0
  return priv->categories;
407
0
}
408
409
/**
410
 * fwupd_release_add_category:
411
 * @self: a #FwupdRelease
412
 * @category: (not nullable): the update category, e.g. `X-EmbeddedController`
413
 *
414
 * Adds the update category.
415
 *
416
 * Since: 1.2.7
417
 **/
418
void
419
fwupd_release_add_category(FwupdRelease *self, const gchar *category)
420
0
{
421
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
422
0
  g_return_if_fail(FWUPD_IS_RELEASE(self));
423
0
  g_return_if_fail(category != NULL);
424
0
  if (fwupd_release_has_category(self, category))
425
0
    return;
426
0
  fwupd_release_ensure_categories(self);
427
0
  g_ptr_array_add(priv->categories, g_strdup(category));
428
0
}
429
430
/**
431
 * fwupd_release_has_category:
432
 * @self: a #FwupdRelease
433
 * @category: (not nullable): the update category, e.g. `X-EmbeddedController`
434
 *
435
 * Finds out if the release has the update category.
436
 *
437
 * Returns: %TRUE if the release matches
438
 *
439
 * Since: 1.2.7
440
 **/
441
gboolean
442
fwupd_release_has_category(FwupdRelease *self, const gchar *category)
443
0
{
444
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
445
0
  g_return_val_if_fail(FWUPD_IS_RELEASE(self), FALSE);
446
0
  g_return_val_if_fail(category != NULL, FALSE);
447
0
  if (priv->categories == NULL)
448
0
    return FALSE;
449
0
  for (guint i = 0; i < priv->categories->len; i++) {
450
0
    const gchar *category_tmp = g_ptr_array_index(priv->categories, i);
451
0
    if (g_strcmp0(category_tmp, category) == 0)
452
0
      return TRUE;
453
0
  }
454
0
  return FALSE;
455
0
}
456
457
static void
458
fwupd_release_ensure_checksums(FwupdRelease *self)
459
0
{
460
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
461
0
  if (priv->checksums == NULL)
462
0
    priv->checksums = g_ptr_array_new_with_free_func(g_free);
463
0
}
464
465
/**
466
 * fwupd_release_get_checksums:
467
 * @self: a #FwupdRelease
468
 *
469
 * Gets the release container checksums.
470
 *
471
 * Returns: (element-type utf8) (transfer none): the checksums, which may be empty
472
 *
473
 * Since: 0.9.3
474
 **/
475
GPtrArray *
476
fwupd_release_get_checksums(FwupdRelease *self)
477
0
{
478
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
479
0
  g_return_val_if_fail(FWUPD_IS_RELEASE(self), NULL);
480
0
  fwupd_release_ensure_checksums(self);
481
0
  return priv->checksums;
482
0
}
483
484
/**
485
 * fwupd_release_add_checksum:
486
 * @self: a #FwupdRelease
487
 * @checksum: (not nullable): the update container checksum
488
 *
489
 * Sets the update checksum.
490
 *
491
 * Since: 0.9.3
492
 **/
493
void
494
fwupd_release_add_checksum(FwupdRelease *self, const gchar *checksum)
495
0
{
496
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
497
0
  g_return_if_fail(FWUPD_IS_RELEASE(self));
498
0
  g_return_if_fail(checksum != NULL);
499
0
  if (fwupd_release_has_checksum(self, checksum))
500
0
    return;
501
0
  fwupd_release_ensure_checksums(self);
502
0
  g_ptr_array_add(priv->checksums, g_strdup(checksum));
503
0
}
504
505
/**
506
 * fwupd_release_has_checksum:
507
 * @self: a #FwupdRelease
508
 * @checksum: (not nullable): the update checksum
509
 *
510
 * Finds out if the release has the update container checksum.
511
 *
512
 * Returns: %TRUE if the release matches
513
 *
514
 * Since: 1.2.6
515
 **/
516
gboolean
517
fwupd_release_has_checksum(FwupdRelease *self, const gchar *checksum)
518
0
{
519
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
520
0
  g_return_val_if_fail(FWUPD_IS_RELEASE(self), FALSE);
521
0
  g_return_val_if_fail(checksum != NULL, FALSE);
522
0
  if (priv->checksums == NULL)
523
0
    return FALSE;
524
0
  for (guint i = 0; i < priv->checksums->len; i++) {
525
0
    const gchar *checksum_tmp = g_ptr_array_index(priv->checksums, i);
526
0
    if (g_strcmp0(checksum_tmp, checksum) == 0)
527
0
      return TRUE;
528
0
  }
529
0
  return FALSE;
530
0
}
531
532
static void
533
fwupd_release_ensure_tags(FwupdRelease *self)
534
0
{
535
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
536
0
  if (priv->tags == NULL)
537
0
    priv->tags = g_ptr_array_new_with_free_func(g_free);
538
0
}
539
540
/**
541
 * fwupd_release_get_tags:
542
 * @self: a #FwupdRelease
543
 *
544
 * Gets the release tags.
545
 *
546
 * Returns: (element-type utf8) (transfer none): the tags, which may be empty
547
 *
548
 * Since: 1.7.3
549
 **/
550
GPtrArray *
551
fwupd_release_get_tags(FwupdRelease *self)
552
0
{
553
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
554
0
  g_return_val_if_fail(FWUPD_IS_RELEASE(self), NULL);
555
0
  fwupd_release_ensure_tags(self);
556
0
  return priv->tags;
557
0
}
558
559
/**
560
 * fwupd_release_add_tag:
561
 * @self: a #FwupdRelease
562
 * @tag: (not nullable): the update tag, e.g. `vendor-factory-2021q1`
563
 *
564
 * Adds a specific release tag.
565
 *
566
 * Since: 1.7.3
567
 **/
568
void
569
fwupd_release_add_tag(FwupdRelease *self, const gchar *tag)
570
0
{
571
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
572
0
  g_return_if_fail(FWUPD_IS_RELEASE(self));
573
0
  g_return_if_fail(tag != NULL);
574
0
  if (fwupd_release_has_tag(self, tag))
575
0
    return;
576
0
  fwupd_release_ensure_tags(self);
577
0
  g_ptr_array_add(priv->tags, g_strdup(tag));
578
0
}
579
580
/**
581
 * fwupd_release_has_tag:
582
 * @self: a #FwupdRelease
583
 * @tag: (not nullable): the update tag, e.g. `vendor-factory-2021q1`
584
 *
585
 * Finds out if the release has a specific tag.
586
 *
587
 * Returns: %TRUE if the release matches
588
 *
589
 * Since: 1.7.3
590
 **/
591
gboolean
592
fwupd_release_has_tag(FwupdRelease *self, const gchar *tag)
593
0
{
594
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
595
0
  g_return_val_if_fail(FWUPD_IS_RELEASE(self), FALSE);
596
0
  g_return_val_if_fail(tag != NULL, FALSE);
597
0
  if (priv->tags == NULL)
598
0
    return FALSE;
599
0
  for (guint i = 0; i < priv->tags->len; i++) {
600
0
    const gchar *tag_tmp = g_ptr_array_index(priv->tags, i);
601
0
    if (g_strcmp0(tag_tmp, tag) == 0)
602
0
      return TRUE;
603
0
  }
604
0
  return FALSE;
605
0
}
606
607
static void
608
fwupd_release_ensure_metadata(FwupdRelease *self)
609
0
{
610
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
611
0
  if (priv->metadata == NULL)
612
0
    priv->metadata = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
613
0
}
614
615
/**
616
 * fwupd_release_get_metadata:
617
 * @self: a #FwupdRelease
618
 *
619
 * Gets the release metadata.
620
 *
621
 * Returns: (transfer none): the metadata, which may be empty
622
 *
623
 * Since: 1.0.4
624
 **/
625
GHashTable *
626
fwupd_release_get_metadata(FwupdRelease *self)
627
0
{
628
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
629
0
  g_return_val_if_fail(FWUPD_IS_RELEASE(self), NULL);
630
0
  fwupd_release_ensure_metadata(self);
631
0
  return priv->metadata;
632
0
}
633
634
/**
635
 * fwupd_release_add_metadata_item:
636
 * @self: a #FwupdRelease
637
 * @key: (not nullable): the key
638
 * @value: (not nullable): the value
639
 *
640
 * Sets a release metadata item.
641
 *
642
 * Since: 1.0.4
643
 **/
644
void
645
fwupd_release_add_metadata_item(FwupdRelease *self, const gchar *key, const gchar *value)
646
0
{
647
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
648
0
  g_return_if_fail(FWUPD_IS_RELEASE(self));
649
0
  g_return_if_fail(key != NULL);
650
0
  g_return_if_fail(value != NULL);
651
0
  fwupd_release_ensure_metadata(self);
652
0
  g_hash_table_insert(priv->metadata, g_strdup(key), g_strdup(value));
653
0
}
654
655
/**
656
 * fwupd_release_add_metadata:
657
 * @self: a #FwupdRelease
658
 * @hash: (not nullable): the key-values
659
 *
660
 * Sets multiple release metadata items.
661
 *
662
 * Since: 1.0.4
663
 **/
664
void
665
fwupd_release_add_metadata(FwupdRelease *self, GHashTable *hash)
666
0
{
667
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
668
0
  g_autoptr(GList) keys = NULL;
669
670
0
  g_return_if_fail(FWUPD_IS_RELEASE(self));
671
0
  g_return_if_fail(hash != NULL);
672
673
  /* deep copy the whole map */
674
0
  fwupd_release_ensure_metadata(self);
675
0
  keys = g_hash_table_get_keys(hash);
676
0
  for (GList *l = keys; l != NULL; l = l->next) {
677
0
    const gchar *key = l->data;
678
0
    const gchar *value = g_hash_table_lookup(hash, key);
679
0
    g_hash_table_insert(priv->metadata, g_strdup(key), g_strdup(value));
680
0
  }
681
0
}
682
683
/**
684
 * fwupd_release_get_metadata_item:
685
 * @self: a #FwupdRelease
686
 * @key: (not nullable): the key
687
 *
688
 * Gets a release metadata item.
689
 *
690
 * Returns: the value, or %NULL if unset
691
 *
692
 * Since: 1.0.4
693
 **/
694
const gchar *
695
fwupd_release_get_metadata_item(FwupdRelease *self, const gchar *key)
696
0
{
697
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
698
0
  g_return_val_if_fail(FWUPD_IS_RELEASE(self), NULL);
699
0
  g_return_val_if_fail(key != NULL, NULL);
700
0
  if (priv->metadata == NULL)
701
0
    return NULL;
702
0
  return g_hash_table_lookup(priv->metadata, key);
703
0
}
704
705
static void
706
fwupd_release_ensure_locations(FwupdRelease *self)
707
0
{
708
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
709
0
  if (priv->locations == NULL)
710
0
    priv->locations = g_ptr_array_new_with_free_func(g_free);
711
0
}
712
713
/**
714
 * fwupd_release_get_locations:
715
 * @self: a #FwupdRelease
716
 *
717
 * Gets the update URI, i.e. where you can download the firmware from.
718
 *
719
 * Typically the first URI will be the main HTTP mirror, but all URIs may not
720
 * be valid HTTP URIs. For example, "ipns://QmSrPmba" is valid here.
721
 *
722
 * Returns: (element-type utf8) (transfer none): the URIs
723
 *
724
 * Since: 1.5.6
725
 **/
726
GPtrArray *
727
fwupd_release_get_locations(FwupdRelease *self)
728
0
{
729
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
730
0
  g_return_val_if_fail(FWUPD_IS_RELEASE(self), NULL);
731
0
  fwupd_release_ensure_locations(self);
732
0
  return priv->locations;
733
0
}
734
735
/**
736
 * fwupd_release_add_location:
737
 * @self: a #FwupdRelease
738
 * @location: (not nullable): the update URI
739
 *
740
 * Adds an update URI, i.e. where you can download the firmware from.
741
 *
742
 * Since: 1.5.6
743
 **/
744
void
745
fwupd_release_add_location(FwupdRelease *self, const gchar *location)
746
0
{
747
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
748
0
  g_return_if_fail(FWUPD_IS_RELEASE(self));
749
0
  g_return_if_fail(location != NULL);
750
0
  fwupd_release_ensure_locations(self);
751
0
  for (guint i = 0; i < priv->locations->len; i++) {
752
0
    const gchar *location_tmp = g_ptr_array_index(priv->locations, i);
753
0
    if (g_strcmp0(location_tmp, location) == 0)
754
0
      return;
755
0
  }
756
0
  g_ptr_array_add(priv->locations, g_strdup(location));
757
0
}
758
759
/**
760
 * fwupd_release_get_homepage:
761
 * @self: a #FwupdRelease
762
 *
763
 * Gets the update homepage.
764
 *
765
 * Returns: the update homepage, or %NULL if unset
766
 *
767
 * Since: 0.9.3
768
 **/
769
const gchar *
770
fwupd_release_get_homepage(FwupdRelease *self)
771
0
{
772
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
773
0
  g_return_val_if_fail(FWUPD_IS_RELEASE(self), NULL);
774
0
  return priv->homepage;
775
0
}
776
777
/**
778
 * fwupd_release_set_homepage:
779
 * @self: a #FwupdRelease
780
 * @homepage: (nullable): the URL
781
 *
782
 * Sets the update homepage URL.
783
 *
784
 * Since: 0.9.3
785
 **/
786
void
787
fwupd_release_set_homepage(FwupdRelease *self, const gchar *homepage)
788
0
{
789
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
790
0
  g_return_if_fail(FWUPD_IS_RELEASE(self));
791
792
  /* not changed */
793
0
  if (g_strcmp0(priv->homepage, homepage) == 0)
794
0
    return;
795
796
0
  g_free(priv->homepage);
797
0
  priv->homepage = g_strdup(homepage);
798
0
}
799
800
/**
801
 * fwupd_release_get_details_url:
802
 * @self: a #FwupdRelease
803
 *
804
 * Gets the URL for the online update notes.
805
 *
806
 * Returns: the update URL, or %NULL if unset
807
 *
808
 * Since: 1.2.4
809
 **/
810
const gchar *
811
fwupd_release_get_details_url(FwupdRelease *self)
812
0
{
813
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
814
0
  g_return_val_if_fail(FWUPD_IS_RELEASE(self), NULL);
815
0
  return priv->details_url;
816
0
}
817
818
/**
819
 * fwupd_release_set_details_url:
820
 * @self: a #FwupdRelease
821
 * @details_url: (nullable): the URL
822
 *
823
 * Sets the URL for the online update notes.
824
 *
825
 * Since: 1.2.4
826
 **/
827
void
828
fwupd_release_set_details_url(FwupdRelease *self, const gchar *details_url)
829
0
{
830
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
831
0
  g_return_if_fail(FWUPD_IS_RELEASE(self));
832
833
  /* not changed */
834
0
  if (g_strcmp0(priv->details_url, details_url) == 0)
835
0
    return;
836
837
0
  g_free(priv->details_url);
838
0
  priv->details_url = g_strdup(details_url);
839
0
}
840
841
/**
842
 * fwupd_release_get_source_url:
843
 * @self: a #FwupdRelease
844
 *
845
 * Gets the URL of the source code used to build this release.
846
 *
847
 * Returns: the update source_url, or %NULL if unset
848
 *
849
 * Since: 1.2.4
850
 **/
851
const gchar *
852
fwupd_release_get_source_url(FwupdRelease *self)
853
0
{
854
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
855
0
  g_return_val_if_fail(FWUPD_IS_RELEASE(self), NULL);
856
0
  return priv->source_url;
857
0
}
858
859
/**
860
 * fwupd_release_set_source_url:
861
 * @self: a #FwupdRelease
862
 * @source_url: (nullable): the URL
863
 *
864
 * Sets the URL of the source code used to build this release.
865
 *
866
 * Since: 1.2.4
867
 **/
868
void
869
fwupd_release_set_source_url(FwupdRelease *self, const gchar *source_url)
870
0
{
871
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
872
0
  g_return_if_fail(FWUPD_IS_RELEASE(self));
873
874
  /* not changed */
875
0
  if (g_strcmp0(priv->source_url, source_url) == 0)
876
0
    return;
877
878
0
  g_free(priv->source_url);
879
0
  priv->source_url = g_strdup(source_url);
880
0
}
881
882
/**
883
 * fwupd_release_set_sbom_url:
884
 * @self: a #FwupdRelease
885
 * @sbom_url: (nullable): the URL
886
 *
887
 * Sets the URL of the SBOM for this release.
888
 *
889
 * Since: 2.0.7
890
 **/
891
void
892
fwupd_release_set_sbom_url(FwupdRelease *self, const gchar *sbom_url)
893
0
{
894
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
895
0
  g_return_if_fail(FWUPD_IS_RELEASE(self));
896
897
  /* not changed */
898
0
  if (g_strcmp0(priv->sbom_url, sbom_url) == 0)
899
0
    return;
900
901
0
  g_free(priv->sbom_url);
902
0
  priv->sbom_url = g_strdup(sbom_url);
903
0
}
904
905
/**
906
 * fwupd_release_get_sbom_url:
907
 * @self: a #FwupdRelease
908
 *
909
 * Gets the URL of the SBOM for this release.
910
 *
911
 * Returns: a URL, or %NULL if unset
912
 *
913
 * Since: 2.0.7
914
 **/
915
const gchar *
916
fwupd_release_get_sbom_url(FwupdRelease *self)
917
0
{
918
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
919
0
  g_return_val_if_fail(FWUPD_IS_RELEASE(self), NULL);
920
0
  return priv->sbom_url;
921
0
}
922
923
/**
924
 * fwupd_release_get_description:
925
 * @self: a #FwupdRelease
926
 *
927
 * Gets the update description in AppStream markup format.
928
 *
929
 * Returns: the update description, or %NULL if unset
930
 *
931
 * Since: 0.9.3
932
 **/
933
const gchar *
934
fwupd_release_get_description(FwupdRelease *self)
935
0
{
936
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
937
0
  g_return_val_if_fail(FWUPD_IS_RELEASE(self), NULL);
938
0
  return priv->description;
939
0
}
940
941
/**
942
 * fwupd_release_set_description:
943
 * @self: a #FwupdRelease
944
 * @description: (nullable): the update description in AppStream markup format
945
 *
946
 * Sets the update description.
947
 *
948
 * Since: 0.9.3
949
 **/
950
void
951
fwupd_release_set_description(FwupdRelease *self, const gchar *description)
952
0
{
953
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
954
0
  g_return_if_fail(FWUPD_IS_RELEASE(self));
955
956
  /* not changed */
957
0
  if (g_strcmp0(priv->description, description) == 0)
958
0
    return;
959
960
0
  g_free(priv->description);
961
0
  priv->description = g_strdup(description);
962
0
}
963
964
/**
965
 * fwupd_release_get_appstream_id:
966
 * @self: a #FwupdRelease
967
 *
968
 * Gets the AppStream ID.
969
 *
970
 * Returns: the AppStream ID, or %NULL if unset
971
 *
972
 * Since: 0.9.3
973
 **/
974
const gchar *
975
fwupd_release_get_appstream_id(FwupdRelease *self)
976
0
{
977
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
978
0
  g_return_val_if_fail(FWUPD_IS_RELEASE(self), NULL);
979
0
  return priv->appstream_id;
980
0
}
981
982
/**
983
 * fwupd_release_set_appstream_id:
984
 * @self: a #FwupdRelease
985
 * @appstream_id: (nullable): the AppStream component ID, e.g. `org.hughski.ColorHug2.firmware`
986
 *
987
 * Sets the AppStream ID.
988
 *
989
 * Since: 0.9.3
990
 **/
991
void
992
fwupd_release_set_appstream_id(FwupdRelease *self, const gchar *appstream_id)
993
0
{
994
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
995
0
  g_return_if_fail(FWUPD_IS_RELEASE(self));
996
997
  /* not changed */
998
0
  if (g_strcmp0(priv->appstream_id, appstream_id) == 0)
999
0
    return;
1000
1001
0
  g_free(priv->appstream_id);
1002
0
  priv->appstream_id = g_strdup(appstream_id);
1003
0
}
1004
1005
/**
1006
 * fwupd_release_get_id:
1007
 * @self: a #FwupdRelease
1008
 *
1009
 * Gets the release ID, which allows identifying the specific uploaded component.
1010
 *
1011
 * Returns: the ID, or %NULL if unset
1012
 *
1013
 * Since: 1.7.2
1014
 **/
1015
const gchar *
1016
fwupd_release_get_id(FwupdRelease *self)
1017
0
{
1018
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
1019
0
  g_return_val_if_fail(FWUPD_IS_RELEASE(self), NULL);
1020
0
  return priv->id;
1021
0
}
1022
1023
/**
1024
 * fwupd_release_set_id:
1025
 * @self: a #FwupdRelease
1026
 * @id: (nullable): the AppStream component ID, e.g. `component:1234`
1027
 *
1028
 * Sets the ID, which allows identifying the specific uploaded component.
1029
 *
1030
 * Since: 1.7.2
1031
 **/
1032
void
1033
fwupd_release_set_id(FwupdRelease *self, const gchar *id)
1034
0
{
1035
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
1036
0
  g_return_if_fail(FWUPD_IS_RELEASE(self));
1037
1038
  /* not changed */
1039
0
  if (g_strcmp0(priv->id, id) == 0)
1040
0
    return;
1041
1042
0
  g_free(priv->id);
1043
0
  priv->id = g_strdup(id);
1044
0
}
1045
1046
/**
1047
 * fwupd_release_get_detach_caption:
1048
 * @self: a #FwupdRelease
1049
 *
1050
 * Gets the optional text caption used to manually detach the device.
1051
 *
1052
 * Returns: the string caption, or %NULL if unset
1053
 *
1054
 * Since: 1.3.3
1055
 **/
1056
const gchar *
1057
fwupd_release_get_detach_caption(FwupdRelease *self)
1058
0
{
1059
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
1060
0
  g_return_val_if_fail(FWUPD_IS_RELEASE(self), NULL);
1061
0
  return priv->detach_caption;
1062
0
}
1063
1064
/**
1065
 * fwupd_release_set_detach_caption:
1066
 * @self: a #FwupdRelease
1067
 * @detach_caption: (nullable): string caption
1068
 *
1069
 * Sets the optional text caption used to manually detach the device.
1070
 *
1071
 * Since: 1.3.3
1072
 **/
1073
void
1074
fwupd_release_set_detach_caption(FwupdRelease *self, const gchar *detach_caption)
1075
0
{
1076
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
1077
0
  g_return_if_fail(FWUPD_IS_RELEASE(self));
1078
1079
  /* not changed */
1080
0
  if (g_strcmp0(priv->detach_caption, detach_caption) == 0)
1081
0
    return;
1082
1083
0
  g_free(priv->detach_caption);
1084
0
  priv->detach_caption = g_strdup(detach_caption);
1085
0
}
1086
1087
/**
1088
 * fwupd_release_get_detach_image:
1089
 * @self: a #FwupdRelease
1090
 *
1091
 * Gets the optional image used to manually detach the device.
1092
 *
1093
 * Returns: the URI, or %NULL if unset
1094
 *
1095
 * Since: 1.3.3
1096
 **/
1097
const gchar *
1098
fwupd_release_get_detach_image(FwupdRelease *self)
1099
0
{
1100
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
1101
0
  g_return_val_if_fail(FWUPD_IS_RELEASE(self), NULL);
1102
0
  return priv->detach_image;
1103
0
}
1104
1105
/**
1106
 * fwupd_release_set_detach_image:
1107
 * @self: a #FwupdRelease
1108
 * @detach_image: (nullable): a fully qualified URI
1109
 *
1110
 * Sets the optional image used to manually detach the device.
1111
 *
1112
 * Since: 1.3.3
1113
 **/
1114
void
1115
fwupd_release_set_detach_image(FwupdRelease *self, const gchar *detach_image)
1116
0
{
1117
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
1118
0
  g_return_if_fail(FWUPD_IS_RELEASE(self));
1119
1120
  /* not changed */
1121
0
  if (g_strcmp0(priv->detach_image, detach_image) == 0)
1122
0
    return;
1123
1124
0
  g_free(priv->detach_image);
1125
0
  priv->detach_image = g_strdup(detach_image);
1126
0
}
1127
1128
/**
1129
 * fwupd_release_get_size:
1130
 * @self: a #FwupdRelease
1131
 *
1132
 * Gets the update size.
1133
 *
1134
 * Returns: the update size in bytes, or 0 if unset
1135
 *
1136
 * Since: 0.9.3
1137
 **/
1138
guint64
1139
fwupd_release_get_size(FwupdRelease *self)
1140
0
{
1141
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
1142
0
  g_return_val_if_fail(FWUPD_IS_RELEASE(self), 0);
1143
0
  return priv->size;
1144
0
}
1145
1146
/**
1147
 * fwupd_release_set_size:
1148
 * @self: a #FwupdRelease
1149
 * @size: the update size in bytes
1150
 *
1151
 * Sets the update size.
1152
 *
1153
 * Since: 0.9.3
1154
 **/
1155
void
1156
fwupd_release_set_size(FwupdRelease *self, guint64 size)
1157
0
{
1158
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
1159
0
  g_return_if_fail(FWUPD_IS_RELEASE(self));
1160
0
  priv->size = size;
1161
0
}
1162
1163
/**
1164
 * fwupd_release_get_created:
1165
 * @self: a #FwupdRelease
1166
 *
1167
 * Gets when the update was created.
1168
 *
1169
 * Returns: UTC timestamp in UNIX format, or 0 if unset
1170
 *
1171
 * Since: 1.4.0
1172
 **/
1173
guint64
1174
fwupd_release_get_created(FwupdRelease *self)
1175
0
{
1176
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
1177
0
  g_return_val_if_fail(FWUPD_IS_RELEASE(self), 0);
1178
0
  return priv->created;
1179
0
}
1180
1181
/**
1182
 * fwupd_release_set_created:
1183
 * @self: a #FwupdRelease
1184
 * @created: UTC timestamp in UNIX format
1185
 *
1186
 * Sets when the update was created.
1187
 *
1188
 * Since: 1.4.0
1189
 **/
1190
void
1191
fwupd_release_set_created(FwupdRelease *self, guint64 created)
1192
0
{
1193
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
1194
0
  g_return_if_fail(FWUPD_IS_RELEASE(self));
1195
0
  priv->created = created;
1196
0
}
1197
1198
/**
1199
 * fwupd_release_get_summary:
1200
 * @self: a #FwupdRelease
1201
 *
1202
 * Gets the update summary.
1203
 *
1204
 * Returns: the update summary, or %NULL if unset
1205
 *
1206
 * Since: 0.9.3
1207
 **/
1208
const gchar *
1209
fwupd_release_get_summary(FwupdRelease *self)
1210
0
{
1211
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
1212
0
  g_return_val_if_fail(FWUPD_IS_RELEASE(self), NULL);
1213
0
  return priv->summary;
1214
0
}
1215
1216
/**
1217
 * fwupd_release_set_summary:
1218
 * @self: a #FwupdRelease
1219
 * @summary: (nullable): the update one line summary
1220
 *
1221
 * Sets the update summary.
1222
 *
1223
 * Since: 0.9.3
1224
 **/
1225
void
1226
fwupd_release_set_summary(FwupdRelease *self, const gchar *summary)
1227
0
{
1228
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
1229
0
  g_return_if_fail(FWUPD_IS_RELEASE(self));
1230
1231
  /* not changed */
1232
0
  if (g_strcmp0(priv->summary, summary) == 0)
1233
0
    return;
1234
1235
0
  g_free(priv->summary);
1236
0
  priv->summary = g_strdup(summary);
1237
0
}
1238
1239
/**
1240
 * fwupd_release_get_branch:
1241
 * @self: a #FwupdRelease
1242
 *
1243
 * Gets the update branch.
1244
 *
1245
 * Returns: the alternate branch, or %NULL if unset
1246
 *
1247
 * Since: 1.5.0
1248
 **/
1249
const gchar *
1250
fwupd_release_get_branch(FwupdRelease *self)
1251
0
{
1252
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
1253
0
  g_return_val_if_fail(FWUPD_IS_RELEASE(self), NULL);
1254
0
  return priv->branch;
1255
0
}
1256
1257
/**
1258
 * fwupd_release_set_branch:
1259
 * @self: a #FwupdRelease
1260
 * @branch: (nullable): the update one line branch
1261
 *
1262
 * Sets the alternate branch.
1263
 *
1264
 * Since: 1.5.0
1265
 **/
1266
void
1267
fwupd_release_set_branch(FwupdRelease *self, const gchar *branch)
1268
0
{
1269
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
1270
0
  g_return_if_fail(FWUPD_IS_RELEASE(self));
1271
1272
  /* not changed */
1273
0
  if (g_strcmp0(priv->branch, branch) == 0)
1274
0
    return;
1275
1276
0
  g_free(priv->branch);
1277
0
  priv->branch = g_strdup(branch);
1278
0
}
1279
1280
/**
1281
 * fwupd_release_get_vendor:
1282
 * @self: a #FwupdRelease
1283
 *
1284
 * Gets the update vendor.
1285
 *
1286
 * Returns: the update vendor, or %NULL if unset
1287
 *
1288
 * Since: 0.9.3
1289
 **/
1290
const gchar *
1291
fwupd_release_get_vendor(FwupdRelease *self)
1292
0
{
1293
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
1294
0
  g_return_val_if_fail(FWUPD_IS_RELEASE(self), NULL);
1295
0
  return priv->vendor;
1296
0
}
1297
1298
/**
1299
 * fwupd_release_set_vendor:
1300
 * @self: a #FwupdRelease
1301
 * @vendor: (nullable): the vendor name, e.g. `Hughski Limited`
1302
 *
1303
 * Sets the update vendor.
1304
 *
1305
 * Since: 0.9.3
1306
 **/
1307
void
1308
fwupd_release_set_vendor(FwupdRelease *self, const gchar *vendor)
1309
0
{
1310
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
1311
0
  g_return_if_fail(FWUPD_IS_RELEASE(self));
1312
1313
  /* not changed */
1314
0
  if (g_strcmp0(priv->vendor, vendor) == 0)
1315
0
    return;
1316
1317
0
  g_free(priv->vendor);
1318
0
  priv->vendor = g_strdup(vendor);
1319
0
}
1320
1321
/**
1322
 * fwupd_release_get_license:
1323
 * @self: a #FwupdRelease
1324
 *
1325
 * Gets the update license.
1326
 *
1327
 * Returns: the update license, or %NULL if unset
1328
 *
1329
 * Since: 0.9.3
1330
 **/
1331
const gchar *
1332
fwupd_release_get_license(FwupdRelease *self)
1333
0
{
1334
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
1335
0
  g_return_val_if_fail(FWUPD_IS_RELEASE(self), NULL);
1336
0
  return priv->license;
1337
0
}
1338
1339
/**
1340
 * fwupd_release_set_license:
1341
 * @self: a #FwupdRelease
1342
 * @license: (nullable): the update license.
1343
 *
1344
 * Sets the update license.
1345
 *
1346
 * Since: 0.9.3
1347
 **/
1348
void
1349
fwupd_release_set_license(FwupdRelease *self, const gchar *license)
1350
0
{
1351
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
1352
0
  g_return_if_fail(FWUPD_IS_RELEASE(self));
1353
1354
  /* not changed */
1355
0
  if (g_strcmp0(priv->license, license) == 0)
1356
0
    return;
1357
1358
0
  g_free(priv->license);
1359
0
  priv->license = g_strdup(license);
1360
0
}
1361
1362
/**
1363
 * fwupd_release_get_name:
1364
 * @self: a #FwupdRelease
1365
 *
1366
 * Gets the update name.
1367
 *
1368
 * Returns: the update name, or %NULL if unset
1369
 *
1370
 * Since: 0.9.3
1371
 **/
1372
const gchar *
1373
fwupd_release_get_name(FwupdRelease *self)
1374
0
{
1375
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
1376
0
  g_return_val_if_fail(FWUPD_IS_RELEASE(self), NULL);
1377
0
  return priv->name;
1378
0
}
1379
1380
/**
1381
 * fwupd_release_set_name:
1382
 * @self: a #FwupdRelease
1383
 * @name: (nullable): the update name.
1384
 *
1385
 * Sets the update name.
1386
 *
1387
 * Since: 0.9.3
1388
 **/
1389
void
1390
fwupd_release_set_name(FwupdRelease *self, const gchar *name)
1391
0
{
1392
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
1393
0
  g_return_if_fail(FWUPD_IS_RELEASE(self));
1394
1395
  /* not changed */
1396
0
  if (g_strcmp0(priv->name, name) == 0)
1397
0
    return;
1398
1399
0
  g_free(priv->name);
1400
0
  priv->name = g_strdup(name);
1401
0
}
1402
1403
/**
1404
 * fwupd_release_get_name_variant_suffix:
1405
 * @self: a #FwupdRelease
1406
 *
1407
 * Gets the update variant suffix.
1408
 *
1409
 * Returns: the update variant, or %NULL if unset
1410
 *
1411
 * Since: 1.3.2
1412
 **/
1413
const gchar *
1414
fwupd_release_get_name_variant_suffix(FwupdRelease *self)
1415
0
{
1416
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
1417
0
  g_return_val_if_fail(FWUPD_IS_RELEASE(self), NULL);
1418
0
  return priv->name_variant_suffix;
1419
0
}
1420
1421
/**
1422
 * fwupd_release_set_name_variant_suffix:
1423
 * @self: a #FwupdRelease
1424
 * @name_variant_suffix: (nullable): the description
1425
 *
1426
 * Sets the update variant suffix.
1427
 *
1428
 * Since: 1.3.2
1429
 **/
1430
void
1431
fwupd_release_set_name_variant_suffix(FwupdRelease *self, const gchar *name_variant_suffix)
1432
0
{
1433
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
1434
0
  g_return_if_fail(FWUPD_IS_RELEASE(self));
1435
1436
  /* not changed */
1437
0
  if (g_strcmp0(priv->name_variant_suffix, name_variant_suffix) == 0)
1438
0
    return;
1439
1440
0
  g_free(priv->name_variant_suffix);
1441
0
  priv->name_variant_suffix = g_strdup(name_variant_suffix);
1442
0
}
1443
1444
/**
1445
 * fwupd_release_get_flags:
1446
 * @self: a #FwupdRelease
1447
 *
1448
 * Gets the release flags.
1449
 *
1450
 * Returns: release flags, or 0 if unset
1451
 *
1452
 * Since: 1.2.6
1453
 **/
1454
FwupdReleaseFlags
1455
fwupd_release_get_flags(FwupdRelease *self)
1456
0
{
1457
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
1458
0
  g_return_val_if_fail(FWUPD_IS_RELEASE(self), 0);
1459
0
  return priv->flags;
1460
0
}
1461
1462
/**
1463
 * fwupd_release_set_flags:
1464
 * @self: a #FwupdRelease
1465
 * @flags: release flags, e.g. %FWUPD_RELEASE_FLAG_TRUSTED_PAYLOAD
1466
 *
1467
 * Sets the release flags.
1468
 *
1469
 * Since: 1.2.6
1470
 **/
1471
void
1472
fwupd_release_set_flags(FwupdRelease *self, FwupdReleaseFlags flags)
1473
0
{
1474
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
1475
0
  g_return_if_fail(FWUPD_IS_RELEASE(self));
1476
0
  priv->flags = flags;
1477
0
}
1478
1479
/**
1480
 * fwupd_release_add_flag:
1481
 * @self: a #FwupdRelease
1482
 * @flag: the #FwupdReleaseFlags
1483
 *
1484
 * Adds a specific release flag to the release.
1485
 *
1486
 * Since: 1.2.6
1487
 **/
1488
void
1489
fwupd_release_add_flag(FwupdRelease *self, FwupdReleaseFlags flag)
1490
0
{
1491
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
1492
0
  g_return_if_fail(FWUPD_IS_RELEASE(self));
1493
0
  priv->flags |= flag;
1494
0
}
1495
1496
/**
1497
 * fwupd_release_remove_flag:
1498
 * @self: a #FwupdRelease
1499
 * @flag: the #FwupdReleaseFlags
1500
 *
1501
 * Removes a specific release flag from the release.
1502
 *
1503
 * Since: 1.2.6
1504
 **/
1505
void
1506
fwupd_release_remove_flag(FwupdRelease *self, FwupdReleaseFlags flag)
1507
0
{
1508
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
1509
0
  g_return_if_fail(FWUPD_IS_RELEASE(self));
1510
0
  priv->flags &= ~flag;
1511
0
}
1512
1513
/**
1514
 * fwupd_release_has_flag:
1515
 * @self: a #FwupdRelease
1516
 * @flag: the #FwupdReleaseFlags
1517
 *
1518
 * Finds if the release has a specific release flag.
1519
 *
1520
 * Returns: %TRUE if the flag is set
1521
 *
1522
 * Since: 1.2.6
1523
 **/
1524
gboolean
1525
fwupd_release_has_flag(FwupdRelease *self, FwupdReleaseFlags flag)
1526
0
{
1527
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
1528
0
  g_return_val_if_fail(FWUPD_IS_RELEASE(self), FALSE);
1529
0
  return (priv->flags & flag) > 0;
1530
0
}
1531
1532
/**
1533
 * fwupd_release_get_urgency:
1534
 * @self: a #FwupdRelease
1535
 *
1536
 * Gets the release urgency.
1537
 *
1538
 * Returns: the release urgency, or 0 if unset
1539
 *
1540
 * Since: 1.4.0
1541
 **/
1542
FwupdReleaseUrgency
1543
fwupd_release_get_urgency(FwupdRelease *self)
1544
0
{
1545
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
1546
0
  g_return_val_if_fail(FWUPD_IS_RELEASE(self), 0);
1547
0
  return priv->urgency;
1548
0
}
1549
1550
/**
1551
 * fwupd_release_set_urgency:
1552
 * @self: a #FwupdRelease
1553
 * @urgency: the release urgency, e.g. %FWUPD_RELEASE_FLAG_TRUSTED_PAYLOAD
1554
 *
1555
 * Sets the release urgency.
1556
 *
1557
 * Since: 1.4.0
1558
 **/
1559
void
1560
fwupd_release_set_urgency(FwupdRelease *self, FwupdReleaseUrgency urgency)
1561
0
{
1562
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
1563
0
  g_return_if_fail(FWUPD_IS_RELEASE(self));
1564
0
  priv->urgency = urgency;
1565
0
}
1566
1567
/**
1568
 * fwupd_release_get_install_duration:
1569
 * @self: a #FwupdRelease
1570
 *
1571
 * Gets the time estimate for firmware installation (in seconds)
1572
 *
1573
 * Returns: the estimated time to flash this release (or 0 if unset)
1574
 *
1575
 * Since: 1.2.1
1576
 **/
1577
guint32
1578
fwupd_release_get_install_duration(FwupdRelease *self)
1579
0
{
1580
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
1581
0
  g_return_val_if_fail(FWUPD_IS_RELEASE(self), 0);
1582
0
  return priv->install_duration;
1583
0
}
1584
1585
static void
1586
fwupd_release_ensure_reports(FwupdRelease *self)
1587
0
{
1588
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
1589
0
  if (priv->reports == NULL)
1590
0
    priv->reports = g_ptr_array_new_with_free_func((GDestroyNotify)g_object_unref);
1591
0
}
1592
1593
/**
1594
 * fwupd_release_get_reports:
1595
 * @self: a #FwupdRelease
1596
 *
1597
 * Gets all the reports for this release.
1598
 *
1599
 * Returns: (transfer none) (element-type FwupdReport): array of reports
1600
 *
1601
 * Since: 1.8.8
1602
 **/
1603
GPtrArray *
1604
fwupd_release_get_reports(FwupdRelease *self)
1605
0
{
1606
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
1607
0
  g_return_val_if_fail(FWUPD_IS_RELEASE(self), NULL);
1608
0
  fwupd_release_ensure_reports(self);
1609
0
  return priv->reports;
1610
0
}
1611
1612
/**
1613
 * fwupd_release_add_report:
1614
 * @self: a #FwupdRelease
1615
 * @report: (not nullable): a #FwupdReport
1616
 *
1617
 * Adds a report for this release.
1618
 *
1619
 * Since: 1.8.8
1620
 **/
1621
void
1622
fwupd_release_add_report(FwupdRelease *self, FwupdReport *report)
1623
0
{
1624
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
1625
0
  g_return_if_fail(FWUPD_IS_RELEASE(self));
1626
0
  g_return_if_fail(FWUPD_IS_REPORT(report));
1627
0
  fwupd_release_ensure_reports(self);
1628
0
  g_ptr_array_add(priv->reports, g_object_ref(report));
1629
0
}
1630
1631
/**
1632
 * fwupd_release_set_install_duration:
1633
 * @self: a #FwupdRelease
1634
 * @duration: amount of time in seconds
1635
 *
1636
 * Sets the time estimate for firmware installation (in seconds)
1637
 *
1638
 * Since: 1.2.1
1639
 **/
1640
void
1641
fwupd_release_set_install_duration(FwupdRelease *self, guint32 duration)
1642
0
{
1643
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
1644
0
  g_return_if_fail(FWUPD_IS_RELEASE(self));
1645
0
  priv->install_duration = duration;
1646
0
}
1647
1648
static void
1649
fwupd_release_add_variant(FwupdCodec *codec, GVariantBuilder *builder, FwupdCodecFlags flags)
1650
0
{
1651
0
  FwupdRelease *self = FWUPD_RELEASE(codec);
1652
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
1653
1654
0
  if (priv->remote_id != NULL) {
1655
0
    g_variant_builder_add(builder,
1656
0
              "{sv}",
1657
0
              FWUPD_RESULT_KEY_REMOTE_ID,
1658
0
              g_variant_new_string(priv->remote_id));
1659
0
  }
1660
0
  if (priv->appstream_id != NULL) {
1661
0
    g_variant_builder_add(builder,
1662
0
              "{sv}",
1663
0
              FWUPD_RESULT_KEY_APPSTREAM_ID,
1664
0
              g_variant_new_string(priv->appstream_id));
1665
0
  }
1666
0
  if (priv->id != NULL) {
1667
0
    g_variant_builder_add(builder,
1668
0
              "{sv}",
1669
0
              FWUPD_RESULT_KEY_RELEASE_ID,
1670
0
              g_variant_new_string(priv->id));
1671
0
  }
1672
0
  if (priv->detach_caption != NULL) {
1673
0
    g_variant_builder_add(builder,
1674
0
              "{sv}",
1675
0
              FWUPD_RESULT_KEY_DETACH_CAPTION,
1676
0
              g_variant_new_string(priv->detach_caption));
1677
0
  }
1678
0
  if (priv->detach_image != NULL) {
1679
0
    g_variant_builder_add(builder,
1680
0
              "{sv}",
1681
0
              FWUPD_RESULT_KEY_DETACH_IMAGE,
1682
0
              g_variant_new_string(priv->detach_image));
1683
0
  }
1684
0
  if (priv->update_message != NULL) {
1685
0
    g_variant_builder_add(builder,
1686
0
              "{sv}",
1687
0
              FWUPD_RESULT_KEY_UPDATE_MESSAGE,
1688
0
              g_variant_new_string(priv->update_message));
1689
0
  }
1690
0
  if (priv->update_image != NULL) {
1691
0
    g_variant_builder_add(builder,
1692
0
              "{sv}",
1693
0
              FWUPD_RESULT_KEY_UPDATE_IMAGE,
1694
0
              g_variant_new_string(priv->update_image));
1695
0
  }
1696
0
  if (priv->filename != NULL) {
1697
0
    g_variant_builder_add(builder,
1698
0
              "{sv}",
1699
0
              FWUPD_RESULT_KEY_FILENAME,
1700
0
              g_variant_new_string(priv->filename));
1701
0
  }
1702
0
  if (priv->protocol != NULL) {
1703
0
    g_variant_builder_add(builder,
1704
0
              "{sv}",
1705
0
              FWUPD_RESULT_KEY_PROTOCOL,
1706
0
              g_variant_new_string(priv->protocol));
1707
0
  }
1708
0
  if (priv->license != NULL) {
1709
0
    g_variant_builder_add(builder,
1710
0
              "{sv}",
1711
0
              FWUPD_RESULT_KEY_LICENSE,
1712
0
              g_variant_new_string(priv->license));
1713
0
  }
1714
0
  if (priv->name != NULL) {
1715
0
    g_variant_builder_add(builder,
1716
0
              "{sv}",
1717
0
              FWUPD_RESULT_KEY_NAME,
1718
0
              g_variant_new_string(priv->name));
1719
0
  }
1720
0
  if (priv->name_variant_suffix != NULL) {
1721
0
    g_variant_builder_add(builder,
1722
0
              "{sv}",
1723
0
              FWUPD_RESULT_KEY_NAME_VARIANT_SUFFIX,
1724
0
              g_variant_new_string(priv->name_variant_suffix));
1725
0
  }
1726
0
  if (priv->size != 0) {
1727
0
    g_variant_builder_add(builder,
1728
0
              "{sv}",
1729
0
              FWUPD_RESULT_KEY_SIZE,
1730
0
              g_variant_new_uint64(priv->size));
1731
0
  }
1732
0
  if (priv->created != 0) {
1733
0
    g_variant_builder_add(builder,
1734
0
              "{sv}",
1735
0
              FWUPD_RESULT_KEY_CREATED,
1736
0
              g_variant_new_uint64(priv->created));
1737
0
  }
1738
0
  if (priv->summary != NULL) {
1739
0
    g_variant_builder_add(builder,
1740
0
              "{sv}",
1741
0
              FWUPD_RESULT_KEY_SUMMARY,
1742
0
              g_variant_new_string(priv->summary));
1743
0
  }
1744
0
  if (priv->branch != NULL) {
1745
0
    g_variant_builder_add(builder,
1746
0
              "{sv}",
1747
0
              FWUPD_RESULT_KEY_BRANCH,
1748
0
              g_variant_new_string(priv->branch));
1749
0
  }
1750
0
  if (priv->description != NULL) {
1751
0
    g_variant_builder_add(builder,
1752
0
              "{sv}",
1753
0
              FWUPD_RESULT_KEY_DESCRIPTION,
1754
0
              g_variant_new_string(priv->description));
1755
0
  }
1756
0
  if (priv->categories != NULL && priv->categories->len > 0) {
1757
0
    g_autofree const gchar **strv = g_new0(const gchar *, priv->categories->len + 1);
1758
0
    for (guint i = 0; i < priv->categories->len; i++)
1759
0
      strv[i] = (const gchar *)g_ptr_array_index(priv->categories, i);
1760
0
    g_variant_builder_add(builder,
1761
0
              "{sv}",
1762
0
              FWUPD_RESULT_KEY_CATEGORIES,
1763
0
              g_variant_new_strv(strv, -1));
1764
0
  }
1765
0
  if (priv->issues != NULL && priv->issues->len > 0) {
1766
0
    g_autofree const gchar **strv = g_new0(const gchar *, priv->issues->len + 1);
1767
0
    for (guint i = 0; i < priv->issues->len; i++)
1768
0
      strv[i] = (const gchar *)g_ptr_array_index(priv->issues, i);
1769
0
    g_variant_builder_add(builder,
1770
0
              "{sv}",
1771
0
              FWUPD_RESULT_KEY_ISSUES,
1772
0
              g_variant_new_strv(strv, -1));
1773
0
  }
1774
0
  if (priv->checksums != NULL && priv->checksums->len > 0) {
1775
0
    g_autoptr(GString) str = g_string_new("");
1776
0
    for (guint i = 0; i < priv->checksums->len; i++) {
1777
0
      const gchar *checksum = g_ptr_array_index(priv->checksums, i);
1778
0
      g_string_append_printf(str, "%s,", checksum);
1779
0
    }
1780
0
    if (str->len > 0)
1781
0
      g_string_truncate(str, str->len - 1);
1782
0
    g_variant_builder_add(builder,
1783
0
              "{sv}",
1784
0
              FWUPD_RESULT_KEY_CHECKSUM,
1785
0
              g_variant_new_string(str->str));
1786
0
  }
1787
0
  if (priv->locations != NULL && priv->locations->len > 0) {
1788
0
    g_variant_builder_add(
1789
0
        builder,
1790
0
        "{sv}",
1791
0
        FWUPD_RESULT_KEY_LOCATIONS,
1792
0
        g_variant_new_strv((const gchar *const *)priv->locations->pdata,
1793
0
               priv->locations->len));
1794
0
  }
1795
0
  if (priv->tags != NULL && priv->tags->len > 0) {
1796
0
    g_variant_builder_add(
1797
0
        builder,
1798
0
        "{sv}",
1799
0
        FWUPD_RESULT_KEY_TAGS,
1800
0
        g_variant_new_strv((const gchar *const *)priv->tags->pdata, priv->tags->len));
1801
0
  }
1802
0
  if (priv->homepage != NULL) {
1803
0
    g_variant_builder_add(builder,
1804
0
              "{sv}",
1805
0
              FWUPD_RESULT_KEY_HOMEPAGE,
1806
0
              g_variant_new_string(priv->homepage));
1807
0
  }
1808
0
  if (priv->details_url != NULL) {
1809
0
    g_variant_builder_add(builder,
1810
0
              "{sv}",
1811
0
              FWUPD_RESULT_KEY_DETAILS_URL,
1812
0
              g_variant_new_string(priv->details_url));
1813
0
  }
1814
0
  if (priv->source_url != NULL) {
1815
0
    g_variant_builder_add(builder,
1816
0
              "{sv}",
1817
0
              FWUPD_RESULT_KEY_SOURCE_URL,
1818
0
              g_variant_new_string(priv->source_url));
1819
0
  }
1820
0
  if (priv->sbom_url != NULL) {
1821
0
    g_variant_builder_add(builder,
1822
0
              "{sv}",
1823
0
              FWUPD_RESULT_KEY_SBOM_URL,
1824
0
              g_variant_new_string(priv->sbom_url));
1825
0
  }
1826
0
  if (priv->version != NULL) {
1827
0
    g_variant_builder_add(builder,
1828
0
              "{sv}",
1829
0
              FWUPD_RESULT_KEY_VERSION,
1830
0
              g_variant_new_string(priv->version));
1831
0
  }
1832
0
  if (priv->vendor != NULL) {
1833
0
    g_variant_builder_add(builder,
1834
0
              "{sv}",
1835
0
              FWUPD_RESULT_KEY_VENDOR,
1836
0
              g_variant_new_string(priv->vendor));
1837
0
  }
1838
0
  if (priv->flags != 0) {
1839
0
    g_variant_builder_add(builder,
1840
0
              "{sv}",
1841
0
              FWUPD_RESULT_KEY_TRUST_FLAGS,
1842
0
              g_variant_new_uint64(priv->flags));
1843
0
  }
1844
0
  if (priv->urgency != 0) {
1845
0
    g_variant_builder_add(builder,
1846
0
              "{sv}",
1847
0
              FWUPD_RESULT_KEY_URGENCY,
1848
0
              g_variant_new_uint32(priv->urgency));
1849
0
  }
1850
0
  if (priv->metadata != NULL && g_hash_table_size(priv->metadata) > 0) {
1851
0
    g_variant_builder_add(builder,
1852
0
              "{sv}",
1853
0
              FWUPD_RESULT_KEY_METADATA,
1854
0
              fwupd_hash_kv_to_variant(priv->metadata));
1855
0
  }
1856
0
  if (priv->install_duration > 0) {
1857
0
    g_variant_builder_add(builder,
1858
0
              "{sv}",
1859
0
              FWUPD_RESULT_KEY_INSTALL_DURATION,
1860
0
              g_variant_new_uint32(priv->install_duration));
1861
0
  }
1862
0
  if (priv->reports != NULL && priv->reports->len > 0) {
1863
0
    g_autofree GVariant **children = NULL;
1864
0
    children = g_new0(GVariant *, priv->reports->len);
1865
0
    for (guint i = 0; i < priv->reports->len; i++) {
1866
0
      FwupdReport *report = g_ptr_array_index(priv->reports, i);
1867
0
      children[i] = fwupd_codec_to_variant(FWUPD_CODEC(report), flags);
1868
0
    }
1869
0
    g_variant_builder_add(
1870
0
        builder,
1871
0
        "{sv}",
1872
0
        FWUPD_RESULT_KEY_REPORTS,
1873
0
        g_variant_new_array(G_VARIANT_TYPE("a{sv}"), children, priv->reports->len));
1874
0
  }
1875
0
}
1876
1877
static void
1878
fwupd_release_from_key_value(FwupdRelease *self, const gchar *key, GVariant *value)
1879
0
{
1880
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
1881
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_REMOTE_ID) == 0) {
1882
0
    fwupd_release_set_remote_id(self, g_variant_get_string(value, NULL));
1883
0
    return;
1884
0
  }
1885
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_APPSTREAM_ID) == 0) {
1886
0
    fwupd_release_set_appstream_id(self, g_variant_get_string(value, NULL));
1887
0
    return;
1888
0
  }
1889
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_RELEASE_ID) == 0) {
1890
0
    fwupd_release_set_id(self, g_variant_get_string(value, NULL));
1891
0
    return;
1892
0
  }
1893
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_DETACH_CAPTION) == 0) {
1894
0
    fwupd_release_set_detach_caption(self, g_variant_get_string(value, NULL));
1895
0
    return;
1896
0
  }
1897
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_DETACH_IMAGE) == 0) {
1898
0
    fwupd_release_set_detach_image(self, g_variant_get_string(value, NULL));
1899
0
    return;
1900
0
  }
1901
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_FILENAME) == 0) {
1902
0
    fwupd_release_set_filename(self, g_variant_get_string(value, NULL));
1903
0
    return;
1904
0
  }
1905
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_PROTOCOL) == 0) {
1906
0
    fwupd_release_set_protocol(self, g_variant_get_string(value, NULL));
1907
0
    return;
1908
0
  }
1909
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_LICENSE) == 0) {
1910
0
    fwupd_release_set_license(self, g_variant_get_string(value, NULL));
1911
0
    return;
1912
0
  }
1913
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_NAME) == 0) {
1914
0
    fwupd_release_set_name(self, g_variant_get_string(value, NULL));
1915
0
    return;
1916
0
  }
1917
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_NAME_VARIANT_SUFFIX) == 0) {
1918
0
    fwupd_release_set_name_variant_suffix(self, g_variant_get_string(value, NULL));
1919
0
    return;
1920
0
  }
1921
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_SIZE) == 0) {
1922
0
    fwupd_release_set_size(self, g_variant_get_uint64(value));
1923
0
    return;
1924
0
  }
1925
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_CREATED) == 0) {
1926
0
    fwupd_release_set_created(self, g_variant_get_uint64(value));
1927
0
    return;
1928
0
  }
1929
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_SUMMARY) == 0) {
1930
0
    fwupd_release_set_summary(self, g_variant_get_string(value, NULL));
1931
0
    return;
1932
0
  }
1933
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_BRANCH) == 0) {
1934
0
    fwupd_release_set_branch(self, g_variant_get_string(value, NULL));
1935
0
    return;
1936
0
  }
1937
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_DESCRIPTION) == 0) {
1938
0
    fwupd_release_set_description(self, g_variant_get_string(value, NULL));
1939
0
    return;
1940
0
  }
1941
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_CATEGORIES) == 0) {
1942
0
    g_autofree const gchar **strv = g_variant_get_strv(value, NULL);
1943
0
    for (guint i = 0; strv[i] != NULL; i++)
1944
0
      fwupd_release_add_category(self, strv[i]);
1945
0
    return;
1946
0
  }
1947
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_ISSUES) == 0) {
1948
0
    g_autofree const gchar **strv = g_variant_get_strv(value, NULL);
1949
0
    for (guint i = 0; strv[i] != NULL; i++)
1950
0
      fwupd_release_add_issue(self, strv[i]);
1951
0
    return;
1952
0
  }
1953
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_CHECKSUM) == 0) {
1954
0
    const gchar *checksums = g_variant_get_string(value, NULL);
1955
0
    g_auto(GStrv) split = g_strsplit(checksums, ",", -1);
1956
0
    for (guint i = 0; split[i] != NULL; i++)
1957
0
      fwupd_release_add_checksum(self, split[i]);
1958
0
    return;
1959
0
  }
1960
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_LOCATIONS) == 0) {
1961
0
    g_autofree const gchar **strv = g_variant_get_strv(value, NULL);
1962
0
    for (guint i = 0; strv[i] != NULL; i++)
1963
0
      fwupd_release_add_location(self, strv[i]);
1964
0
    return;
1965
0
  }
1966
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_TAGS) == 0) {
1967
0
    g_autofree const gchar **strv = g_variant_get_strv(value, NULL);
1968
0
    for (guint i = 0; strv[i] != NULL; i++)
1969
0
      fwupd_release_add_tag(self, strv[i]);
1970
0
    return;
1971
0
  }
1972
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_URI) == 0) {
1973
0
    fwupd_release_add_location(self, g_variant_get_string(value, NULL));
1974
0
    return;
1975
0
  }
1976
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_HOMEPAGE) == 0) {
1977
0
    fwupd_release_set_homepage(self, g_variant_get_string(value, NULL));
1978
0
    return;
1979
0
  }
1980
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_DETAILS_URL) == 0) {
1981
0
    fwupd_release_set_details_url(self, g_variant_get_string(value, NULL));
1982
0
    return;
1983
0
  }
1984
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_SOURCE_URL) == 0) {
1985
0
    fwupd_release_set_source_url(self, g_variant_get_string(value, NULL));
1986
0
    return;
1987
0
  }
1988
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_SBOM_URL) == 0) {
1989
0
    fwupd_release_set_sbom_url(self, g_variant_get_string(value, NULL));
1990
0
    return;
1991
0
  }
1992
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_VERSION) == 0) {
1993
0
    fwupd_release_set_version(self, g_variant_get_string(value, NULL));
1994
0
    return;
1995
0
  }
1996
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_VENDOR) == 0) {
1997
0
    fwupd_release_set_vendor(self, g_variant_get_string(value, NULL));
1998
0
    return;
1999
0
  }
2000
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_TRUST_FLAGS) == 0) {
2001
0
    fwupd_release_set_flags(self, g_variant_get_uint64(value));
2002
0
    return;
2003
0
  }
2004
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_URGENCY) == 0) {
2005
0
    fwupd_release_set_urgency(self, g_variant_get_uint32(value));
2006
0
    return;
2007
0
  }
2008
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_INSTALL_DURATION) == 0) {
2009
0
    fwupd_release_set_install_duration(self, g_variant_get_uint32(value));
2010
0
    return;
2011
0
  }
2012
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_UPDATE_MESSAGE) == 0) {
2013
0
    fwupd_release_set_update_message(self, g_variant_get_string(value, NULL));
2014
0
    return;
2015
0
  }
2016
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_UPDATE_IMAGE) == 0) {
2017
0
    fwupd_release_set_update_image(self, g_variant_get_string(value, NULL));
2018
0
    return;
2019
0
  }
2020
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_METADATA) == 0) {
2021
0
    if (priv->metadata != NULL)
2022
0
      g_hash_table_unref(priv->metadata);
2023
0
    priv->metadata = fwupd_variant_to_hash_kv(value);
2024
0
    return;
2025
0
  }
2026
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_REPORTS) == 0) {
2027
0
    GVariantIter iter;
2028
0
    GVariant *child;
2029
0
    g_variant_iter_init(&iter, value);
2030
0
    while ((child = g_variant_iter_next_value(&iter))) {
2031
0
      g_autoptr(FwupdReport) report = fwupd_report_new();
2032
0
      if (fwupd_codec_from_variant(FWUPD_CODEC(report), child, NULL))
2033
0
        fwupd_release_add_report(self, report);
2034
0
      g_variant_unref(child);
2035
0
    }
2036
0
    return;
2037
0
  }
2038
0
}
2039
2040
static void
2041
fwupd_release_string_append_flags(GString *str,
2042
          guint idt,
2043
          const gchar *key,
2044
          FwupdReleaseFlags release_flags)
2045
0
{
2046
0
  g_autoptr(GString) tmp = g_string_new("");
2047
0
  for (guint i = 0; i < 64; i++) {
2048
0
    if ((release_flags & ((guint64)1 << i)) == 0)
2049
0
      continue;
2050
0
    g_string_append_printf(tmp, "%s|", fwupd_release_flag_to_string((guint64)1 << i));
2051
0
  }
2052
0
  if (tmp->len == 0) {
2053
0
    g_string_append(tmp, fwupd_release_flag_to_string(0));
2054
0
  } else {
2055
0
    g_string_truncate(tmp, tmp->len - 1);
2056
0
  }
2057
0
  fwupd_codec_string_append(str, idt, key, tmp->str);
2058
0
}
2059
2060
static void
2061
fwupd_release_add_json(FwupdCodec *codec, FwupdJsonObject *json_obj, FwupdCodecFlags flags)
2062
0
{
2063
0
  FwupdRelease *self = FWUPD_RELEASE(codec);
2064
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
2065
2066
0
  if (priv->appstream_id != NULL) {
2067
0
    fwupd_json_object_add_string(json_obj,
2068
0
               FWUPD_RESULT_KEY_APPSTREAM_ID,
2069
0
               priv->appstream_id);
2070
0
  }
2071
0
  if (priv->id != NULL)
2072
0
    fwupd_json_object_add_string(json_obj, FWUPD_RESULT_KEY_RELEASE_ID, priv->id);
2073
0
  if (priv->remote_id != NULL)
2074
0
    fwupd_json_object_add_string(json_obj, FWUPD_RESULT_KEY_REMOTE_ID, priv->remote_id);
2075
0
  if (priv->name != NULL)
2076
0
    fwupd_json_object_add_string(json_obj, FWUPD_RESULT_KEY_NAME, priv->name);
2077
0
  if (priv->name_variant_suffix != NULL) {
2078
0
    fwupd_json_object_add_string(json_obj,
2079
0
               FWUPD_RESULT_KEY_NAME_VARIANT_SUFFIX,
2080
0
               priv->name_variant_suffix);
2081
0
  }
2082
0
  if (priv->summary != NULL)
2083
0
    fwupd_json_object_add_string(json_obj, FWUPD_RESULT_KEY_SUMMARY, priv->summary);
2084
0
  if (priv->description != NULL) {
2085
0
    fwupd_json_object_add_string(json_obj,
2086
0
               FWUPD_RESULT_KEY_DESCRIPTION,
2087
0
               priv->description);
2088
0
  }
2089
0
  if (priv->branch != NULL)
2090
0
    fwupd_json_object_add_string(json_obj, FWUPD_RESULT_KEY_BRANCH, priv->branch);
2091
0
  if (priv->version != NULL)
2092
0
    fwupd_json_object_add_string(json_obj, FWUPD_RESULT_KEY_VERSION, priv->version);
2093
0
  if (priv->filename != NULL)
2094
0
    fwupd_json_object_add_string(json_obj, FWUPD_RESULT_KEY_FILENAME, priv->filename);
2095
0
  if (priv->protocol != NULL)
2096
0
    fwupd_json_object_add_string(json_obj, FWUPD_RESULT_KEY_PROTOCOL, priv->protocol);
2097
0
  if (priv->categories != NULL && priv->categories->len > 0) {
2098
0
    g_autoptr(FwupdJsonArray) json_arr = fwupd_json_array_new();
2099
0
    for (guint i = 0; i < priv->categories->len; i++) {
2100
0
      const gchar *tmp = g_ptr_array_index(priv->categories, i);
2101
0
      fwupd_json_array_add_string(json_arr, tmp);
2102
0
    }
2103
0
    fwupd_json_object_add_array(json_obj, FWUPD_RESULT_KEY_CATEGORIES, json_arr);
2104
0
  }
2105
0
  if (priv->issues != NULL && priv->issues->len > 0) {
2106
0
    g_autoptr(FwupdJsonArray) json_arr = fwupd_json_array_new();
2107
0
    for (guint i = 0; i < priv->issues->len; i++) {
2108
0
      const gchar *tmp = g_ptr_array_index(priv->issues, i);
2109
0
      fwupd_json_array_add_string(json_arr, tmp);
2110
0
    }
2111
0
    fwupd_json_object_add_array(json_obj, FWUPD_RESULT_KEY_ISSUES, json_arr);
2112
0
  }
2113
0
  if (priv->checksums != NULL && priv->checksums->len > 0) {
2114
0
    g_autoptr(FwupdJsonArray) json_arr = fwupd_json_array_new();
2115
0
    for (guint i = 0; i < priv->checksums->len; i++) {
2116
0
      const gchar *checksum = g_ptr_array_index(priv->checksums, i);
2117
0
      fwupd_json_array_add_string(json_arr, checksum);
2118
0
    }
2119
0
    fwupd_json_object_add_array(json_obj, FWUPD_RESULT_KEY_CHECKSUM, json_arr);
2120
0
  }
2121
0
  if (priv->tags != NULL && priv->tags->len > 0) {
2122
0
    g_autoptr(FwupdJsonArray) json_arr = fwupd_json_array_new();
2123
0
    for (guint i = 0; i < priv->tags->len; i++) {
2124
0
      const gchar *tag = g_ptr_array_index(priv->tags, i);
2125
0
      fwupd_json_array_add_string(json_arr, tag);
2126
0
    }
2127
0
    fwupd_json_object_add_array(json_obj, FWUPD_RESULT_KEY_TAGS, json_arr);
2128
0
  }
2129
0
  if (priv->license != NULL)
2130
0
    fwupd_json_object_add_string(json_obj, FWUPD_RESULT_KEY_LICENSE, priv->license);
2131
0
  if (priv->size > 0)
2132
0
    fwupd_json_object_add_integer(json_obj, FWUPD_RESULT_KEY_SIZE, priv->size);
2133
0
  if (priv->created > 0)
2134
0
    fwupd_json_object_add_integer(json_obj, FWUPD_RESULT_KEY_CREATED, priv->created);
2135
0
  if (priv->locations != NULL && priv->locations->len > 0) {
2136
0
    g_autoptr(FwupdJsonArray) json_arr = fwupd_json_array_new();
2137
0
    for (guint i = 0; i < priv->locations->len; i++) {
2138
0
      const gchar *location = g_ptr_array_index(priv->locations, i);
2139
0
      fwupd_json_array_add_string(json_arr, location);
2140
0
    }
2141
0
    fwupd_json_object_add_array(json_obj, FWUPD_RESULT_KEY_LOCATIONS, json_arr);
2142
0
  }
2143
0
  if (priv->homepage != NULL)
2144
0
    fwupd_json_object_add_string(json_obj, FWUPD_RESULT_KEY_HOMEPAGE, priv->homepage);
2145
0
  if (priv->details_url != NULL) {
2146
0
    fwupd_json_object_add_string(json_obj,
2147
0
               FWUPD_RESULT_KEY_DETAILS_URL,
2148
0
               priv->details_url);
2149
0
  }
2150
0
  if (priv->source_url != NULL) {
2151
0
    fwupd_json_object_add_string(json_obj,
2152
0
               FWUPD_RESULT_KEY_SOURCE_URL,
2153
0
               priv->source_url);
2154
0
  }
2155
0
  if (priv->sbom_url != NULL)
2156
0
    fwupd_json_object_add_string(json_obj, FWUPD_RESULT_KEY_SBOM_URL, priv->sbom_url);
2157
0
  if (priv->vendor != NULL)
2158
0
    fwupd_json_object_add_string(json_obj, FWUPD_RESULT_KEY_VENDOR, priv->vendor);
2159
0
  if (priv->flags != FWUPD_RELEASE_FLAG_NONE) {
2160
0
    g_autoptr(FwupdJsonArray) json_arr = fwupd_json_array_new();
2161
0
    for (guint i = 0; i < 64; i++) {
2162
0
      const gchar *tmp;
2163
0
      if ((priv->flags & ((guint64)1 << i)) == 0)
2164
0
        continue;
2165
0
      tmp = fwupd_release_flag_to_string((guint64)1 << i);
2166
0
      fwupd_json_array_add_string(json_arr, tmp);
2167
0
    }
2168
0
    fwupd_json_object_add_array(json_obj, FWUPD_RESULT_KEY_FLAGS, json_arr);
2169
0
  }
2170
0
  if (priv->install_duration > 0) {
2171
0
    fwupd_json_object_add_integer(json_obj,
2172
0
                FWUPD_RESULT_KEY_INSTALL_DURATION,
2173
0
                priv->install_duration);
2174
0
  }
2175
0
  if (priv->detach_caption != NULL) {
2176
0
    fwupd_json_object_add_string(json_obj,
2177
0
               FWUPD_RESULT_KEY_DETACH_CAPTION,
2178
0
               priv->detach_caption);
2179
0
  }
2180
0
  if (priv->detach_image != NULL) {
2181
0
    fwupd_json_object_add_string(json_obj,
2182
0
               FWUPD_RESULT_KEY_DETACH_IMAGE,
2183
0
               priv->detach_image);
2184
0
  }
2185
0
  if (priv->update_message != NULL) {
2186
0
    fwupd_json_object_add_string(json_obj,
2187
0
               FWUPD_RESULT_KEY_UPDATE_MESSAGE,
2188
0
               priv->update_message);
2189
0
  }
2190
0
  if (priv->update_image != NULL) {
2191
0
    fwupd_json_object_add_string(json_obj,
2192
0
               FWUPD_RESULT_KEY_UPDATE_IMAGE,
2193
0
               priv->update_image);
2194
0
  }
2195
2196
  /* metadata */
2197
0
  if (priv->metadata != NULL) {
2198
0
    g_autoptr(GList) keys = g_hash_table_get_keys(priv->metadata);
2199
0
    for (GList *l = keys; l != NULL; l = l->next) {
2200
0
      const gchar *key = l->data;
2201
0
      const gchar *value = g_hash_table_lookup(priv->metadata, key);
2202
0
      fwupd_json_object_add_string(json_obj, key, value);
2203
0
    }
2204
0
  }
2205
2206
  /* reports */
2207
0
  if (priv->reports != NULL && priv->reports->len > 0)
2208
0
    fwupd_codec_array_to_json(priv->reports, "Reports", json_obj, flags);
2209
0
}
2210
2211
static void
2212
fwupd_release_add_string(FwupdCodec *codec, guint idt, GString *str)
2213
0
{
2214
0
  FwupdRelease *self = FWUPD_RELEASE(codec);
2215
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
2216
2217
0
  fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_APPSTREAM_ID, priv->appstream_id);
2218
0
  fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_RELEASE_ID, priv->id);
2219
0
  fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_REMOTE_ID, priv->remote_id);
2220
0
  fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_NAME, priv->name);
2221
0
  fwupd_codec_string_append(str,
2222
0
          idt,
2223
0
          FWUPD_RESULT_KEY_NAME_VARIANT_SUFFIX,
2224
0
          priv->name_variant_suffix);
2225
0
  fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_SUMMARY, priv->summary);
2226
0
  fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_DESCRIPTION, priv->description);
2227
0
  fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_BRANCH, priv->branch);
2228
0
  fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_VERSION, priv->version);
2229
0
  fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_FILENAME, priv->filename);
2230
0
  fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_PROTOCOL, priv->protocol);
2231
0
  if (priv->categories != NULL) {
2232
0
    for (guint i = 0; i < priv->categories->len; i++) {
2233
0
      const gchar *tmp = g_ptr_array_index(priv->categories, i);
2234
0
      fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_CATEGORIES, tmp);
2235
0
    }
2236
0
  }
2237
0
  if (priv->issues != NULL) {
2238
0
    for (guint i = 0; i < priv->issues->len; i++) {
2239
0
      const gchar *tmp = g_ptr_array_index(priv->issues, i);
2240
0
      fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_ISSUES, tmp);
2241
0
    }
2242
0
  }
2243
0
  if (priv->checksums != NULL) {
2244
0
    for (guint i = 0; i < priv->checksums->len; i++) {
2245
0
      const gchar *checksum = g_ptr_array_index(priv->checksums, i);
2246
0
      g_autofree gchar *checksum_display =
2247
0
          fwupd_checksum_format_for_display(checksum);
2248
0
      fwupd_codec_string_append(str,
2249
0
              idt,
2250
0
              FWUPD_RESULT_KEY_CHECKSUM,
2251
0
              checksum_display);
2252
0
    }
2253
0
  }
2254
0
  if (priv->tags != NULL) {
2255
0
    for (guint i = 0; i < priv->tags->len; i++) {
2256
0
      const gchar *tag = g_ptr_array_index(priv->tags, i);
2257
0
      fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_TAGS, tag);
2258
0
    }
2259
0
  }
2260
0
  fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_LICENSE, priv->license);
2261
0
  fwupd_codec_string_append_size(str, idt, FWUPD_RESULT_KEY_SIZE, priv->size);
2262
0
  fwupd_codec_string_append_time(str, idt, FWUPD_RESULT_KEY_CREATED, priv->created);
2263
0
  if (priv->locations != NULL) {
2264
0
    for (guint i = 0; i < priv->locations->len; i++) {
2265
0
      const gchar *location = g_ptr_array_index(priv->locations, i);
2266
0
      fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_URI, location);
2267
0
    }
2268
0
  }
2269
0
  fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_HOMEPAGE, priv->homepage);
2270
0
  fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_DETAILS_URL, priv->details_url);
2271
0
  fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_SOURCE_URL, priv->source_url);
2272
0
  fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_SBOM_URL, priv->sbom_url);
2273
0
  if (priv->urgency != FWUPD_RELEASE_URGENCY_UNKNOWN) {
2274
0
    fwupd_codec_string_append(str,
2275
0
            idt,
2276
0
            FWUPD_RESULT_KEY_URGENCY,
2277
0
            fwupd_release_urgency_to_string(priv->urgency));
2278
0
  }
2279
0
  fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_VENDOR, priv->vendor);
2280
0
  fwupd_release_string_append_flags(str, idt, FWUPD_RESULT_KEY_FLAGS, priv->flags);
2281
0
  fwupd_codec_string_append_int(str,
2282
0
              idt,
2283
0
              FWUPD_RESULT_KEY_INSTALL_DURATION,
2284
0
              priv->install_duration);
2285
0
  fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_DETACH_CAPTION, priv->detach_caption);
2286
0
  fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_DETACH_IMAGE, priv->detach_image);
2287
0
  fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_UPDATE_MESSAGE, priv->update_message);
2288
0
  fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_UPDATE_IMAGE, priv->update_image);
2289
2290
  /* metadata */
2291
0
  if (priv->metadata != NULL) {
2292
0
    g_autoptr(GList) keys = g_hash_table_get_keys(priv->metadata);
2293
0
    for (GList *l = keys; l != NULL; l = l->next) {
2294
0
      const gchar *key = l->data;
2295
0
      const gchar *value = g_hash_table_lookup(priv->metadata, key);
2296
0
      fwupd_codec_string_append(str, idt, key, value);
2297
0
    }
2298
0
  }
2299
0
  if (priv->reports != NULL) {
2300
0
    for (guint i = 0; i < priv->reports->len; i++) {
2301
0
      FwupdReport *report = g_ptr_array_index(priv->reports, i);
2302
0
      fwupd_codec_add_string(FWUPD_CODEC(report), idt, str);
2303
0
    }
2304
0
  }
2305
0
}
2306
2307
static void
2308
fwupd_release_get_property(GObject *obj, guint prop_id, GValue *value, GParamSpec *pspec)
2309
0
{
2310
0
  FwupdRelease *self = FWUPD_RELEASE(obj);
2311
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
2312
2313
0
  switch (prop_id) {
2314
0
  case PROP_REMOTE_ID:
2315
0
    g_value_set_string(value, priv->remote_id);
2316
0
    break;
2317
0
  default:
2318
0
    G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, prop_id, pspec);
2319
0
    break;
2320
0
  }
2321
0
}
2322
2323
static void
2324
fwupd_release_set_property(GObject *obj, guint prop_id, const GValue *value, GParamSpec *pspec)
2325
0
{
2326
0
  FwupdRelease *self = FWUPD_RELEASE(obj);
2327
2328
0
  switch (prop_id) {
2329
0
  case PROP_REMOTE_ID:
2330
0
    fwupd_release_set_remote_id(self, g_value_get_string(value));
2331
0
    break;
2332
0
  default:
2333
0
    G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, prop_id, pspec);
2334
0
    break;
2335
0
  }
2336
0
}
2337
2338
static void
2339
fwupd_release_class_init(FwupdReleaseClass *klass)
2340
0
{
2341
0
  GParamSpec *pspec;
2342
0
  GObjectClass *object_class = G_OBJECT_CLASS(klass);
2343
0
  object_class->finalize = fwupd_release_finalize;
2344
0
  object_class->get_property = fwupd_release_get_property;
2345
0
  object_class->set_property = fwupd_release_set_property;
2346
2347
  /**
2348
   * FwupdRelease:remote-id:
2349
   *
2350
   * The remote ID.
2351
   *
2352
   * Since: 1.8.0
2353
   */
2354
0
  pspec = g_param_spec_string("remote-id",
2355
0
            NULL,
2356
0
            NULL,
2357
0
            NULL,
2358
0
            G_PARAM_READWRITE | G_PARAM_STATIC_NAME);
2359
0
  g_object_class_install_property(object_class, PROP_REMOTE_ID, pspec);
2360
0
}
2361
2362
static void
2363
fwupd_release_init(FwupdRelease *self)
2364
0
{
2365
0
}
2366
2367
static void
2368
fwupd_release_finalize(GObject *object)
2369
0
{
2370
0
  FwupdRelease *self = FWUPD_RELEASE(object);
2371
0
  FwupdReleasePrivate *priv = GET_PRIVATE(self);
2372
2373
0
  g_free(priv->description);
2374
0
  g_free(priv->filename);
2375
0
  g_free(priv->protocol);
2376
0
  g_free(priv->appstream_id);
2377
0
  g_free(priv->id);
2378
0
  g_free(priv->detach_caption);
2379
0
  g_free(priv->detach_image);
2380
0
  g_free(priv->license);
2381
0
  g_free(priv->name);
2382
0
  g_free(priv->name_variant_suffix);
2383
0
  g_free(priv->summary);
2384
0
  g_free(priv->branch);
2385
0
  if (priv->locations != NULL)
2386
0
    g_ptr_array_unref(priv->locations);
2387
0
  g_free(priv->homepage);
2388
0
  g_free(priv->details_url);
2389
0
  g_free(priv->source_url);
2390
0
  g_free(priv->sbom_url);
2391
0
  g_free(priv->vendor);
2392
0
  g_free(priv->version);
2393
0
  g_free(priv->remote_id);
2394
0
  g_free(priv->update_message);
2395
0
  g_free(priv->update_image);
2396
0
  if (priv->categories != NULL)
2397
0
    g_ptr_array_unref(priv->categories);
2398
0
  if (priv->issues != NULL)
2399
0
    g_ptr_array_unref(priv->issues);
2400
0
  if (priv->checksums != NULL)
2401
0
    g_ptr_array_unref(priv->checksums);
2402
0
  if (priv->tags != NULL)
2403
0
    g_ptr_array_unref(priv->tags);
2404
0
  if (priv->reports != NULL)
2405
0
    g_ptr_array_unref(priv->reports);
2406
0
  if (priv->metadata != NULL)
2407
0
    g_hash_table_unref(priv->metadata);
2408
2409
0
  G_OBJECT_CLASS(fwupd_release_parent_class)->finalize(object);
2410
0
}
2411
2412
static void
2413
fwupd_release_from_variant_iter(FwupdCodec *codec, GVariantIter *iter)
2414
0
{
2415
0
  FwupdRelease *self = FWUPD_RELEASE(codec);
2416
0
  GVariant *value;
2417
0
  const gchar *key;
2418
0
  while (g_variant_iter_next(iter, "{&sv}", &key, &value)) {
2419
0
    fwupd_release_from_key_value(self, key, value);
2420
0
    g_variant_unref(value);
2421
0
  }
2422
0
}
2423
2424
static void
2425
fwupd_release_codec_iface_init(FwupdCodecInterface *iface)
2426
0
{
2427
0
  iface->add_string = fwupd_release_add_string;
2428
0
  iface->add_json = fwupd_release_add_json;
2429
0
  iface->add_variant = fwupd_release_add_variant;
2430
0
  iface->from_variant_iter = fwupd_release_from_variant_iter;
2431
0
}
2432
2433
/**
2434
 * fwupd_release_match_flags:
2435
 * @include: #FwupdReleaseFlags, or %FWUPD_RELEASE_FLAG_NONE
2436
 * @exclude: #FwupdReleaseFlags, or %FWUPD_RELEASE_FLAG_NONE
2437
 *
2438
 * Check if the release flags match.
2439
 *
2440
 * Returns: %TRUE if the release flags match
2441
 *
2442
 * Since: 1.9.3
2443
 **/
2444
gboolean
2445
fwupd_release_match_flags(FwupdRelease *self, FwupdReleaseFlags include, FwupdReleaseFlags exclude)
2446
0
{
2447
0
  g_return_val_if_fail(FWUPD_IS_RELEASE(self), FALSE);
2448
2449
0
  for (guint i = 0; i < 64; i++) {
2450
0
    FwupdReleaseFlags flag = 1LLU << i;
2451
0
    if ((include & flag) > 0) {
2452
0
      if (!fwupd_release_has_flag(self, flag))
2453
0
        return FALSE;
2454
0
    }
2455
0
    if ((exclude & flag) > 0) {
2456
0
      if (fwupd_release_has_flag(self, flag))
2457
0
        return FALSE;
2458
0
    }
2459
0
  }
2460
0
  return TRUE;
2461
0
}
2462
2463
/**
2464
 * fwupd_release_array_filter_flags:
2465
 * @rels: (not nullable) (element-type FwupdRelease): releases
2466
 * @include: #FwupdReleaseFlags, or %FWUPD_RELEASE_FLAG_NONE
2467
 * @exclude: #FwupdReleaseFlags, or %FWUPD_RELEASE_FLAG_NONE
2468
 * @error: (nullable): optional return location for an error
2469
 *
2470
 * Creates an array of new releases that match using fwupd_release_match_flags().
2471
 *
2472
 * Returns: (transfer container) (element-type FwupdRelease): releases
2473
 *
2474
 * Since: 1.9.3
2475
 **/
2476
GPtrArray *
2477
fwupd_release_array_filter_flags(GPtrArray *rels,
2478
         FwupdReleaseFlags include,
2479
         FwupdReleaseFlags exclude,
2480
         GError **error)
2481
0
{
2482
0
  g_autoptr(GPtrArray) rels_filtered =
2483
0
      g_ptr_array_new_with_free_func((GDestroyNotify)g_object_unref);
2484
2485
0
  g_return_val_if_fail(rels != NULL, NULL);
2486
0
  g_return_val_if_fail(error == NULL || *error == NULL, NULL);
2487
2488
0
  for (guint i = 0; i < rels->len; i++) {
2489
0
    FwupdRelease *rel = g_ptr_array_index(rels, i);
2490
0
    if (!fwupd_release_match_flags(rel, include, exclude))
2491
0
      continue;
2492
0
    g_ptr_array_add(rels_filtered, g_object_ref(rel));
2493
0
  }
2494
0
  if (rels_filtered->len == 0) {
2495
0
    g_set_error_literal(error, FWUPD_ERROR, FWUPD_ERROR_NOTHING_TO_DO, "no releases");
2496
0
    return NULL;
2497
0
  }
2498
0
  return g_steal_pointer(&rels_filtered);
2499
0
}
2500
2501
/**
2502
 * fwupd_release_new:
2503
 *
2504
 * Creates a new release.
2505
 *
2506
 * Returns: a new #FwupdRelease
2507
 *
2508
 * Since: 0.9.3
2509
 **/
2510
FwupdRelease *
2511
fwupd_release_new(void)
2512
0
{
2513
0
  FwupdRelease *self;
2514
0
  self = g_object_new(FWUPD_TYPE_RELEASE, NULL);
2515
0
  return FWUPD_RELEASE(self);
2516
0
}