/src/fwupd/libfwupd/fwupd-report.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright 2022 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-report.h" |
16 | | |
17 | | /** |
18 | | * FwupdReport: |
19 | | * |
20 | | * A firmware report from a vendor. |
21 | | * |
22 | | * This is the LVFS formatted report that the fwupd user consumes, NOT the thing that gets uploaded. |
23 | | * |
24 | | * See also: [class@FwupdRelease] |
25 | | */ |
26 | | |
27 | | typedef struct { |
28 | | guint64 created; |
29 | | gchar *version_old; |
30 | | gchar *vendor; |
31 | | guint32 vendor_id; |
32 | | gchar *device_name; |
33 | | gchar *distro_id; |
34 | | gchar *distro_version; |
35 | | GHashTable *metadata; |
36 | | gchar *distro_variant; |
37 | | gchar *remote_id; |
38 | | FwupdReportFlags flags; |
39 | | } FwupdReportPrivate; |
40 | | |
41 | | enum { PROP_0, PROP_FLAGS, PROP_LAST }; |
42 | | |
43 | | static void |
44 | | fwupd_report_codec_iface_init(FwupdCodecInterface *iface); |
45 | | |
46 | | G_DEFINE_TYPE_EXTENDED(FwupdReport, |
47 | | fwupd_report, |
48 | | G_TYPE_OBJECT, |
49 | | 0, |
50 | | G_ADD_PRIVATE(FwupdReport) |
51 | | G_IMPLEMENT_INTERFACE(FWUPD_TYPE_CODEC, fwupd_report_codec_iface_init)); |
52 | | |
53 | 0 | #define GET_PRIVATE(o) (fwupd_report_get_instance_private(o)) |
54 | | |
55 | | /** |
56 | | * fwupd_report_get_created: |
57 | | * @self: a #FwupdReport |
58 | | * |
59 | | * Gets when the report was created. |
60 | | * |
61 | | * Returns: UTC timestamp in UNIX format, or 0 if unset |
62 | | * |
63 | | * Since: 1.8.8 |
64 | | **/ |
65 | | guint64 |
66 | | fwupd_report_get_created(FwupdReport *self) |
67 | 0 | { |
68 | 0 | FwupdReportPrivate *priv = GET_PRIVATE(self); |
69 | 0 | g_return_val_if_fail(FWUPD_IS_REPORT(self), 0); |
70 | 0 | return priv->created; |
71 | 0 | } |
72 | | |
73 | | /** |
74 | | * fwupd_report_set_created: |
75 | | * @self: a #FwupdReport |
76 | | * @created: UTC timestamp in UNIX format |
77 | | * |
78 | | * Sets when the report was created. |
79 | | * |
80 | | * Since: 1.8.8 |
81 | | **/ |
82 | | void |
83 | | fwupd_report_set_created(FwupdReport *self, guint64 created) |
84 | 0 | { |
85 | 0 | FwupdReportPrivate *priv = GET_PRIVATE(self); |
86 | 0 | g_return_if_fail(FWUPD_IS_REPORT(self)); |
87 | 0 | priv->created = created; |
88 | 0 | } |
89 | | |
90 | | /** |
91 | | * fwupd_report_get_version_old: |
92 | | * @self: a #FwupdReport |
93 | | * |
94 | | * Gets the old version, i.e. what the upser was upgrading *from*. |
95 | | * |
96 | | * Returns: the version, or %NULL if unset |
97 | | * |
98 | | * Since: 1.8.8 |
99 | | **/ |
100 | | const gchar * |
101 | | fwupd_report_get_version_old(FwupdReport *self) |
102 | 0 | { |
103 | 0 | FwupdReportPrivate *priv = GET_PRIVATE(self); |
104 | 0 | g_return_val_if_fail(FWUPD_IS_REPORT(self), NULL); |
105 | 0 | return priv->version_old; |
106 | 0 | } |
107 | | |
108 | | /** |
109 | | * fwupd_report_set_version_old: |
110 | | * @self: a #FwupdReport |
111 | | * @version_old: (nullable): the version, e.g. `1.2.3` |
112 | | * |
113 | | * Sets the old version, i.e. what the upser was upgrading *from*. |
114 | | * |
115 | | * Since: 1.8.8 |
116 | | **/ |
117 | | void |
118 | | fwupd_report_set_version_old(FwupdReport *self, const gchar *version_old) |
119 | 0 | { |
120 | 0 | FwupdReportPrivate *priv = GET_PRIVATE(self); |
121 | 0 | g_return_if_fail(FWUPD_IS_REPORT(self)); |
122 | | |
123 | | /* not changed */ |
124 | 0 | if (g_strcmp0(priv->version_old, version_old) == 0) |
125 | 0 | return; |
126 | | |
127 | 0 | g_free(priv->version_old); |
128 | 0 | priv->version_old = g_strdup(version_old); |
129 | 0 | } |
130 | | |
131 | | /** |
132 | | * fwupd_report_get_vendor: |
133 | | * @self: a #FwupdReport |
134 | | * |
135 | | * Gets the vendor that uploaded the test result. |
136 | | * |
137 | | * Returns: the test vendor, or %NULL if unset |
138 | | * |
139 | | * Since: 1.8.8 |
140 | | **/ |
141 | | const gchar * |
142 | | fwupd_report_get_vendor(FwupdReport *self) |
143 | 0 | { |
144 | 0 | FwupdReportPrivate *priv = GET_PRIVATE(self); |
145 | 0 | g_return_val_if_fail(FWUPD_IS_REPORT(self), NULL); |
146 | 0 | return priv->vendor; |
147 | 0 | } |
148 | | |
149 | | /** |
150 | | * fwupd_report_set_vendor: |
151 | | * @self: a #FwupdReport |
152 | | * @vendor: (nullable): the vendor name |
153 | | * |
154 | | * Sets the vendor that uploaded the test result. |
155 | | * |
156 | | * Since: 1.8.8 |
157 | | **/ |
158 | | void |
159 | | fwupd_report_set_vendor(FwupdReport *self, const gchar *vendor) |
160 | 0 | { |
161 | 0 | FwupdReportPrivate *priv = GET_PRIVATE(self); |
162 | 0 | g_return_if_fail(FWUPD_IS_REPORT(self)); |
163 | | |
164 | | /* not changed */ |
165 | 0 | if (g_strcmp0(priv->vendor, vendor) == 0) |
166 | 0 | return; |
167 | | |
168 | 0 | g_free(priv->vendor); |
169 | 0 | priv->vendor = g_strdup(vendor); |
170 | 0 | } |
171 | | |
172 | | /** |
173 | | * fwupd_report_get_vendor_id: |
174 | | * @self: a #FwupdReport |
175 | | * |
176 | | * Gets the vendor identifier. The mapping is only known on the remote server, and this can be |
177 | | * useful to filter on different QA teams that work for the same OEM. |
178 | | * |
179 | | * Returns: the vendor ID, or 0 if unset |
180 | | * |
181 | | * Since: 1.8.8 |
182 | | **/ |
183 | | guint32 |
184 | | fwupd_report_get_vendor_id(FwupdReport *self) |
185 | 0 | { |
186 | 0 | FwupdReportPrivate *priv = GET_PRIVATE(self); |
187 | 0 | g_return_val_if_fail(FWUPD_IS_REPORT(self), 0); |
188 | 0 | return priv->vendor_id; |
189 | 0 | } |
190 | | |
191 | | /** |
192 | | * fwupd_report_set_vendor_id: |
193 | | * @self: a #FwupdReport |
194 | | * @vendor_id: the vendor ID, or 0 |
195 | | * |
196 | | * Sets the vendor identifier. The mapping is only known on the remote server, and this can be |
197 | | * useful to filter on different QA teams that work for the same OEM. |
198 | | * |
199 | | * Since: 1.8.8 |
200 | | **/ |
201 | | void |
202 | | fwupd_report_set_vendor_id(FwupdReport *self, guint32 vendor_id) |
203 | 0 | { |
204 | 0 | FwupdReportPrivate *priv = GET_PRIVATE(self); |
205 | 0 | g_return_if_fail(FWUPD_IS_REPORT(self)); |
206 | 0 | priv->vendor_id = vendor_id; |
207 | 0 | } |
208 | | |
209 | | /** |
210 | | * fwupd_report_get_device_name: |
211 | | * @self: a #FwupdReport |
212 | | * |
213 | | * Gets the name of the device the update was performed on. |
214 | | * |
215 | | * Returns: the name, or %NULL if unset |
216 | | * |
217 | | * Since: 1.8.8 |
218 | | **/ |
219 | | const gchar * |
220 | | fwupd_report_get_device_name(FwupdReport *self) |
221 | 0 | { |
222 | 0 | FwupdReportPrivate *priv = GET_PRIVATE(self); |
223 | 0 | g_return_val_if_fail(FWUPD_IS_REPORT(self), NULL); |
224 | 0 | return priv->device_name; |
225 | 0 | } |
226 | | |
227 | | /** |
228 | | * fwupd_report_set_device_name: |
229 | | * @self: a #FwupdReport |
230 | | * @device_name: (nullable): the name, e.g. `LENOVO ThinkPad P1 Gen 3` |
231 | | * |
232 | | * Sets the name of the device the update was performed on. |
233 | | * |
234 | | * Since: 1.8.8 |
235 | | **/ |
236 | | void |
237 | | fwupd_report_set_device_name(FwupdReport *self, const gchar *device_name) |
238 | 0 | { |
239 | 0 | FwupdReportPrivate *priv = GET_PRIVATE(self); |
240 | 0 | g_return_if_fail(FWUPD_IS_REPORT(self)); |
241 | | |
242 | | /* not changed */ |
243 | 0 | if (g_strcmp0(priv->device_name, device_name) == 0) |
244 | 0 | return; |
245 | | |
246 | 0 | g_free(priv->device_name); |
247 | 0 | priv->device_name = g_strdup(device_name); |
248 | 0 | } |
249 | | |
250 | | /** |
251 | | * fwupd_report_get_distro_id: |
252 | | * @self: a #FwupdReport |
253 | | * |
254 | | * Gets the distribution name. |
255 | | * |
256 | | * Returns: the name, or %NULL if unset |
257 | | * |
258 | | * Since: 1.8.8 |
259 | | **/ |
260 | | const gchar * |
261 | | fwupd_report_get_distro_id(FwupdReport *self) |
262 | 0 | { |
263 | 0 | FwupdReportPrivate *priv = GET_PRIVATE(self); |
264 | 0 | g_return_val_if_fail(FWUPD_IS_REPORT(self), NULL); |
265 | 0 | return priv->distro_id; |
266 | 0 | } |
267 | | |
268 | | /** |
269 | | * fwupd_report_set_distro_id: |
270 | | * @self: a #FwupdReport |
271 | | * @distro_id: (nullable): the name, e.g. `fedora` |
272 | | * |
273 | | * Sets the distribution name. |
274 | | * |
275 | | * Since: 1.8.8 |
276 | | **/ |
277 | | void |
278 | | fwupd_report_set_distro_id(FwupdReport *self, const gchar *distro_id) |
279 | 0 | { |
280 | 0 | FwupdReportPrivate *priv = GET_PRIVATE(self); |
281 | 0 | g_return_if_fail(FWUPD_IS_REPORT(self)); |
282 | | |
283 | | /* not changed */ |
284 | 0 | if (g_strcmp0(priv->distro_id, distro_id) == 0) |
285 | 0 | return; |
286 | | |
287 | 0 | g_free(priv->distro_id); |
288 | 0 | priv->distro_id = g_strdup(distro_id); |
289 | 0 | } |
290 | | |
291 | | /** |
292 | | * fwupd_report_get_distro_variant: |
293 | | * @self: a #FwupdReport |
294 | | * |
295 | | * Gets the distribution variant. |
296 | | * |
297 | | * Returns: variant, or %NULL if unset |
298 | | * |
299 | | * Since: 1.8.8 |
300 | | **/ |
301 | | const gchar * |
302 | | fwupd_report_get_distro_variant(FwupdReport *self) |
303 | 0 | { |
304 | 0 | FwupdReportPrivate *priv = GET_PRIVATE(self); |
305 | 0 | g_return_val_if_fail(FWUPD_IS_REPORT(self), NULL); |
306 | 0 | return priv->distro_variant; |
307 | 0 | } |
308 | | |
309 | | /** |
310 | | * fwupd_report_set_distro_variant: |
311 | | * @self: a #FwupdReport |
312 | | * @distro_variant: (nullable): the variant, e.g. `workstation` |
313 | | * |
314 | | * Sets the distribution variant. |
315 | | * |
316 | | * Since: 1.8.8 |
317 | | **/ |
318 | | void |
319 | | fwupd_report_set_distro_variant(FwupdReport *self, const gchar *distro_variant) |
320 | 0 | { |
321 | 0 | FwupdReportPrivate *priv = GET_PRIVATE(self); |
322 | 0 | g_return_if_fail(FWUPD_IS_REPORT(self)); |
323 | | |
324 | | /* not changed */ |
325 | 0 | if (g_strcmp0(priv->distro_variant, distro_variant) == 0) |
326 | 0 | return; |
327 | | |
328 | 0 | g_free(priv->distro_variant); |
329 | 0 | priv->distro_variant = g_strdup(distro_variant); |
330 | 0 | } |
331 | | |
332 | | /** |
333 | | * fwupd_report_get_remote_id: |
334 | | * @self: a #FwupdReport |
335 | | * |
336 | | * Gets the remote ID. |
337 | | * |
338 | | * Returns: ID, or %NULL if unset |
339 | | * |
340 | | * Since: 1.9.3 |
341 | | **/ |
342 | | const gchar * |
343 | | fwupd_report_get_remote_id(FwupdReport *self) |
344 | 0 | { |
345 | 0 | FwupdReportPrivate *priv = GET_PRIVATE(self); |
346 | 0 | g_return_val_if_fail(FWUPD_IS_REPORT(self), NULL); |
347 | 0 | return priv->remote_id; |
348 | 0 | } |
349 | | |
350 | | /** |
351 | | * fwupd_report_set_remote_id: |
352 | | * @self: a #FwupdReport |
353 | | * @remote_id: (nullable): the remote, e.g. `lvfs` |
354 | | * |
355 | | * Sets the remote ID. |
356 | | * |
357 | | * Since: 1.9.3 |
358 | | **/ |
359 | | void |
360 | | fwupd_report_set_remote_id(FwupdReport *self, const gchar *remote_id) |
361 | 0 | { |
362 | 0 | FwupdReportPrivate *priv = GET_PRIVATE(self); |
363 | 0 | g_return_if_fail(FWUPD_IS_REPORT(self)); |
364 | | |
365 | | /* not changed */ |
366 | 0 | if (g_strcmp0(priv->remote_id, remote_id) == 0) |
367 | 0 | return; |
368 | | |
369 | 0 | g_free(priv->remote_id); |
370 | 0 | priv->remote_id = g_strdup(remote_id); |
371 | 0 | } |
372 | | |
373 | | /** |
374 | | * fwupd_report_get_distro_version: |
375 | | * @self: a #FwupdReport |
376 | | * |
377 | | * Gets the distribution version. |
378 | | * |
379 | | * Returns: a string, or %NULL if unset |
380 | | * |
381 | | * Since: 1.8.8 |
382 | | **/ |
383 | | const gchar * |
384 | | fwupd_report_get_distro_version(FwupdReport *self) |
385 | 0 | { |
386 | 0 | FwupdReportPrivate *priv = GET_PRIVATE(self); |
387 | 0 | g_return_val_if_fail(FWUPD_IS_REPORT(self), NULL); |
388 | 0 | return priv->distro_version; |
389 | 0 | } |
390 | | |
391 | | /** |
392 | | * fwupd_report_set_distro_version: |
393 | | * @self: a #FwupdReport |
394 | | * @distro_version: (nullable): a string |
395 | | * |
396 | | * Sets the distribution version. |
397 | | * |
398 | | * Since: 1.8.8 |
399 | | **/ |
400 | | void |
401 | | fwupd_report_set_distro_version(FwupdReport *self, const gchar *distro_version) |
402 | 0 | { |
403 | 0 | FwupdReportPrivate *priv = GET_PRIVATE(self); |
404 | 0 | g_return_if_fail(FWUPD_IS_REPORT(self)); |
405 | | |
406 | | /* not changed */ |
407 | 0 | if (g_strcmp0(priv->distro_version, distro_version) == 0) |
408 | 0 | return; |
409 | | |
410 | 0 | g_free(priv->distro_version); |
411 | 0 | priv->distro_version = g_strdup(distro_version); |
412 | 0 | } |
413 | | |
414 | | /** |
415 | | * fwupd_report_get_metadata: |
416 | | * @self: a #FwupdReport |
417 | | * |
418 | | * Gets the report metadata. |
419 | | * |
420 | | * Returns: (transfer none): the metadata, which may be empty |
421 | | * |
422 | | * Since: 1.8.8 |
423 | | **/ |
424 | | GHashTable * |
425 | | fwupd_report_get_metadata(FwupdReport *self) |
426 | 0 | { |
427 | 0 | FwupdReportPrivate *priv = GET_PRIVATE(self); |
428 | 0 | g_return_val_if_fail(FWUPD_IS_REPORT(self), NULL); |
429 | 0 | return priv->metadata; |
430 | 0 | } |
431 | | |
432 | | /** |
433 | | * fwupd_report_add_metadata_item: |
434 | | * @self: a #FwupdReport |
435 | | * @key: (not nullable): the key |
436 | | * @value: (not nullable): the value |
437 | | * |
438 | | * Sets a report metadata item. |
439 | | * |
440 | | * Since: 1.8.8 |
441 | | **/ |
442 | | void |
443 | | fwupd_report_add_metadata_item(FwupdReport *self, const gchar *key, const gchar *value) |
444 | 0 | { |
445 | 0 | FwupdReportPrivate *priv = GET_PRIVATE(self); |
446 | 0 | g_return_if_fail(FWUPD_IS_REPORT(self)); |
447 | 0 | g_return_if_fail(key != NULL); |
448 | 0 | g_return_if_fail(value != NULL); |
449 | 0 | g_hash_table_insert(priv->metadata, g_strdup(key), g_strdup(value)); |
450 | 0 | } |
451 | | |
452 | | /** |
453 | | * fwupd_report_get_metadata_item: |
454 | | * @self: a #FwupdReport |
455 | | * @key: (not nullable): the key |
456 | | * |
457 | | * Gets a report metadata item. |
458 | | * |
459 | | * Returns: the value, or %NULL if unset |
460 | | * |
461 | | * Since: 1.8.8 |
462 | | **/ |
463 | | const gchar * |
464 | | fwupd_report_get_metadata_item(FwupdReport *self, const gchar *key) |
465 | 0 | { |
466 | 0 | FwupdReportPrivate *priv = GET_PRIVATE(self); |
467 | 0 | g_return_val_if_fail(FWUPD_IS_REPORT(self), NULL); |
468 | 0 | g_return_val_if_fail(key != NULL, NULL); |
469 | 0 | return g_hash_table_lookup(priv->metadata, key); |
470 | 0 | } |
471 | | |
472 | | static void |
473 | | fwupd_report_add_variant(FwupdCodec *codec, GVariantBuilder *builder, FwupdCodecFlags flags) |
474 | 0 | { |
475 | 0 | FwupdReport *self = FWUPD_REPORT(codec); |
476 | 0 | FwupdReportPrivate *priv = GET_PRIVATE(self); |
477 | |
|
478 | 0 | if (priv->distro_id != NULL) { |
479 | 0 | g_variant_builder_add(builder, |
480 | 0 | "{sv}", |
481 | 0 | FWUPD_RESULT_KEY_DISTRO_ID, |
482 | 0 | g_variant_new_string(priv->distro_id)); |
483 | 0 | } |
484 | 0 | if (priv->distro_variant != NULL) { |
485 | 0 | g_variant_builder_add(builder, |
486 | 0 | "{sv}", |
487 | 0 | FWUPD_RESULT_KEY_DISTRO_VARIANT, |
488 | 0 | g_variant_new_string(priv->distro_variant)); |
489 | 0 | } |
490 | 0 | if (priv->distro_version != NULL) { |
491 | 0 | g_variant_builder_add(builder, |
492 | 0 | "{sv}", |
493 | 0 | FWUPD_RESULT_KEY_DISTRO_VERSION, |
494 | 0 | g_variant_new_string(priv->distro_version)); |
495 | 0 | } |
496 | 0 | if (priv->vendor != NULL) { |
497 | 0 | g_variant_builder_add(builder, |
498 | 0 | "{sv}", |
499 | 0 | FWUPD_RESULT_KEY_VENDOR, |
500 | 0 | g_variant_new_string(priv->vendor)); |
501 | 0 | } |
502 | 0 | if (priv->device_name != NULL) { |
503 | 0 | g_variant_builder_add(builder, |
504 | 0 | "{sv}", |
505 | 0 | FWUPD_RESULT_KEY_DEVICE_NAME, |
506 | 0 | g_variant_new_string(priv->device_name)); |
507 | 0 | } |
508 | 0 | if (priv->created != 0) { |
509 | 0 | g_variant_builder_add(builder, |
510 | 0 | "{sv}", |
511 | 0 | FWUPD_RESULT_KEY_CREATED, |
512 | 0 | g_variant_new_uint64(priv->created)); |
513 | 0 | } |
514 | 0 | if (priv->version_old != NULL) { |
515 | 0 | g_variant_builder_add(builder, |
516 | 0 | "{sv}", |
517 | 0 | FWUPD_RESULT_KEY_VERSION_OLD, |
518 | 0 | g_variant_new_string(priv->version_old)); |
519 | 0 | } |
520 | 0 | if (priv->vendor_id > 0) { |
521 | 0 | g_variant_builder_add(builder, |
522 | 0 | "{sv}", |
523 | 0 | FWUPD_RESULT_KEY_VENDOR_ID, |
524 | 0 | g_variant_new_uint32(priv->vendor_id)); |
525 | 0 | } |
526 | 0 | if (priv->remote_id != NULL) { |
527 | 0 | g_variant_builder_add(builder, |
528 | 0 | "{sv}", |
529 | 0 | FWUPD_RESULT_KEY_REMOTE_ID, |
530 | 0 | g_variant_new_string(priv->remote_id)); |
531 | 0 | } |
532 | 0 | if (g_hash_table_size(priv->metadata) > 0) { |
533 | 0 | g_variant_builder_add(builder, |
534 | 0 | "{sv}", |
535 | 0 | FWUPD_RESULT_KEY_METADATA, |
536 | 0 | fwupd_hash_kv_to_variant(priv->metadata)); |
537 | 0 | } |
538 | 0 | if (priv->flags > 0) { |
539 | 0 | g_variant_builder_add(builder, |
540 | 0 | "{sv}", |
541 | 0 | FWUPD_RESULT_KEY_FLAGS, |
542 | 0 | g_variant_new_uint64(priv->flags)); |
543 | 0 | } |
544 | 0 | } |
545 | | |
546 | | static void |
547 | | fwupd_report_from_key_value(FwupdReport *self, const gchar *key, GVariant *value) |
548 | 0 | { |
549 | 0 | FwupdReportPrivate *priv = GET_PRIVATE(self); |
550 | 0 | if (g_strcmp0(key, FWUPD_RESULT_KEY_DISTRO_ID) == 0) { |
551 | 0 | fwupd_report_set_distro_id(self, g_variant_get_string(value, NULL)); |
552 | 0 | return; |
553 | 0 | } |
554 | 0 | if (g_strcmp0(key, FWUPD_RESULT_KEY_DISTRO_VARIANT) == 0) { |
555 | 0 | fwupd_report_set_distro_variant(self, g_variant_get_string(value, NULL)); |
556 | 0 | return; |
557 | 0 | } |
558 | 0 | if (g_strcmp0(key, FWUPD_RESULT_KEY_DISTRO_VERSION) == 0) { |
559 | 0 | fwupd_report_set_distro_version(self, g_variant_get_string(value, NULL)); |
560 | 0 | return; |
561 | 0 | } |
562 | 0 | if (g_strcmp0(key, FWUPD_RESULT_KEY_VENDOR) == 0) { |
563 | 0 | fwupd_report_set_vendor(self, g_variant_get_string(value, NULL)); |
564 | 0 | return; |
565 | 0 | } |
566 | 0 | if (g_strcmp0(key, FWUPD_RESULT_KEY_VENDOR_ID) == 0) { |
567 | 0 | fwupd_report_set_vendor_id(self, g_variant_get_uint32(value)); |
568 | 0 | return; |
569 | 0 | } |
570 | 0 | if (g_strcmp0(key, FWUPD_RESULT_KEY_DEVICE_NAME) == 0) { |
571 | 0 | fwupd_report_set_device_name(self, g_variant_get_string(value, NULL)); |
572 | 0 | return; |
573 | 0 | } |
574 | 0 | if (g_strcmp0(key, FWUPD_RESULT_KEY_CREATED) == 0) { |
575 | 0 | fwupd_report_set_created(self, g_variant_get_uint64(value)); |
576 | 0 | return; |
577 | 0 | } |
578 | 0 | if (g_strcmp0(key, FWUPD_RESULT_KEY_VERSION_OLD) == 0) { |
579 | 0 | fwupd_report_set_version_old(self, g_variant_get_string(value, NULL)); |
580 | 0 | return; |
581 | 0 | } |
582 | 0 | if (g_strcmp0(key, FWUPD_RESULT_KEY_REMOTE_ID) == 0) { |
583 | 0 | fwupd_report_set_remote_id(self, g_variant_get_string(value, NULL)); |
584 | 0 | return; |
585 | 0 | } |
586 | 0 | if (g_strcmp0(key, FWUPD_RESULT_KEY_FLAGS) == 0) { |
587 | 0 | fwupd_report_set_flags(self, g_variant_get_uint64(value)); |
588 | 0 | return; |
589 | 0 | } |
590 | 0 | if (g_strcmp0(key, FWUPD_RESULT_KEY_METADATA) == 0) { |
591 | 0 | g_hash_table_unref(priv->metadata); |
592 | 0 | priv->metadata = fwupd_variant_to_hash_kv(value); |
593 | 0 | return; |
594 | 0 | } |
595 | 0 | } |
596 | | |
597 | | static void |
598 | | fwupd_report_add_json(FwupdCodec *codec, JsonBuilder *builder, FwupdCodecFlags flags) |
599 | 0 | { |
600 | 0 | FwupdReport *self = FWUPD_REPORT(codec); |
601 | 0 | FwupdReportPrivate *priv = GET_PRIVATE(self); |
602 | 0 | g_autoptr(GList) keys = NULL; |
603 | |
|
604 | 0 | fwupd_codec_json_append(builder, FWUPD_RESULT_KEY_DEVICE_NAME, priv->device_name); |
605 | 0 | fwupd_codec_json_append(builder, FWUPD_RESULT_KEY_DISTRO_ID, priv->distro_id); |
606 | 0 | fwupd_codec_json_append(builder, FWUPD_RESULT_KEY_DISTRO_VARIANT, priv->distro_variant); |
607 | 0 | fwupd_codec_json_append(builder, FWUPD_RESULT_KEY_DISTRO_VERSION, priv->distro_version); |
608 | 0 | fwupd_codec_json_append(builder, FWUPD_RESULT_KEY_VERSION_OLD, priv->version_old); |
609 | 0 | fwupd_codec_json_append(builder, FWUPD_RESULT_KEY_VENDOR, priv->vendor); |
610 | 0 | fwupd_codec_json_append(builder, FWUPD_RESULT_KEY_REMOTE_ID, priv->remote_id); |
611 | 0 | if (priv->vendor_id > 0) { |
612 | 0 | fwupd_codec_json_append_int(builder, FWUPD_RESULT_KEY_VENDOR_ID, priv->vendor_id); |
613 | 0 | } |
614 | |
|
615 | 0 | if (priv->flags != FWUPD_REPORT_FLAG_NONE) { |
616 | 0 | json_builder_set_member_name(builder, FWUPD_RESULT_KEY_FLAGS); |
617 | 0 | json_builder_begin_array(builder); |
618 | 0 | for (guint i = 0; i < 64; i++) { |
619 | 0 | const gchar *tmp; |
620 | 0 | if ((priv->flags & ((guint64)1 << i)) == 0) |
621 | 0 | continue; |
622 | 0 | tmp = fwupd_report_flag_to_string((guint64)1 << i); |
623 | 0 | json_builder_add_string_value(builder, tmp); |
624 | 0 | } |
625 | 0 | json_builder_end_array(builder); |
626 | 0 | } |
627 | | |
628 | | /* metadata */ |
629 | 0 | keys = g_hash_table_get_keys(priv->metadata); |
630 | 0 | for (GList *l = keys; l != NULL; l = l->next) { |
631 | 0 | const gchar *key = l->data; |
632 | 0 | const gchar *value = g_hash_table_lookup(priv->metadata, key); |
633 | 0 | fwupd_codec_json_append(builder, key, value); |
634 | 0 | } |
635 | 0 | } |
636 | | |
637 | | static void |
638 | | fwupd_report_string_append_flags(GString *str, guint idt, const gchar *key, guint64 report_flags) |
639 | 0 | { |
640 | 0 | g_autoptr(GString) tmp = g_string_new(""); |
641 | 0 | for (guint i = 0; i < 64; i++) { |
642 | 0 | if ((report_flags & ((guint64)1 << i)) == 0) |
643 | 0 | continue; |
644 | 0 | g_string_append_printf(tmp, "%s|", fwupd_report_flag_to_string((guint64)1 << i)); |
645 | 0 | } |
646 | 0 | if (tmp->len == 0) { |
647 | 0 | g_string_append(tmp, fwupd_report_flag_to_string(0)); |
648 | 0 | } else { |
649 | 0 | g_string_truncate(tmp, tmp->len - 1); |
650 | 0 | } |
651 | 0 | fwupd_codec_string_append(str, idt, key, tmp->str); |
652 | 0 | } |
653 | | |
654 | | static void |
655 | | fwupd_report_add_string(FwupdCodec *codec, guint idt, GString *str) |
656 | 0 | { |
657 | 0 | FwupdReport *self = FWUPD_REPORT(codec); |
658 | 0 | FwupdReportPrivate *priv = GET_PRIVATE(self); |
659 | 0 | g_autoptr(GList) keys = NULL; |
660 | |
|
661 | 0 | fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_DEVICE_NAME, priv->device_name); |
662 | 0 | fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_DISTRO_ID, priv->distro_id); |
663 | 0 | fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_DISTRO_VARIANT, priv->distro_variant); |
664 | 0 | fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_DISTRO_VERSION, priv->distro_version); |
665 | 0 | fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_VERSION_OLD, priv->version_old); |
666 | 0 | fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_VENDOR, priv->vendor); |
667 | 0 | fwupd_codec_string_append_int(str, idt, FWUPD_RESULT_KEY_VENDOR_ID, priv->vendor_id); |
668 | 0 | fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_REMOTE_ID, priv->remote_id); |
669 | 0 | fwupd_report_string_append_flags(str, idt, FWUPD_RESULT_KEY_FLAGS, priv->flags); |
670 | | |
671 | | /* metadata */ |
672 | 0 | keys = g_hash_table_get_keys(priv->metadata); |
673 | 0 | for (GList *l = keys; l != NULL; l = l->next) { |
674 | 0 | const gchar *key = l->data; |
675 | 0 | const gchar *value = g_hash_table_lookup(priv->metadata, key); |
676 | 0 | fwupd_codec_string_append(str, idt, key, value); |
677 | 0 | } |
678 | 0 | } |
679 | | |
680 | | /** |
681 | | * fwupd_report_get_flags: |
682 | | * @self: a #FwupdReport |
683 | | * |
684 | | * Gets the report flags. |
685 | | * |
686 | | * Returns: report flags, or 0 if unset |
687 | | * |
688 | | * Since: 1.9.1 |
689 | | **/ |
690 | | guint64 |
691 | | fwupd_report_get_flags(FwupdReport *self) |
692 | 0 | { |
693 | 0 | FwupdReportPrivate *priv = GET_PRIVATE(self); |
694 | 0 | g_return_val_if_fail(FWUPD_IS_REPORT(self), 0); |
695 | 0 | return priv->flags; |
696 | 0 | } |
697 | | |
698 | | /** |
699 | | * fwupd_report_set_flags: |
700 | | * @self: a #FwupdReport |
701 | | * @flags: report flags, e.g. %FWUPD_REPORT_FLAG_FROM_OEM |
702 | | * |
703 | | * Sets the report flags. |
704 | | * |
705 | | * Since: 1.9.1 |
706 | | **/ |
707 | | void |
708 | | fwupd_report_set_flags(FwupdReport *self, guint64 flags) |
709 | 0 | { |
710 | 0 | FwupdReportPrivate *priv = GET_PRIVATE(self); |
711 | 0 | g_return_if_fail(FWUPD_IS_REPORT(self)); |
712 | 0 | if (priv->flags == flags) |
713 | 0 | return; |
714 | 0 | priv->flags = flags; |
715 | 0 | g_object_notify(G_OBJECT(self), "flags"); |
716 | 0 | } |
717 | | |
718 | | /** |
719 | | * fwupd_report_add_flag: |
720 | | * @self: a #FwupdReport |
721 | | * @flag: the #FwupdReportFlags |
722 | | * |
723 | | * Adds a specific report flag to the report. |
724 | | * |
725 | | * Since: 1.9.1 |
726 | | **/ |
727 | | void |
728 | | fwupd_report_add_flag(FwupdReport *self, FwupdReportFlags flag) |
729 | 0 | { |
730 | 0 | FwupdReportPrivate *priv = GET_PRIVATE(self); |
731 | 0 | g_return_if_fail(FWUPD_IS_REPORT(self)); |
732 | 0 | if (flag == 0) |
733 | 0 | return; |
734 | 0 | if ((priv->flags & flag) > 0) |
735 | 0 | return; |
736 | 0 | priv->flags |= flag; |
737 | 0 | g_object_notify(G_OBJECT(self), "flags"); |
738 | 0 | } |
739 | | |
740 | | /** |
741 | | * fwupd_report_remove_flag: |
742 | | * @self: a #FwupdReport |
743 | | * @flag: a report flag |
744 | | * |
745 | | * Removes a specific report flag from the report. |
746 | | * |
747 | | * Since: 1.9.1 |
748 | | **/ |
749 | | void |
750 | | fwupd_report_remove_flag(FwupdReport *self, FwupdReportFlags flag) |
751 | 0 | { |
752 | 0 | FwupdReportPrivate *priv = GET_PRIVATE(self); |
753 | 0 | g_return_if_fail(FWUPD_IS_REPORT(self)); |
754 | 0 | if (flag == 0) |
755 | 0 | return; |
756 | 0 | if ((priv->flags & flag) == 0) |
757 | 0 | return; |
758 | 0 | priv->flags &= ~flag; |
759 | 0 | g_object_notify(G_OBJECT(self), "flags"); |
760 | 0 | } |
761 | | |
762 | | /** |
763 | | * fwupd_report_has_flag: |
764 | | * @self: a #FwupdReport |
765 | | * @flag: a report flag |
766 | | * |
767 | | * Finds if the report has a specific report flag. |
768 | | * |
769 | | * Returns: %TRUE if the flag is set |
770 | | * |
771 | | * Since: 1.9.1 |
772 | | **/ |
773 | | gboolean |
774 | | fwupd_report_has_flag(FwupdReport *self, FwupdReportFlags flag) |
775 | 0 | { |
776 | 0 | FwupdReportPrivate *priv = GET_PRIVATE(self); |
777 | 0 | g_return_val_if_fail(FWUPD_IS_REPORT(self), FALSE); |
778 | 0 | return (priv->flags & flag) > 0; |
779 | 0 | } |
780 | | |
781 | | /** |
782 | | * fwupd_report_flag_to_string: |
783 | | * @report_flag: report flags, e.g. %FWUPD_REPORT_FLAG_FROM_OEM |
784 | | * |
785 | | * Converts an enumerated report flag to a string. |
786 | | * |
787 | | * Returns: identifier string |
788 | | * |
789 | | * Since: 1.9.1 |
790 | | **/ |
791 | | const gchar * |
792 | | fwupd_report_flag_to_string(FwupdReportFlags report_flag) |
793 | 0 | { |
794 | 0 | if (report_flag == FWUPD_REPORT_FLAG_NONE) |
795 | 0 | return "none"; |
796 | 0 | if (report_flag == FWUPD_REPORT_FLAG_FROM_OEM) |
797 | 0 | return "from-oem"; |
798 | 0 | if (report_flag == FWUPD_REPORT_FLAG_IS_UPGRADE) |
799 | 0 | return "is-upgrade"; |
800 | 0 | return NULL; |
801 | 0 | } |
802 | | |
803 | | /** |
804 | | * fwupd_report_flag_from_string: |
805 | | * @report_flag: (nullable): a string, e.g. `from-oem` |
806 | | * |
807 | | * Converts a string to an enumerated report flag. |
808 | | * |
809 | | * Returns: enumerated value |
810 | | * |
811 | | * Since: 1.9.1 |
812 | | **/ |
813 | | FwupdReportFlags |
814 | | fwupd_report_flag_from_string(const gchar *report_flag) |
815 | 0 | { |
816 | 0 | if (g_strcmp0(report_flag, "none") == 0) |
817 | 0 | return FWUPD_REPORT_FLAG_NONE; |
818 | 0 | if (g_strcmp0(report_flag, "from-oem") == 0) |
819 | 0 | return FWUPD_REPORT_FLAG_FROM_OEM; |
820 | 0 | if (g_strcmp0(report_flag, "is-upgrade") == 0) |
821 | 0 | return FWUPD_REPORT_FLAG_IS_UPGRADE; |
822 | 0 | return FWUPD_REPORT_FLAG_UNKNOWN; |
823 | 0 | } |
824 | | |
825 | | static void |
826 | | fwupd_report_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) |
827 | 0 | { |
828 | 0 | FwupdReport *self = FWUPD_REPORT(object); |
829 | 0 | FwupdReportPrivate *priv = GET_PRIVATE(self); |
830 | 0 | switch (prop_id) { |
831 | 0 | case PROP_FLAGS: |
832 | 0 | g_value_set_uint64(value, priv->flags); |
833 | 0 | break; |
834 | 0 | default: |
835 | 0 | G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); |
836 | 0 | break; |
837 | 0 | } |
838 | 0 | } |
839 | | |
840 | | static void |
841 | | fwupd_report_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) |
842 | 0 | { |
843 | 0 | FwupdReport *self = FWUPD_REPORT(object); |
844 | 0 | switch (prop_id) { |
845 | 0 | case PROP_FLAGS: |
846 | 0 | fwupd_report_set_flags(self, g_value_get_uint64(value)); |
847 | 0 | break; |
848 | 0 | default: |
849 | 0 | G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); |
850 | 0 | break; |
851 | 0 | } |
852 | 0 | } |
853 | | |
854 | | static void |
855 | | fwupd_report_init(FwupdReport *self) |
856 | 0 | { |
857 | 0 | FwupdReportPrivate *priv = GET_PRIVATE(self); |
858 | 0 | priv->metadata = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); |
859 | 0 | } |
860 | | |
861 | | static void |
862 | | fwupd_report_finalize(GObject *object) |
863 | 0 | { |
864 | 0 | FwupdReport *self = FWUPD_REPORT(object); |
865 | 0 | FwupdReportPrivate *priv = GET_PRIVATE(self); |
866 | |
|
867 | 0 | g_free(priv->vendor); |
868 | 0 | g_free(priv->device_name); |
869 | 0 | g_free(priv->distro_id); |
870 | 0 | g_free(priv->distro_version); |
871 | 0 | g_free(priv->distro_variant); |
872 | 0 | g_free(priv->remote_id); |
873 | 0 | g_free(priv->version_old); |
874 | 0 | g_hash_table_unref(priv->metadata); |
875 | |
|
876 | 0 | G_OBJECT_CLASS(fwupd_report_parent_class)->finalize(object); |
877 | 0 | } |
878 | | |
879 | | static void |
880 | | fwupd_report_class_init(FwupdReportClass *klass) |
881 | 0 | { |
882 | 0 | GObjectClass *object_class = G_OBJECT_CLASS(klass); |
883 | 0 | GParamSpec *pspec; |
884 | |
|
885 | 0 | object_class->finalize = fwupd_report_finalize; |
886 | 0 | object_class->get_property = fwupd_report_get_property; |
887 | 0 | object_class->set_property = fwupd_report_set_property; |
888 | | |
889 | | /** |
890 | | * FwupdReport:flags: |
891 | | * |
892 | | * The report flags. |
893 | | * |
894 | | * Since: 1.9.1 |
895 | | */ |
896 | 0 | pspec = g_param_spec_uint64("flags", |
897 | 0 | NULL, |
898 | 0 | NULL, |
899 | 0 | FWUPD_REPORT_FLAG_NONE, |
900 | 0 | FWUPD_REPORT_FLAG_UNKNOWN, |
901 | 0 | FWUPD_REPORT_FLAG_NONE, |
902 | 0 | G_PARAM_READWRITE | G_PARAM_STATIC_NAME); |
903 | 0 | g_object_class_install_property(object_class, PROP_FLAGS, pspec); |
904 | 0 | } |
905 | | |
906 | | static void |
907 | | fwupd_report_from_variant_iter(FwupdCodec *codec, GVariantIter *iter) |
908 | 0 | { |
909 | 0 | FwupdReport *self = FWUPD_REPORT(codec); |
910 | 0 | GVariant *value; |
911 | 0 | const gchar *key; |
912 | 0 | while (g_variant_iter_next(iter, "{&sv}", &key, &value)) { |
913 | 0 | fwupd_report_from_key_value(self, key, value); |
914 | 0 | g_variant_unref(value); |
915 | 0 | } |
916 | 0 | } |
917 | | |
918 | | static void |
919 | | fwupd_report_codec_iface_init(FwupdCodecInterface *iface) |
920 | 0 | { |
921 | 0 | iface->add_string = fwupd_report_add_string; |
922 | 0 | iface->add_json = fwupd_report_add_json; |
923 | 0 | iface->add_variant = fwupd_report_add_variant; |
924 | 0 | iface->from_variant_iter = fwupd_report_from_variant_iter; |
925 | 0 | } |
926 | | |
927 | | /** |
928 | | * fwupd_report_new: |
929 | | * |
930 | | * Creates a new report. |
931 | | * |
932 | | * Returns: a new #FwupdReport |
933 | | * |
934 | | * Since: 1.8.8 |
935 | | **/ |
936 | | FwupdReport * |
937 | | fwupd_report_new(void) |
938 | 0 | { |
939 | 0 | FwupdReport *self; |
940 | 0 | self = g_object_new(FWUPD_TYPE_REPORT, NULL); |
941 | 0 | return FWUPD_REPORT(self); |
942 | 0 | } |