GCC Code Coverage Report


Directory: ./
File: libfprint/fp-print.c
Date: 2024-05-04 14:54:39
Exec Total Coverage
Lines: 297 321 92.5%
Functions: 25 26 96.2%
Branches: 110 178 61.8%

Line Branch Exec Source
1 /*
2 * FPrint Print handling
3 * Copyright (C) 2007 Daniel Drake <dsd@gentoo.org>
4 * Copyright (C) 2019 Benjamin Berg <bberg@redhat.com>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 #define FP_COMPONENT "print"
22
23 #include "fp-print-private.h"
24 #include "fpi-compat.h"
25 #include "fpi-log.h"
26
27 /**
28 * SECTION: fp-print
29 * @title: FpPrint
30 * @short_description: Fingerprint handling
31 *
32 * Interaction with prints and their storage.
33 */
34
35 /**
36 * SECTION: fpi-print
37 * @title: Internal FpPrint
38 * @short_description: Internal fingerprint handling routines
39 *
40 * Interaction with prints and their storage. See also the public
41 * #FpPrint routines.
42 */
43
44
4/5
✓ Branch 0 taken 71 times.
✓ Branch 1 taken 765882 times.
✓ Branch 2 taken 67 times.
✓ Branch 3 taken 71 times.
✗ Branch 4 not taken.
1532182 G_DEFINE_TYPE (FpPrint, fp_print, G_TYPE_INITIALLY_UNOWNED)
45
46 enum {
47 PROP_0,
48 PROP_DRIVER,
49 PROP_DEVICE_ID,
50 PROP_DEVICE_STORED,
51 PROP_IMAGE,
52
53 /* The following is metadata that is stored by default for each print.
54 * Drivers may make use of these during enrollment (e.g. to additionally store
55 * the metadata on the device). */
56 PROP_FINGER,
57 PROP_USERNAME,
58 PROP_DESCRIPTION,
59 PROP_ENROLL_DATE,
60
61 /* Private property*/
62 PROP_FPI_TYPE,
63 PROP_FPI_DATA,
64 PROP_FPI_PRINTS,
65 N_PROPS
66 };
67
68 static GParamSpec *properties[N_PROPS];
69
70 static void
71 5720 fp_print_finalize (GObject *object)
72 {
73 5720 FpPrint *self = (FpPrint *) object;
74
75
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 5687 times.
5720 g_clear_object (&self->image);
76
1/2
✓ Branch 0 taken 5720 times.
✗ Branch 1 not taken.
5720 g_clear_pointer (&self->device_id, g_free);
77
1/2
✓ Branch 0 taken 5720 times.
✗ Branch 1 not taken.
5720 g_clear_pointer (&self->driver, g_free);
78
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 5679 times.
5720 g_clear_pointer (&self->username, g_free);
79
2/2
✓ Branch 0 taken 62 times.
✓ Branch 1 taken 5658 times.
5720 g_clear_pointer (&self->description, g_free);
80
2/2
✓ Branch 0 taken 52 times.
✓ Branch 1 taken 5668 times.
5720 g_clear_pointer (&self->enroll_date, g_date_free);
81
2/2
✓ Branch 0 taken 5647 times.
✓ Branch 1 taken 73 times.
5720 g_clear_pointer (&self->data, g_variant_unref);
82
2/2
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 5677 times.
5720 g_clear_pointer (&self->prints, g_ptr_array_unref);
83
84 5720 G_OBJECT_CLASS (fp_print_parent_class)->finalize (object);
85 5720 }
86
87 static void
88 408 fp_print_get_property (GObject *object,
89 guint prop_id,
90 GValue *value,
91 GParamSpec *pspec)
92 {
93 408 FpPrint *self = FP_PRINT (object);
94
95
10/12
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 28 times.
✓ Branch 2 taken 28 times.
✓ Branch 3 taken 24 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 3 times.
✓ Branch 7 taken 1 times.
✓ Branch 8 taken 114 times.
✓ Branch 9 taken 180 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
408 switch (prop_id)
96 {
97 28 case PROP_DRIVER:
98 28 g_value_set_string (value, self->driver);
99 28 break;
100
101 28 case PROP_DEVICE_ID:
102 28 g_value_set_string (value, self->device_id);
103 28 break;
104
105 28 case PROP_DEVICE_STORED:
106 28 g_value_set_boolean (value, self->device_stored);
107 28 break;
108
109 24 case PROP_IMAGE:
110 24 g_value_set_object (value, self->image);
111 24 break;
112
113 1 case PROP_FINGER:
114 1 g_value_set_enum (value, self->finger);
115 1 break;
116
117 1 case PROP_USERNAME:
118 1 g_value_set_string (value, self->username);
119 1 break;
120
121 3 case PROP_DESCRIPTION:
122 3 g_value_set_string (value, self->description);
123 3 break;
124
125 1 case PROP_ENROLL_DATE:
126 1 g_value_set_boxed (value, self->enroll_date);
127 1 break;
128
129 114 case PROP_FPI_TYPE:
130 114 g_value_set_enum (value, self->type);
131 114 break;
132
133 180 case PROP_FPI_DATA:
134 180 g_value_set_variant (value, self->data);
135 180 break;
136
137 case PROP_FPI_PRINTS:
138 g_value_set_pointer (value, self->prints);
139 break;
140
141 default:
142 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
143 }
144 408 }
145
146 static void
147 22931 fp_print_set_property (GObject *object,
148 guint prop_id,
149 const GValue *value,
150 GParamSpec *pspec)
151 {
152 22931 FpPrint *self = FP_PRINT (object);
153
154
9/11
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 5728 times.
✓ Branch 2 taken 5728 times.
✓ Branch 3 taken 5728 times.
✓ Branch 4 taken 12 times.
✓ Branch 5 taken 12 times.
✓ Branch 6 taken 57 times.
✓ Branch 7 taken 12 times.
✓ Branch 8 taken 5647 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
22931 switch (prop_id)
155 {
156 7 case PROP_FPI_TYPE:
157 7 fpi_print_set_type (self, g_value_get_enum (value));
158 7 break;
159
160 5728 case PROP_DRIVER:
161 5728 self->driver = g_value_dup_string (value);
162 5728 break;
163
164 5728 case PROP_DEVICE_ID:
165 5728 self->device_id = g_value_dup_string (value);
166 5728 break;
167
168 5728 case PROP_DEVICE_STORED:
169 5728 self->device_stored = g_value_get_boolean (value);
170 5728 break;
171
172 12 case PROP_FINGER:
173 12 self->finger = g_value_get_enum (value);
174 12 break;
175
176 12 case PROP_USERNAME:
177
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 g_clear_pointer (&self->username, g_free);
178 12 self->username = g_value_dup_string (value);
179 12 break;
180
181 57 case PROP_DESCRIPTION:
182
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 g_clear_pointer (&self->description, g_free);
183 57 self->description = g_value_dup_string (value);
184 57 break;
185
186 12 case PROP_ENROLL_DATE:
187
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 g_clear_pointer (&self->enroll_date, g_date_free);
188 12 self->enroll_date = g_value_dup_boxed (value);
189 12 break;
190
191 5647 case PROP_FPI_DATA:
192
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5647 times.
5647 g_clear_pointer (&self->data, g_variant_unref);
193 5647 self->data = g_value_dup_variant (value);
194 5647 break;
195
196 case PROP_FPI_PRINTS:
197 g_clear_pointer (&self->prints, g_ptr_array_unref);
198 self->prints = g_value_get_pointer (value);
199 break;
200
201 default:
202 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
203 }
204 22931 }
205
206 static void
207 5728 fp_print_constructed (GObject *obj)
208 {
209 5728 FpPrint *self = FP_PRINT (obj);
210
211
1/2
✓ Branch 0 taken 5728 times.
✗ Branch 1 not taken.
5728 g_assert (self->driver != NULL);
212
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5728 times.
5728 g_assert (self->device_id != NULL);
213 5728 }
214
215 static void
216 67 fp_print_class_init (FpPrintClass *klass)
217 {
218 67 GObjectClass *object_class = G_OBJECT_CLASS (klass);
219
220 67 object_class->constructed = fp_print_constructed;
221 67 object_class->finalize = fp_print_finalize;
222 67 object_class->get_property = fp_print_get_property;
223 67 object_class->set_property = fp_print_set_property;
224
225 134 properties[PROP_DRIVER] =
226 67 g_param_spec_string ("driver",
227 "Driver",
228 "The name of the driver that created the print",
229 NULL,
230 G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
231
232 134 properties[PROP_DEVICE_ID] =
233 67 g_param_spec_string ("device-id",
234 "Device ID",
235 "Unique ID allowing to check if a device is compatible with the print",
236 NULL,
237 G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
238
239 134 properties[PROP_DEVICE_STORED] =
240 67 g_param_spec_boolean ("device-stored",
241 "Device Stored",
242 "Whether the print is a handle for data that is stored on the device",
243 FALSE,
244 G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
245
246 134 properties[PROP_IMAGE] =
247 67 g_param_spec_object ("image",
248 "Image",
249 "The image that was used for the print, only valid for newly enrolled prints on image based devices",
250 FP_TYPE_IMAGE,
251 G_PARAM_STATIC_STRINGS | G_PARAM_READABLE);
252
253 134 properties[PROP_FINGER] =
254 67 g_param_spec_enum ("finger",
255 "Finger",
256 "The enrolled finger",
257 FP_TYPE_FINGER,
258 FP_FINGER_UNKNOWN,
259 G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE);
260
261 134 properties[PROP_USERNAME] =
262 67 g_param_spec_string ("username",
263 "Username",
264 "The username that the enrolled print belongs to",
265 NULL,
266 G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE);
267
268 134 properties[PROP_DESCRIPTION] =
269 67 g_param_spec_string ("description",
270 "Description",
271 "A user defined description for the print",
272 NULL,
273 G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE);
274
275 134 properties[PROP_ENROLL_DATE] =
276 67 g_param_spec_boxed ("enroll-date",
277 "Enroll Date",
278 "The date of enrollment",
279 G_TYPE_DATE,
280 G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE);
281
282 /**
283 * FpPrint::fpi-type: (skip)
284 *
285 * This property is only for internal purposes.
286 *
287 * Stability: private
288 */
289 134 properties[PROP_FPI_TYPE] =
290 67 g_param_spec_enum ("fpi-type",
291 "Type",
292 "Private: The type of the print data",
293 FPI_TYPE_PRINT_TYPE,
294 FPI_PRINT_UNDEFINED,
295 G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
296
297 /**
298 * FpPrint::fpi-data: (skip)
299 *
300 * This property is only for internal purposes.
301 *
302 * Stability: private
303 */
304 134 properties[PROP_FPI_DATA] =
305 67 g_param_spec_variant ("fpi-data",
306 "Raw Data",
307 "The raw data for internal use only",
308 G_VARIANT_TYPE_ANY,
309 NULL,
310 G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE);
311
312 /**
313 * FpPrint::fpi-prints: (skip)
314 *
315 * This property is only for internal purposes.
316 *
317 * Stability: private
318 */
319 134 properties[PROP_FPI_PRINTS] =
320 67 g_param_spec_pointer ("fpi-prints",
321 "Prints",
322 "Prints for internal use only",
323 G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE);
324
325 67 g_object_class_install_properties (object_class, N_PROPS, properties);
326 67 }
327
328 static void
329 5728 fp_print_init (FpPrint *self)
330 {
331 5728 }
332
333 /**
334 * fp_print_new:
335 * @device: A #FpDevice
336 *
337 * Create a new #FpPrint. This is only useful to prepare an enrollment
338 * of a new print using fp_device_enroll(). For this you should first
339 * create a new print, fill in the relevant metadata, and then start
340 * enrollment.
341 *
342 * Returns: (transfer floating): A newly created #FpPrint
343 */
344 FpPrint *
345 5720 fp_print_new (FpDevice *device)
346 {
347
1/2
✓ Branch 0 taken 5720 times.
✗ Branch 1 not taken.
5720 g_return_val_if_fail (device, NULL);
348
349 5720 return g_object_new (FP_TYPE_PRINT,
350 "driver", fp_device_get_driver (device),
351 "device-id", fp_device_get_device_id (device),
352 NULL);
353 }
354
355 /**
356 * fp_print_get_driver:
357 * @print: A #FpPrint
358 *
359 * Returns the driver that the print was created for.
360 *
361 * Returns: (transfer none): The driver
362 */
363 const gchar *
364 6 fp_print_get_driver (FpPrint *print)
365 {
366
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 g_return_val_if_fail (FP_IS_PRINT (print), NULL);
367
368 6 return print->driver;
369 }
370
371 /**
372 * fp_print_get_device_id:
373 * @print: A #FpPrint
374 *
375 * Returns the device ID that the print was created for.
376 *
377 * Returns: (transfer none): The device ID
378 */
379 const gchar *
380 fp_print_get_device_id (FpPrint *print)
381 {
382 g_return_val_if_fail (FP_IS_PRINT (print), NULL);
383
384 return print->device_id;
385 }
386
387 /**
388 * fp_print_get_device_stored:
389 * @print: A #FpPrint
390 *
391 * Whether the print is actually stored on the device and this is
392 * just a handle to use that references the device stored data.
393 *
394 * Returns: Whether the print is stored on the device
395 */
396 gboolean
397 23 fp_print_get_device_stored (FpPrint *print)
398 {
399
1/2
✓ Branch 1 taken 23 times.
✗ Branch 2 not taken.
23 g_return_val_if_fail (FP_IS_PRINT (print), FALSE);
400
401 23 return print->device_stored;
402 }
403
404 /**
405 * fp_print_get_image:
406 * @print: A #FpPrint
407 *
408 * Returns the image that the print was created from, or %NULL
409 *
410 * Returns: (transfer none) (nullable): The #FpImage
411 */
412 FpImage *
413 5 fp_print_get_image (FpPrint *print)
414 {
415
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
5 g_return_val_if_fail (FP_IS_PRINT (print), NULL);
416
417 5 return print->image;
418 }
419
420 /**
421 * fp_print_get_finger:
422 * @print: A #FpPrint
423 *
424 * Returns the finger that the print was created for.
425 *
426 * Returns: The #FpFinger
427 */
428 FpFinger
429 66 fp_print_get_finger (FpPrint *print)
430 {
431
1/2
✓ Branch 1 taken 66 times.
✗ Branch 2 not taken.
66 g_return_val_if_fail (FP_IS_PRINT (print), FP_FINGER_UNKNOWN);
432
433 66 return print->finger;
434 }
435
436 /**
437 * fp_print_get_username:
438 * @print: A #FpPrint
439 *
440 * Returns the user defined username for the print.
441 *
442 * Returns: (transfer none) (nullable): The username
443 */
444 const gchar *
445 23 fp_print_get_username (FpPrint *print)
446 {
447
1/2
✓ Branch 1 taken 23 times.
✗ Branch 2 not taken.
23 g_return_val_if_fail (FP_IS_PRINT (print), NULL);
448
449 23 return print->username;
450 }
451
452 /**
453 * fp_print_get_description:
454 * @print: A #FpPrint
455 *
456 * Returns the user defined description for the print.
457 *
458 * Returns: (transfer none) (nullable): The description
459 */
460 const gchar *
461 1771 fp_print_get_description (FpPrint *print)
462 {
463
1/2
✓ Branch 1 taken 1771 times.
✗ Branch 2 not taken.
1771 g_return_val_if_fail (FP_IS_PRINT (print), NULL);
464
465 1771 return print->description;
466 }
467
468 /**
469 * fp_print_get_enroll_date:
470 * @print: A #FpPrint
471 *
472 * Returns the user defined enroll date for the print.
473 *
474 * Returns: (transfer none) (nullable): The #GDate
475 */
476 const GDate *
477 10 fp_print_get_enroll_date (FpPrint *print)
478 {
479
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 g_return_val_if_fail (FP_IS_PRINT (print), NULL);
480
481 10 return print->enroll_date;
482 }
483
484 /**
485 * fp_print_set_finger:
486 * @print: A #FpPrint
487 * @finger: The #FpFinger
488 *
489 * Set the finger that the print is for.
490 */
491 void
492 70 fp_print_set_finger (FpPrint *print,
493 FpFinger finger)
494 {
495
1/2
✓ Branch 1 taken 70 times.
✗ Branch 2 not taken.
70 g_return_if_fail (FP_IS_PRINT (print));
496
497 70 print->finger = finger;
498 70 g_object_notify_by_pspec (G_OBJECT (print), properties[PROP_FINGER]);
499 }
500
501 /**
502 * fp_print_set_username:
503 * @print: A #FpPrint
504 * @username: (transfer none): The new username
505 *
506 * Set the username for the print.
507 */
508 void
509 35 fp_print_set_username (FpPrint *print,
510 const gchar *username)
511 {
512
1/2
✓ Branch 1 taken 35 times.
✗ Branch 2 not taken.
35 g_return_if_fail (FP_IS_PRINT (print));
513
514
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 35 times.
35 g_clear_pointer (&print->username, g_free);
515
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 35 times.
35 print->username = g_strdup (username);
516 35 g_object_notify_by_pspec (G_OBJECT (print), properties[PROP_USERNAME]);
517 }
518
519 /**
520 * fp_print_set_description:
521 * @print: A #FpPrint
522 * @description: (transfer none): The new description
523 *
524 * Set the description for the print.
525 */
526 void
527 6 fp_print_set_description (FpPrint *print,
528 const gchar *description)
529 {
530
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 g_return_if_fail (FP_IS_PRINT (print));
531
532
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 g_clear_pointer (&print->description, g_free);
533
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 print->description = g_strdup (description);
534 6 g_object_notify_by_pspec (G_OBJECT (print), properties[PROP_DESCRIPTION]);
535 }
536
537 /**
538 * fp_print_set_enroll_date:
539 * @print: A #FpPrint
540 * @enroll_date: (transfer none): The new enroll date
541 *
542 * Set the enroll date for the print.
543 */
544 void
545 40 fp_print_set_enroll_date (FpPrint *print,
546 const GDate *enroll_date)
547 {
548
1/2
✓ Branch 1 taken 40 times.
✗ Branch 2 not taken.
40 g_return_if_fail (FP_IS_PRINT (print));
549
550
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
40 g_clear_pointer (&print->enroll_date, g_date_free);
551
1/2
✓ Branch 0 taken 40 times.
✗ Branch 1 not taken.
40 if (enroll_date)
552 40 print->enroll_date = g_date_copy (enroll_date);
553
554 40 g_object_notify_by_pspec (G_OBJECT (print), properties[PROP_ENROLL_DATE]);
555 }
556
557 /**
558 * fp_print_compatible:
559 * @self: A #FpPrint
560 * @device: A #FpDevice
561 *
562 * Tests whether the prints is compatible with the given device.
563 *
564 * Returns: %TRUE if the print is compatible with the device
565 */
566 gboolean
567 4 fp_print_compatible (FpPrint *self, FpDevice *device)
568 {
569
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 g_return_val_if_fail (FP_IS_PRINT (self), FALSE);
570
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 g_return_val_if_fail (FP_IS_DEVICE (device), FALSE);
571
572
2/2
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 3 times.
4 if (g_strcmp0 (self->driver, fp_device_get_driver (device)))
573 return FALSE;
574
575
2/2
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 2 times.
3 if (g_strcmp0 (self->device_id, fp_device_get_device_id (device)))
576 return FALSE;
577
578 return TRUE;
579 }
580
581 /**
582 * fp_print_equal:
583 * @self: First #FpPrint
584 * @other: Second #FpPrint
585 *
586 * Tests whether the prints can be considered equal. This only compares the
587 * actual information about the print, not the metadata.
588 *
589 * Returns: %TRUE if the prints are equal
590 */
591 gboolean
592 375824 fp_print_equal (FpPrint *self, FpPrint *other)
593 {
594
1/2
✓ Branch 1 taken 375824 times.
✗ Branch 2 not taken.
375824 g_return_val_if_fail (FP_IS_PRINT (self), FALSE);
595
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 375824 times.
375824 g_return_val_if_fail (FP_IS_PRINT (other), FALSE);
596
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 375824 times.
375824 g_return_val_if_fail (self->type != FPI_PRINT_UNDEFINED, FALSE);
597
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 375824 times.
375824 g_return_val_if_fail (other->type != FPI_PRINT_UNDEFINED, FALSE);
598
599
1/2
✓ Branch 0 taken 375824 times.
✗ Branch 1 not taken.
375824 if (self->type != other->type)
600 return FALSE;
601
602
1/2
✓ Branch 1 taken 375824 times.
✗ Branch 2 not taken.
375824 if (g_strcmp0 (self->driver, other->driver))
603 return FALSE;
604
605
1/2
✓ Branch 1 taken 375824 times.
✗ Branch 2 not taken.
375824 if (g_strcmp0 (self->device_id, other->device_id))
606 return FALSE;
607
608
2/2
✓ Branch 0 taken 375823 times.
✓ Branch 1 taken 1 times.
375824 if (self->type == FPI_PRINT_RAW)
609 {
610 375823 return g_variant_equal (self->data, other->data);
611 }
612
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 else if (self->type == FPI_PRINT_NBIS)
613 {
614 1 guint i;
615
616
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (self->prints->len != other->prints->len)
617 return FALSE;
618
619
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 1 times.
6 for (i = 0; i < self->prints->len; i++)
620 {
621 5 struct xyt_struct *a = g_ptr_array_index (self->prints, i);
622 5 struct xyt_struct *b = g_ptr_array_index (other->prints, i);
623
624
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (memcmp (a, b, sizeof (struct xyt_struct)) != 0)
625 return FALSE;
626 }
627
628 return TRUE;
629 }
630 else
631 {
632 g_assert_not_reached ();
633 }
634 }
635
636 #define FPI_PRINT_VARIANT_TYPE G_VARIANT_TYPE ("(issbymsmsia{sv}v)")
637
638 G_STATIC_ASSERT (sizeof (((struct xyt_struct *) NULL)->xcol[0]) == 4);
639
640 /**
641 * fp_print_serialize:
642 * @print: A #FpPrint
643 * @data: (array length=length) (transfer full) (out): Return location for data pointer
644 * @length: (transfer full) (out): Length of @data
645 * @error: Return location for error
646 *
647 * Serialize a print definition for permanent storage. Note that this is
648 * lossy in the sense that e.g. the image data is discarded.
649 *
650 * Returns: (type void): %TRUE on success
651 */
652 gboolean
653 8 fp_print_serialize (FpPrint *print,
654 guchar **data,
655 gsize *length,
656 GError **error)
657 {
658 16 g_autoptr(GVariant) result = NULL;
659 8 GVariantBuilder builder = G_VARIANT_BUILDER_INIT (FPI_PRINT_VARIANT_TYPE);
660 8 gsize len;
661
662
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 g_assert (data);
663
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 g_assert (length);
664
665 8 g_variant_builder_add (&builder, "i", print->type);
666 8 g_variant_builder_add (&builder, "s", print->driver);
667 8 g_variant_builder_add (&builder, "s", print->device_id);
668 8 g_variant_builder_add (&builder, "b", print->device_stored);
669
670 /* Metadata */
671 8 g_variant_builder_add (&builder, "y", print->finger);
672 8 g_variant_builder_add (&builder, "ms", print->username);
673 8 g_variant_builder_add (&builder, "ms", print->description);
674
3/4
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 7 times.
8 if (print->enroll_date && g_date_valid (print->enroll_date))
675 1 g_variant_builder_add (&builder, "i", g_date_get_julian (print->enroll_date));
676 else
677 7 g_variant_builder_add (&builder, "i", G_MININT32);
678
679 /* Unused a{sv} for expansion */
680 8 g_variant_builder_open (&builder, G_VARIANT_TYPE_VARDICT);
681 8 g_variant_builder_close (&builder);
682
683 /* Insert NBIS print data for type NBIS, otherwise the GVariant directly */
684
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 7 times.
8 if (print->type == FPI_PRINT_NBIS)
685 {
686 1 GVariantBuilder nested = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE ("(a(aiaiai))"));
687 1 guint i;
688
689 1 g_variant_builder_open (&nested, G_VARIANT_TYPE ("a(aiaiai)"));
690
2/2
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 1 times.
7 for (i = 0; i < print->prints->len; i++)
691 {
692 5 struct xyt_struct *xyt = g_ptr_array_index (print->prints, i);
693
694 5 g_variant_builder_open (&nested, G_VARIANT_TYPE ("(aiaiai)"));
695
696 5 g_variant_builder_add_value (&nested,
697 g_variant_new_fixed_array (G_VARIANT_TYPE_INT32,
698 5 xyt->xcol,
699 5 xyt->nrows,
700 sizeof (xyt->xcol[0])));
701 5 g_variant_builder_add_value (&nested,
702 g_variant_new_fixed_array (G_VARIANT_TYPE_INT32,
703 5 xyt->ycol,
704 5 xyt->nrows,
705 sizeof (xyt->ycol[0])));
706 5 g_variant_builder_add_value (&nested,
707 g_variant_new_fixed_array (G_VARIANT_TYPE_INT32,
708 5 xyt->thetacol,
709 5 xyt->nrows,
710 sizeof (xyt->thetacol[0])));
711 5 g_variant_builder_close (&nested);
712 }
713
714 1 g_variant_builder_close (&nested);
715 1 g_variant_builder_add (&builder, "v", g_variant_builder_end (&nested));
716 }
717 else
718 {
719 7 g_variant_builder_add (&builder, "v", g_variant_new_variant (print->data));
720 }
721
722 8 result = g_variant_builder_end (&builder);
723
724 #if (G_BYTE_ORDER == G_BIG_ENDIAN)
725 GVariant *tmp;
726 tmp = g_variant_byteswap (result);
727 g_variant_unref (result);
728 result = tmp;
729 #endif
730
731 8 len = g_variant_get_size (result);
732 /* Add 3 bytes of header */
733 8 len += 3;
734
735 8 *data = g_malloc (len);
736 8 *length = len;
737
738 8 (*data)[0] = (guchar) 'F';
739 8 (*data)[1] = (guchar) 'P';
740 8 (*data)[2] = (guchar) '3';
741
742 8 g_variant_get_data (result);
743 8 g_variant_store (result, (*data) + 3);
744
745
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 return TRUE;
746 }
747
748 /**
749 * fp_print_deserialize:
750 * @data: (array length=length): The binary data
751 * @length: Length of the data
752 * @error: Return location for error
753 *
754 * Deserialize a print definition from permanent storage.
755 *
756 * Returns: (transfer full): A newly created #FpPrint on success
757 */
758 FpPrint *
759 8 fp_print_deserialize (const guchar *data,
760 gsize length,
761 GError **error)
762 {
763 16 g_autoptr(FpPrint) result = NULL;
764
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 g_autoptr(GVariant) raw_value = NULL;
765
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 g_autoptr(GVariant) value = NULL;
766
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 g_autoptr(GVariant) print_data = NULL;
767
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 g_autoptr(GDate) date = NULL;
768 8 guchar *aligned_data = NULL;
769 8 guint8 finger_int8;
770 8 FpFinger finger;
771
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 g_autofree gchar *username = NULL;
772 8 g_autofree gchar *description = NULL;
773 8 gint julian_date;
774 8 FpiPrintType type;
775 8 const gchar *driver;
776 8 const gchar *device_id;
777 8 gboolean device_stored;
778
779
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 g_assert (data);
780
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 g_assert (length > 3);
781
782
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (memcmp (data, "FP3", 3) != 0)
783 goto invalid_format;
784
785 /* NOTE:
786 * We make sure that we have no variant left over from the parsing at the end
787 * of this function (meaning we don't need to keep the data around.
788 */
789
790 /* To support GLIB < 2.60 we need to make sure that the memory is aligned correctly.
791 * We also need to copy the backing store for the raw data that we may keep for
792 * longer. */
793 8 aligned_data = g_malloc (length - 3);
794 8 memcpy (aligned_data, data + 3, length - 3);
795 8 raw_value = g_variant_new_from_data (FPI_PRINT_VARIANT_TYPE,
796 aligned_data, length - 3,
797 FALSE, g_free, aligned_data);
798
799
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (!raw_value)
800 goto invalid_format;
801
802 #if (G_BYTE_ORDER == G_BIG_ENDIAN)
803 value = g_variant_byteswap (raw_value);
804 #else
805 8 value = g_variant_get_normal_form (raw_value);
806 #endif
807
808 8 g_variant_get (value,
809 "(i&s&sbymsmsi@a{sv}v)",
810 &type,
811 &driver,
812 &device_id,
813 &device_stored,
814 &finger_int8,
815 &username,
816 &description,
817 &julian_date,
818 NULL,
819 &print_data);
820
821 8 finger = finger_int8;
822
823 /* Assume data is valid at this point if the values are somewhat sane. */
824
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 7 times.
8 if (type == FPI_PRINT_NBIS)
825 {
826 1 g_autoptr(GVariant) prints = g_variant_get_child_value (print_data, 0);
827 1 guint i;
828
829 1 result = g_object_new (FP_TYPE_PRINT,
830 "driver", driver,
831 "device-id", device_id,
832 "device-stored", device_stored,
833 NULL);
834 1 g_object_ref_sink (result);
835 1 fpi_print_set_type (result, FPI_PRINT_NBIS);
836
2/2
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 1 times.
7 for (i = 0; i < g_variant_n_children (prints); i++)
837 {
838
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
5 g_autofree struct xyt_struct *xyt = NULL;
839 5 const gint32 *xcol, *ycol, *thetacol;
840 5 gsize xlen, ylen, thetalen;
841 5 g_autoptr(GVariant) xyt_data = NULL;
842 5 GVariant *child;
843
844 5 xyt_data = g_variant_get_child_value (prints, i);
845
846 5 child = g_variant_get_child_value (xyt_data, 0);
847 5 xcol = g_variant_get_fixed_array (child, &xlen, sizeof (gint32));
848 5 g_variant_unref (child);
849
850 5 child = g_variant_get_child_value (xyt_data, 1);
851 5 ycol = g_variant_get_fixed_array (child, &ylen, sizeof (gint32));
852 5 g_variant_unref (child);
853
854 5 child = g_variant_get_child_value (xyt_data, 2);
855 5 thetacol = g_variant_get_fixed_array (child, &thetalen, sizeof (gint32));
856 5 g_variant_unref (child);
857
858
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
5 if (xlen != ylen || xlen != thetalen)
859 goto invalid_format;
860
861
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (xlen > G_N_ELEMENTS (xyt->xcol))
862 goto invalid_format;
863
864 5 xyt = g_new0 (struct xyt_struct, 1);
865 5 xyt->nrows = xlen;
866 5 memcpy (xyt->xcol, xcol, sizeof (xcol[0]) * xlen);
867 5 memcpy (xyt->ycol, ycol, sizeof (xcol[0]) * xlen);
868 5 memcpy (xyt->thetacol, thetacol, sizeof (xcol[0]) * xlen);
869
870
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
5 g_ptr_array_add (result->prints, g_steal_pointer (&xyt));
871 }
872 }
873
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 else if (type == FPI_PRINT_RAW)
874 {
875 7 g_autoptr(GVariant) fp_data = g_variant_get_child_value (print_data, 0);
876
877 7 result = g_object_new (FP_TYPE_PRINT,
878 "fpi-type", type,
879 "driver", driver,
880 "device-id", device_id,
881 "device-stored", device_stored,
882 "fpi-data", fp_data,
883 NULL);
884
1/2
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
7 g_object_ref_sink (result);
885 }
886 else
887 {
888 g_warning ("Invalid print type: 0x%X", type);
889 goto invalid_format;
890 }
891
892 8 date = g_date_new_julian (julian_date);
893 8 g_object_set (result,
894 "finger", finger,
895 "username", username,
896 "description", description,
897 "enroll_date", date,
898 NULL);
899
900 8 return g_steal_pointer (&result);
901
902 invalid_format:
903 g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA,
904 "Data could not be parsed");
905 return NULL;
906 }
907