Greenbone Vulnerability Management Libraries 22.12.2
cpeutils.c
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2009-2024 Greenbone AG
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later
4 */
5
18#include "cpeutils.h"
19
20#include <assert.h>
21#include <ctype.h>
22#include <errno.h>
23#include <glib.h>
24#include <string.h>
25
26#undef G_LOG_DOMAIN
30#define G_LOG_DOMAIN "libgvm util"
31
32static enum set_relation
33compare_component (const char *, const char *);
34
35static enum set_relation
36compare_strings (const char *, const char *);
37
38static int
39count_escapes (const char *, int, int);
40
41static gboolean
42is_even_wildcards (const char *, int);
43
44static gboolean
45has_wildcards (const char *);
46
47static int
48index_of (const char *, const char *, int);
49
50static gboolean
51is_string (const char *);
52
53static char *
54get_uri_component (const char *, int);
55
56static char *
57decode_uri_component (const char *);
58
59static void
61
62static char *
63get_fs_component (const char *, int);
64
65static char *
66unbind_fs_component (char *);
67
68static char *
69add_quoting (const char *);
70
71static char *
72bind_cpe_component_for_uri (const char *);
73
74static char *
75transform_for_uri (const char *);
76
77static char *
79
80static char *
81bind_cpe_component_for_fs (const char *);
82
83static char *
84process_quoted_chars (const char *);
85
86static void
87trim_pct (char *);
88
89static void
90get_code (char *, const char *);
91
92static void
93str_cpy (char **, const char *, int);
94
102char *
103uri_cpe_to_fs_cpe (const char *uri_cpe)
104{
105 cpe_struct_t cpe;
106 char *fs_cpe;
107
108 cpe_struct_init (&cpe);
109 uri_cpe_to_cpe_struct (uri_cpe, &cpe);
110 fs_cpe = cpe_struct_to_fs_cpe (&cpe);
111 cpe_struct_free (&cpe);
112 return (fs_cpe);
113}
114
122char *
123uri_cpe_to_fs_product (const char *uri_cpe)
124{
125 cpe_struct_t cpe;
126 char *fs_cpe;
127
128 cpe_struct_init (&cpe);
129 uri_cpe_to_cpe_struct (uri_cpe, &cpe);
130 fs_cpe = cpe_struct_to_fs_product (&cpe);
131 cpe_struct_free (&cpe);
132 return (fs_cpe);
133}
134
142char *
143fs_cpe_to_uri_cpe (const char *fs_cpe)
144{
145 cpe_struct_t cpe;
146 char *uri_cpe;
147
148 cpe_struct_init (&cpe);
149 fs_cpe_to_cpe_struct (fs_cpe, &cpe);
150 uri_cpe = cpe_struct_to_uri_cpe (&cpe);
151 cpe_struct_free (&cpe);
152 return (uri_cpe);
153}
154
162char *
163fs_cpe_to_uri_product (const char *fs_cpe)
164{
165 cpe_struct_t cpe;
166 char *uri_cpe;
167
168 cpe_struct_init (&cpe);
169 fs_cpe_to_cpe_struct (fs_cpe, &cpe);
170 uri_cpe = cpe_struct_to_uri_product (&cpe);
171 cpe_struct_free (&cpe);
172 return (uri_cpe);
173}
174
182void
183uri_cpe_to_cpe_struct (const char *uri_cpe, cpe_struct_t *cpe)
184{
185 char *uri_component;
186
187 uri_component = get_uri_component (uri_cpe, 1);
188 cpe->part = decode_uri_component (uri_component);
189 g_free (uri_component);
190 uri_component = get_uri_component (uri_cpe, 2);
191 cpe->vendor = decode_uri_component (uri_component);
192 g_free (uri_component);
193 uri_component = get_uri_component (uri_cpe, 3);
194 cpe->product = decode_uri_component (uri_component);
195 g_free (uri_component);
196 uri_component = get_uri_component (uri_cpe, 4);
197 cpe->version = decode_uri_component (uri_component);
198 g_free (uri_component);
199 uri_component = get_uri_component (uri_cpe, 5);
200 cpe->update = decode_uri_component (uri_component);
201 g_free (uri_component);
202 uri_component = get_uri_component (uri_cpe, 6);
203 if (strcmp (uri_component, "") == 0 || strcmp (uri_component, "-") == 0
204 || *uri_component != '~')
205 cpe->edition = decode_uri_component (uri_component);
206 else
207 unpack_sixth_uri_component (uri_component, cpe);
208 g_free (uri_component);
209
210 uri_component = get_uri_component (uri_cpe, 7);
211 cpe->language = decode_uri_component (uri_component);
212 g_free (uri_component);
213}
214
222char *
224{
225 GString *uri_cpe;
226 char *bind_cpe_component;
227 uri_cpe = g_string_new ("cpe:/");
228
229 bind_cpe_component = bind_cpe_component_for_uri (cpe->part);
230 if (bind_cpe_component)
231 {
232 g_string_append_printf (uri_cpe, "%s:", bind_cpe_component);
233 g_free (bind_cpe_component);
234 }
235 bind_cpe_component = bind_cpe_component_for_uri (cpe->vendor);
236 if (bind_cpe_component)
237 {
238 g_string_append_printf (uri_cpe, "%s:", bind_cpe_component);
239 g_free (bind_cpe_component);
240 }
241 bind_cpe_component = bind_cpe_component_for_uri (cpe->product);
242 if (bind_cpe_component)
243 {
244 g_string_append_printf (uri_cpe, "%s:", bind_cpe_component);
245 g_free (bind_cpe_component);
246 }
247 bind_cpe_component = bind_cpe_component_for_uri (cpe->version);
248 if (bind_cpe_component)
249 {
250 g_string_append_printf (uri_cpe, "%s:", bind_cpe_component);
251 g_free (bind_cpe_component);
252 }
253 bind_cpe_component = bind_cpe_component_for_uri (cpe->update);
254 if (bind_cpe_component)
255 {
256 g_string_append_printf (uri_cpe, "%s:", bind_cpe_component);
257 g_free (bind_cpe_component);
258 }
259 bind_cpe_component = pack_sixth_uri_component (cpe);
260 if (bind_cpe_component)
261 {
262 g_string_append_printf (uri_cpe, "%s:", bind_cpe_component);
263 g_free (bind_cpe_component);
264 }
265 bind_cpe_component = bind_cpe_component_for_uri (cpe->language);
266 if (bind_cpe_component)
267 {
268 g_string_append_printf (uri_cpe, "%s:", bind_cpe_component);
269 g_free (bind_cpe_component);
270 }
271
272 char *result = g_string_free (uri_cpe, FALSE);
273 trim_pct (result);
274 return (result);
275}
276
284char *
286{
287 GString *uri_cpe;
288 char *bind_cpe_component;
289 uri_cpe = g_string_new ("cpe:/");
290
291 bind_cpe_component = bind_cpe_component_for_uri (cpe->part);
292 if (bind_cpe_component)
293 {
294 g_string_append_printf (uri_cpe, "%s:", bind_cpe_component);
295 g_free (bind_cpe_component);
296 }
297 bind_cpe_component = bind_cpe_component_for_uri (cpe->vendor);
298 if (bind_cpe_component)
299 {
300 g_string_append_printf (uri_cpe, "%s:", bind_cpe_component);
301 g_free (bind_cpe_component);
302 }
303 bind_cpe_component = bind_cpe_component_for_uri (cpe->product);
304 if (bind_cpe_component)
305 {
306 g_string_append_printf (uri_cpe, "%s:", bind_cpe_component);
307 g_free (bind_cpe_component);
308 }
309
310 char *result = g_string_free (uri_cpe, FALSE);
311 trim_pct (result);
312 return (result);
313}
314
322void
323fs_cpe_to_cpe_struct (const char *fs_cpe, cpe_struct_t *cpe)
324{
325 char *fs_component;
326
327 fs_component = get_fs_component (fs_cpe, 2);
328 cpe->part = unbind_fs_component (fs_component);
329 fs_component = get_fs_component (fs_cpe, 3);
330 cpe->vendor = unbind_fs_component (fs_component);
331 g_free (fs_component);
332 fs_component = get_fs_component (fs_cpe, 4);
333 cpe->product = unbind_fs_component (fs_component);
334 g_free (fs_component);
335 fs_component = get_fs_component (fs_cpe, 5);
336 cpe->version = unbind_fs_component (fs_component);
337 g_free (fs_component);
338 fs_component = get_fs_component (fs_cpe, 6);
339 cpe->update = unbind_fs_component (fs_component);
340 g_free (fs_component);
341 fs_component = get_fs_component (fs_cpe, 7);
342 cpe->edition = unbind_fs_component (fs_component);
343 g_free (fs_component);
344 fs_component = get_fs_component (fs_cpe, 8);
345 cpe->language = unbind_fs_component (fs_component);
346 g_free (fs_component);
347 fs_component = get_fs_component (fs_cpe, 9);
348 cpe->sw_edition = unbind_fs_component (fs_component);
349 g_free (fs_component);
350 fs_component = get_fs_component (fs_cpe, 10);
351 cpe->target_sw = unbind_fs_component (fs_component);
352 g_free (fs_component);
353 fs_component = get_fs_component (fs_cpe, 11);
354 cpe->target_hw = unbind_fs_component (fs_component);
355 g_free (fs_component);
356 fs_component = get_fs_component (fs_cpe, 12);
357 cpe->other = unbind_fs_component (fs_component);
358 g_free (fs_component);
359}
360
368char *
370{
371 GString *fs_cpe;
372 char *bind_cpe_component;
373
374 fs_cpe = g_string_new ("cpe:2.3:");
375
376 bind_cpe_component = bind_cpe_component_for_fs (cpe->part);
377 if (bind_cpe_component)
378 {
379 g_string_append_printf (fs_cpe, "%s:", bind_cpe_component);
380 g_free (bind_cpe_component);
381 }
382 bind_cpe_component = bind_cpe_component_for_fs (cpe->vendor);
383 if (bind_cpe_component)
384 {
385 g_string_append_printf (fs_cpe, "%s:", bind_cpe_component);
386 g_free (bind_cpe_component);
387 }
388 bind_cpe_component = bind_cpe_component_for_fs (cpe->product);
389 if (bind_cpe_component)
390 {
391 g_string_append_printf (fs_cpe, "%s:", bind_cpe_component);
392 g_free (bind_cpe_component);
393 }
394 bind_cpe_component = bind_cpe_component_for_fs (cpe->version);
395 if (bind_cpe_component)
396 {
397 g_string_append_printf (fs_cpe, "%s:", bind_cpe_component);
398 g_free (bind_cpe_component);
399 }
400 bind_cpe_component = bind_cpe_component_for_fs (cpe->update);
401 if (bind_cpe_component)
402 {
403 g_string_append_printf (fs_cpe, "%s:", bind_cpe_component);
404 g_free (bind_cpe_component);
405 }
406 bind_cpe_component = bind_cpe_component_for_fs (cpe->edition);
407 if (bind_cpe_component)
408 {
409 g_string_append_printf (fs_cpe, "%s:", bind_cpe_component);
410 g_free (bind_cpe_component);
411 }
412 bind_cpe_component = bind_cpe_component_for_fs (cpe->language);
413 if (bind_cpe_component)
414 {
415 g_string_append_printf (fs_cpe, "%s:", bind_cpe_component);
416 g_free (bind_cpe_component);
417 }
418 bind_cpe_component = bind_cpe_component_for_fs (cpe->sw_edition);
419 if (bind_cpe_component)
420 {
421 g_string_append_printf (fs_cpe, "%s:", bind_cpe_component);
422 g_free (bind_cpe_component);
423 }
424 bind_cpe_component = bind_cpe_component_for_fs (cpe->target_sw);
425 if (bind_cpe_component)
426 {
427 g_string_append_printf (fs_cpe, "%s:", bind_cpe_component);
428 g_free (bind_cpe_component);
429 }
430 bind_cpe_component = bind_cpe_component_for_fs (cpe->target_hw);
431 if (bind_cpe_component)
432 {
433 g_string_append_printf (fs_cpe, "%s:", bind_cpe_component);
434 g_free (bind_cpe_component);
435 }
436 bind_cpe_component = bind_cpe_component_for_fs (cpe->other);
437 if (bind_cpe_component)
438 {
439 g_string_append_printf (fs_cpe, "%s", bind_cpe_component);
440 g_free (bind_cpe_component);
441 }
442 return (g_string_free (fs_cpe, FALSE));
443}
444
452char *
454{
455 GString *fs_cpe;
456 char *bind_cpe_component;
457
458 fs_cpe = g_string_new ("cpe:2.3:");
459
460 bind_cpe_component = bind_cpe_component_for_fs (cpe->part);
461 if (bind_cpe_component)
462 {
463 g_string_append_printf (fs_cpe, "%s:", bind_cpe_component);
464 g_free (bind_cpe_component);
465 }
466 bind_cpe_component = bind_cpe_component_for_fs (cpe->vendor);
467 if (bind_cpe_component)
468 {
469 g_string_append_printf (fs_cpe, "%s:", bind_cpe_component);
470 g_free (bind_cpe_component);
471 }
472 bind_cpe_component = bind_cpe_component_for_fs (cpe->product);
473 if (bind_cpe_component)
474 {
475 g_string_append_printf (fs_cpe, "%s:", bind_cpe_component);
476 g_free (bind_cpe_component);
477 }
478 return (g_string_free (fs_cpe, FALSE));
479}
480
489static char *
490get_uri_component (const char *uri_cpe, int index)
491{
492 char *component = NULL;
493 char *c;
494 char *component_start, *component_end;
495
496 if (!uri_cpe)
497 return NULL;
498
499 c = (char *) uri_cpe;
500
501 /* find start of component */
502 for (int i = 0; *c != '\0' && i < index; c++)
503 {
504 if (*c == ':')
505 i++;
506 }
507
508 if (index == 1 && *c != '\0')
509 c++;
510
511 component_start = c;
512
513 /* find end of component */
514 if (*component_start == '\0')
515 component_end = component_start;
516 else
517 {
518 for (c = component_start; *c != '\0' && *c != ':'; c++)
519 ;
520 }
521
522 component_end = c;
523
524 if (component_start >= component_end || component_end == 0)
525 component = (char *) g_strdup ("");
526 else
527 str_cpy (&component, component_start, component_end - component_start);
528
529 return component;
530}
531
539static char *
540decode_uri_component (const char *component)
541{
542 GString *decoded_component;
543 char *escapes = "!\"#$%&'()*+,/:;<=>?@[\\]^`{|}~";
544 char *tmp_component;
545 char code_a[4], code_b[4], code_c[4];
546 long unsigned int index;
547 gboolean embedded;
548
549 if (!component)
550 return (NULL);
551
552 if (strcmp (component, "") == 0 || strcmp (component, " ") == 0)
553 {
554 return (g_strdup ("ANY"));
555 }
556 if (strcmp (component, "-") == 0)
557 {
558 return (g_strdup ("NA"));
559 }
560
561 tmp_component = g_strdup (component);
562
563 /* set all characters to lowercase */
564 char *c = tmp_component;
565 for (; *c; c++)
566 *c = tolower (*c);
567
568 index = 0;
569 embedded = FALSE;
570 decoded_component = g_string_new ("");
571
572 char l;
573 char *unescaped;
574 while (index < strlen (tmp_component))
575 {
576 l = *(tmp_component + index);
577
578 if (l == '.' || l == '-' || l == '~')
579 {
580 g_string_append_printf (decoded_component, "\\%c", l);
581 index++;
582 embedded = TRUE;
583 continue;
584 }
585 if (l != '%')
586 {
587 g_string_append_printf (decoded_component, "%c", l);
588 index++;
589 embedded = TRUE;
590 continue;
591 }
592
593 get_code (code_a, tmp_component + index);
594
595 if (strcmp (code_a, "%01") == 0)
596 {
597 if (index >= 3)
598 get_code (code_b, tmp_component + index - 3);
599 else
600 code_b[0] = '0';
601 if (strlen (tmp_component) >= index + 6)
602 get_code (code_c, tmp_component + index + 3);
603 else
604 code_c[0] = '0';
605 if ((index == 0 || index == strlen (tmp_component) - 3)
606 || (!embedded && strcmp (code_b, "%01"))
607 || (embedded && strcmp (code_c, "%01")))
608 {
609 g_string_append_printf (decoded_component, "%c", '?');
610 index = index + 3;
611 continue;
612 }
613 else
614 {
615 g_string_free (decoded_component, TRUE);
616 g_free (tmp_component);
617 return (NULL);
618 }
619 }
620
621 if (strcmp (code_a, "%02") == 0)
622 {
623 if (index == 0 || index == strlen (tmp_component) - 3)
624 {
625 g_string_append_printf (decoded_component, "%c", '*');
626 index = index + 3;
627 continue;
628 }
629 else
630 {
631 g_string_free (decoded_component, TRUE);
632 g_free (tmp_component);
633 return (NULL);
634 }
635 }
636
637 unescaped = g_uri_unescape_string (code_a, NULL);
638 if (unescaped && strchr (escapes, *unescaped))
639 {
640 g_string_append_printf (decoded_component, "\\%s", unescaped);
641 g_free (unescaped);
642 }
643 else if (unescaped)
644 {
645 g_string_append_printf (decoded_component, "%s", unescaped);
646 g_free (unescaped);
647 }
648 else
649 {
650 g_string_free (decoded_component, TRUE);
651 g_free (tmp_component);
652 return (NULL);
653 }
654 index = index + 3;
655 embedded = TRUE;
656 }
657
658 g_free (tmp_component);
659 return (g_string_free (decoded_component, FALSE));
660}
661
670static void
671unpack_sixth_uri_component (const char *component, cpe_struct_t *cpe)
672{
673 const char *start = component + 1;
674 const char *end;
675
676 char *edition, *sw_edition, *target_sw, *target_hw, *other;
677
678 end = strchr (start, '~');
679 if (start >= end || end == NULL)
680 edition = strdup ("");
681 else
682 str_cpy (&edition, start, end - start);
683
684 if (end != NULL)
685 {
686 start = end + 1;
687 end = strchr (start, '~');
688 if (start >= end || end == NULL)
689 sw_edition = strdup ("");
690 else
691 str_cpy (&sw_edition, start, end - start);
692 }
693 else
694 sw_edition = strdup ("");
695
696 if (end != NULL)
697 {
698 start = end + 1;
699 end = strchr (start, '~');
700 if (start >= end || end == NULL)
701 target_sw = strdup ("");
702 else
703 str_cpy (&target_sw, start, end - start);
704 }
705 else
706 target_sw = strdup ("");
707
708 if (end != NULL)
709 {
710 start = end + 1;
711 end = strchr (start, '~');
712 if (start >= end || end == NULL)
713 target_hw = strdup ("");
714 else
715 str_cpy (&target_hw, start, end - start);
716 }
717 else
718 target_hw = strdup ("");
719
720 if (end != NULL)
721 {
722 start = end + 1;
723 end = component + strlen (component);
724 if (start >= end)
725 other = strdup ("");
726 else
727 str_cpy (&other, start, end - start);
728 }
729 else
730 other = strdup ("");
731
732 cpe->edition = decode_uri_component (edition);
733 g_free (edition);
734 cpe->sw_edition = decode_uri_component (sw_edition);
735 g_free (sw_edition);
736 cpe->target_sw = decode_uri_component (target_sw);
737 g_free (target_sw);
738 cpe->target_hw = decode_uri_component (target_hw);
739 g_free (target_hw);
740 cpe->other = decode_uri_component (other);
741 g_free (other);
742}
743
752static char *
753get_fs_component (const char *fs_cpe, int index)
754{
755 char *component = NULL;
756 char *c;
757 char *component_start, *component_end;
758
759 if (!fs_cpe)
760 return NULL;
761
762 if (*fs_cpe == '\0')
763 return ((char *) g_strdup (""));
764
765 c = (char *) fs_cpe;
766
767 /* find start of component */
768 if (index == 0)
769 component_start = c;
770 else
771 {
772 for (int i = 0; *c != '\0' && i < index; c++)
773 {
774 if (*c == ':' && c == fs_cpe)
775 i++;
776 else if (c > fs_cpe && *c == ':' && *(c - 1) != '\\')
777 i++;
778 }
779 component_start = c;
780 }
781
782 /* find end of component */
783 if (*component_start == '\0')
784 component_end = component_start;
785 else
786 {
787 for (c = component_start; *c != '\0' && *c != ':'; c++)
788 ;
789 }
790
791 component_end = c;
792
793 if (component_start >= component_end || component_end == NULL)
794 component = (char *) g_strdup ("");
795 else
796 str_cpy (&component, component_start, component_end - component_start);
797
798 return component;
799}
800
808static char *
809unbind_fs_component (char *component)
810{
811 if (strcmp (component, "*") == 0)
812 return ((char *) g_strdup ("ANY"));
813 if (strcmp (component, "-") == 0)
814 return ((char *) g_strdup ("NA"));
815 return (add_quoting (component));
816}
817
826static char *
827add_quoting (const char *component)
828{
829 GString *quoted_component;
830 char *tmp_component;
831 char *c;
832 gboolean embedded;
833
834 if (!component)
835 return (NULL);
836
837 quoted_component = g_string_new ("");
838 tmp_component = (char *) g_strdup (component);
839 embedded = FALSE;
840
841 /* set all characters to lowercase */
842 for (c = tmp_component; *c; c++)
843 *c = tolower (*c);
844
845 c = tmp_component;
846 while (*c != '\0')
847 {
848 if (g_ascii_isalnum (*c) || *c == '_')
849 {
850 g_string_append_printf (quoted_component, "%c", *c);
851 c++;
852 embedded = TRUE;
853 continue;
854 }
855 if (*c == '\\')
856 {
857 c++;
858 if (*c != '\0')
859 {
860 g_string_append_printf (quoted_component, "\\%c", *c);
861 embedded = TRUE;
862 c++;
863 continue;
864 }
865 }
866 if (*c == '*')
867 {
868 if ((c == tmp_component)
869 || (c == tmp_component + strlen (tmp_component - 1)))
870 {
871 g_string_append_printf (quoted_component, "%c", *c);
872 c++;
873 embedded = TRUE;
874 continue;
875 }
876 else
877 {
878 g_free (tmp_component);
879 return (NULL);
880 }
881 }
882 if (*c == '?')
883 {
884 if ((c == tmp_component)
885 || (c == tmp_component + strlen (tmp_component - 1))
886 || (!embedded && (c > tmp_component) && (*(c - 1) == '?'))
887 || (embedded && *(c + 1) == '?'))
888 {
889 g_string_append_printf (quoted_component, "%c", *c);
890 c++;
891 embedded = FALSE;
892 continue;
893 }
894 else
895 {
896 g_free (tmp_component);
897 return (NULL);
898 }
899 }
900 g_string_append_printf (quoted_component, "\\%c", *c);
901 c++;
902 embedded = TRUE;
903 }
904 g_free (tmp_component);
905 return (g_string_free (quoted_component, FALSE));
906}
907
915static char *
916bind_cpe_component_for_uri (const char *component)
917{
918 if (!component)
919 return (g_strdup (""));
920 if (strcmp (component, "") == 0)
921 return (g_strdup (""));
922 if (strcmp (component, "ANY") == 0)
923 return (g_strdup (""));
924 if (strcmp (component, "NA") == 0)
925 return (g_strdup ("-"));
926 return (transform_for_uri (component));
927}
928
936static char *
937transform_for_uri (const char *component)
938{
939 GString *result;
940 char *tmp_component;
941 char *c;
942
943 if (!component)
944 return (g_strdup (""));
945 if (strcmp (component, "") == 0)
946 return (g_strdup (""));
947
948 tmp_component = g_strdup (component);
949
950 /* set all characters to lowercase */
951 for (c = tmp_component; *c; c++)
952 *c = tolower (*c);
953
954 result = g_string_new ("");
955 c = tmp_component;
956
957 while (*c)
958 {
959 if ((g_ascii_isalnum (*c) || *c == '_') && *c != '-')
960 {
961 g_string_append_printf (result, "%c", *c);
962 c++;
963 continue;
964 }
965 if (*c == '\\')
966 {
967 c++;
968 if (*c != '\0')
969 {
970 char to_escape[2];
971 char *escaped;
972 to_escape[0] = *c;
973 to_escape[1] = '\0';
974 escaped = g_uri_escape_string (to_escape, NULL, FALSE);
975 g_string_append_printf (result, "%s", escaped);
976 g_free (escaped);
977 c++;
978 }
979 continue;
980 }
981 if (*c == '?')
982 g_string_append_printf (result, "%s", "%01");
983 if (*c == '*')
984 g_string_append_printf (result, "%s", "%02");
985 c++;
986 }
987 g_free (tmp_component);
988 return (g_string_free (result, FALSE));
989}
990
999static char *
1001{
1002 if ((cpe->sw_edition == NULL || strcmp (cpe->sw_edition, "") == 0)
1003 && (cpe->target_sw == NULL || strcmp (cpe->target_sw, "") == 0)
1004 && (cpe->target_hw == NULL || strcmp (cpe->target_hw, "") == 0)
1005 && (cpe->other == NULL || strcmp (cpe->other, "") == 0))
1006 {
1007 if (strcmp (cpe->edition, "ANY") == 0)
1008 return (g_strdup (""));
1009 if (strcmp (cpe->edition, "NA") == 0)
1010 return (g_strdup ("-"));
1011 return (g_strdup (cpe->edition));
1012 }
1013
1014 char *edition = bind_cpe_component_for_uri (cpe->edition);
1015 char *sw_edition = bind_cpe_component_for_uri (cpe->sw_edition);
1016 char *target_sw = bind_cpe_component_for_uri (cpe->target_sw);
1017 char *target_hw = bind_cpe_component_for_uri (cpe->target_hw);
1018 char *other = bind_cpe_component_for_uri (cpe->other);
1019 GString *component;
1020 component = g_string_new ("");
1021 if (!((!sw_edition || strcmp (sw_edition, "") == 0)
1022 && (!target_sw || strcmp (target_sw, "") == 0)
1023 && (!target_hw || strcmp (target_hw, "") == 0)
1024 && (!other || strcmp (other, "") == 0)))
1025 g_string_append_printf (component, "~%s~%s~%s~%s~%s", edition, sw_edition,
1026 target_sw, target_hw, other);
1027 else if (edition)
1028 g_string_append_printf (component, "%s", edition);
1029
1030 if (edition)
1031 g_free (edition);
1032 if (sw_edition)
1033 g_free (sw_edition);
1034 if (target_sw)
1035 g_free (target_sw);
1036 if (target_hw)
1037 g_free (target_hw);
1038 if (other)
1039 g_free (other);
1040 return (g_string_free (component, FALSE));
1041}
1042
1050static char *
1051bind_cpe_component_for_fs (const char *component)
1052{
1053 if (!component)
1054 return (g_strdup ("*"));
1055 if (strcmp (component, "") == 0)
1056 return (g_strdup ("*"));
1057 if (strcmp (component, "ANY") == 0)
1058 return (g_strdup ("*"));
1059 if (strcmp (component, "NA") == 0)
1060 return (g_strdup ("-"));
1061 return (process_quoted_chars (component));
1062}
1063
1072static char *
1073process_quoted_chars (const char *component)
1074{
1075 if (!component)
1076 return (g_strdup (""));
1077 if (strcmp (component, "") == 0)
1078 return (g_strdup (""));
1079
1080 GString *fs_component;
1081 fs_component = g_string_new ("");
1082 char *c = (char *) component;
1083 char next_c;
1084
1085 while (*c)
1086 {
1087 if (*c != '\\')
1088 {
1089 g_string_append_printf (fs_component, "%c", *c);
1090 c++;
1091 }
1092 else
1093 {
1094 next_c = *(c + 1);
1095 if (next_c == '.' || next_c == '-' || next_c == '_')
1096 {
1097 g_string_append_printf (fs_component, "%c", next_c);
1098 c += 2;
1099 }
1100 else if (next_c)
1101 {
1102 g_string_append_printf (fs_component, "\\%c", next_c);
1103 c += 2;
1104 }
1105 }
1106 }
1107 return (g_string_free (fs_component, FALSE));
1108}
1109
1115void
1117{
1118 cpe->part = NULL;
1119 cpe->vendor = NULL;
1120 cpe->product = NULL;
1121 cpe->version = NULL;
1122 cpe->update = NULL;
1123 cpe->edition = NULL;
1124 cpe->sw_edition = NULL;
1125 cpe->target_sw = NULL;
1126 cpe->target_hw = NULL;
1127 cpe->other = NULL;
1128 cpe->language = NULL;
1129
1130 /* to keep the compiler satisfied */
1131 cpe->part = cpe->part;
1132}
1133
1139void
1141{
1142 if (cpe->part)
1143 g_free (cpe->part);
1144 if (cpe->vendor)
1145 g_free (cpe->vendor);
1146 if (cpe->product)
1147 g_free (cpe->product);
1148 if (cpe->version)
1149 g_free (cpe->version);
1150 if (cpe->update)
1151 g_free (cpe->update);
1152 if (cpe->edition)
1153 g_free (cpe->edition);
1154 if (cpe->sw_edition)
1155 g_free (cpe->sw_edition);
1156 if (cpe->target_sw)
1157 g_free (cpe->target_sw);
1158 if (cpe->target_hw)
1159 g_free (cpe->target_hw);
1160 if (cpe->other)
1161 g_free (cpe->other);
1162 if (cpe->language)
1163 g_free (cpe->language);
1164}
1165
1171static void
1172trim_pct (char *str)
1173{
1174 char *c;
1175
1176 if (!str)
1177 return;
1178 c = str + strlen (str) - 1;
1179 while (c >= str)
1180 {
1181 if (*c == ':')
1182 {
1183 *c = '\0';
1184 c--;
1185 }
1186 else
1187 break;
1188 }
1189}
1190
1197static void
1198get_code (char *code, const char *str)
1199{
1200 code[0] = *str;
1201 code[1] = *(str + 1);
1202 code[2] = *(str + 2);
1203 code[3] = '\0';
1204}
1205
1215static void
1216str_cpy (char **dest, const char *src, int size)
1217{
1218 *dest = (char *) g_malloc (size + 1);
1219 memset (*dest, 0, size + 1);
1220 strncpy (*dest, src, size);
1221}
1222
1235gboolean
1237{
1238 enum set_relation relation;
1239
1240 relation = compare_component (source.part, target.part);
1241 if (relation != SUPERSET && relation != EQUAL)
1242 return (FALSE);
1243 relation = compare_component (source.vendor, target.vendor);
1244 if (relation != SUPERSET && relation != EQUAL)
1245 return (FALSE);
1246 relation = compare_component (source.product, target.product);
1247 if (relation != SUPERSET && relation != EQUAL)
1248 return (FALSE);
1249 relation = compare_component (source.version, target.version);
1250 if (relation != SUPERSET && relation != EQUAL)
1251 return (FALSE);
1252 relation = compare_component (source.update, target.update);
1253 if (relation != SUPERSET && relation != EQUAL)
1254 return (FALSE);
1255 relation = compare_component (source.edition, target.edition);
1256 if (relation != SUPERSET && relation != EQUAL)
1257 return (FALSE);
1258 relation = compare_component (source.sw_edition, target.sw_edition);
1259 if (relation != SUPERSET && relation != EQUAL)
1260 return (FALSE);
1261 relation = compare_component (source.target_sw, target.target_sw);
1262 if (relation != SUPERSET && relation != EQUAL)
1263 return (FALSE);
1264 relation = compare_component (source.target_hw, target.target_hw);
1265 if (relation != SUPERSET && relation != EQUAL)
1266 return (FALSE);
1267 relation = compare_component (source.other, target.other);
1268 if (relation != SUPERSET && relation != EQUAL)
1269 return (FALSE);
1270 relation = compare_component (source.language, target.language);
1271 if (relation != SUPERSET && relation != EQUAL)
1272 return (FALSE);
1273
1274 return (TRUE);
1275}
1276
1288static enum set_relation
1289compare_component (const char *source, const char *target)
1290{
1291 enum set_relation result;
1292 char *source_cpy, *target_cpy;
1293 char *c;
1294
1295 if (source)
1296 source_cpy = g_strdup (source);
1297 else
1298 source_cpy = g_strdup ("ANY");
1299 if (target)
1300 target_cpy = g_strdup (target);
1301 else
1302 target_cpy = g_strdup ("ANY");
1303
1304 if (is_string (source_cpy))
1305 {
1306 /* set all characters to lowercase */
1307 for (c = source_cpy; *c; c++)
1308 *c = tolower (*c);
1309 }
1310 if (is_string (target_cpy))
1311 {
1312 /* set all characters to lowercase */
1313 for (c = target_cpy; *c; c++)
1314 *c = tolower (*c);
1315 }
1316 if (is_string (target_cpy) && has_wildcards (target_cpy))
1317 {
1318 g_free (source_cpy);
1319 g_free (target_cpy);
1320 return (UNDEFINED);
1321 }
1322 if (strcmp (source_cpy, target_cpy) == 0)
1323 {
1324 g_free (source_cpy);
1325 g_free (target_cpy);
1326 return (EQUAL);
1327 }
1328 if (strcmp (source_cpy, "ANY") == 0)
1329 {
1330 g_free (source_cpy);
1331 g_free (target_cpy);
1332 return (SUPERSET);
1333 }
1334 if (strcmp (target_cpy, "ANY") == 0)
1335 {
1336 g_free (source_cpy);
1337 g_free (target_cpy);
1338 return (SUBSET);
1339 }
1340 if (strcmp (target_cpy, "NA") == 0 || strcmp (source_cpy, "NA") == 0)
1341 {
1342 g_free (source_cpy);
1343 g_free (target_cpy);
1344 return (DISJOINT);
1345 }
1346
1347 result = compare_strings (source_cpy, target_cpy);
1348 g_free (source_cpy);
1349 g_free (target_cpy);
1350 return (result);
1351}
1352
1365static enum set_relation
1366compare_strings (const char *source, const char *target)
1367{
1368 int start = 0;
1369 int end = strlen (source);
1370 int begins = 0;
1371 int ends = 0;
1372
1373 char *sub_source;
1374
1375 if (*source == '*')
1376 {
1377 start = 1;
1378 begins = -1;
1379 }
1380 else
1381 {
1382 while (start < (int) strlen (source) && *(source + start) == '?')
1383 {
1384 start++;
1385 begins++;
1386 }
1387 }
1388 if (*(source + end - 1) == '*' && is_even_wildcards (source, end - 1))
1389 {
1390 end--;
1391 ends = -1;
1392 }
1393 else
1394 {
1395 while (end > 0 && *(source + end - 1) == '?'
1396 && is_even_wildcards (source, end - 1))
1397 {
1398 end--;
1399 ends++;
1400 }
1401 }
1402
1403 str_cpy (&sub_source, source + start, end - start);
1404 int index = -1;
1405 int escapes = 0;
1406 int leftover = strlen (target);
1407
1408 while (leftover > 0)
1409 {
1410 index = index_of (target, sub_source, index + 1);
1411 if (index == -1)
1412 break;
1413 escapes = count_escapes (target, 0, index);
1414 if (index > 0 && begins != -1 && begins < (index - escapes))
1415 break;
1416 escapes = count_escapes (target, index + 1, strlen (target));
1417 leftover = strlen (target) - index - escapes - strlen (sub_source);
1418 if (leftover > 0 && (ends != -1 && leftover > ends))
1419 continue;
1420 g_free (sub_source);
1421 return SUPERSET;
1422 }
1423 g_free (sub_source);
1424 return DISJOINT;
1425}
1426
1440static int
1441count_escapes (const char *str, int start, int end)
1442{
1443 int result = 0;
1444 gboolean active = FALSE;
1445
1446 for (int i = 0; i < end && *(str + i) != '\0'; i++)
1447 {
1448 active = (!active && *(str + i) == '\\');
1449 if (active && i >= start)
1450 result++;
1451 }
1452 return (result);
1453}
1454
1465static gboolean
1466is_even_wildcards (const char *str, int index)
1467{
1468 int result = 0;
1469
1470 while (index > 0 && *(str + index - 1) == '\\')
1471 {
1472 index--;
1473 result++;
1474 }
1475 return ((result % 2) == 0);
1476}
1477
1485static gboolean
1486has_wildcards (const char *str)
1487{
1488 char *c = (char *) str;
1489 gboolean active = FALSE;
1490
1491 while (*c != '\0')
1492 {
1493 if (!active && (*c == '?' || *c == '*'))
1494 return TRUE;
1495
1496 if (!active && *c == '\\')
1497 active = TRUE;
1498 else
1499 active = FALSE;
1500
1501 c++;
1502 }
1503 return FALSE;
1504}
1505
1517static int
1518index_of (const char *str, const char *sub_str, int offset)
1519{
1520 char *start;
1521 char *begin_substr;
1522
1523 if (offset > (int) strlen (str))
1524 return (-1);
1525
1526 start = (char *) str + offset;
1527 begin_substr = strstr (start, sub_str);
1528 if (begin_substr == NULL)
1529 return (-1);
1530 return (begin_substr - str);
1531}
1532
1542static gboolean
1543is_string (const char *str)
1544{
1545 if (!str)
1546 return TRUE;
1547
1548 return (strcmp (str, "ANY") && strcmp (str, "NA"));
1549}
char * fs_cpe_to_uri_cpe(const char *fs_cpe)
Convert a formatted string CPE to a URI CPE.
Definition cpeutils.c:143
static char * bind_cpe_component_for_fs(const char *)
Bind a CPE component for a formatted string CPE.
Definition cpeutils.c:1051
char * uri_cpe_to_fs_cpe(const char *uri_cpe)
Convert a URI CPE to a formatted string CPE.
Definition cpeutils.c:103
static enum set_relation compare_strings(const char *, const char *)
Returns if the string of a component "source" is a match for the the string of a component "target"....
Definition cpeutils.c:1366
static char * bind_cpe_component_for_uri(const char *)
Bind a CPE component for a URI CPE.
Definition cpeutils.c:916
static char * get_fs_component(const char *, int)
Get the indexth component of a formatted string CPE.
Definition cpeutils.c:753
static gboolean is_even_wildcards(const char *, int)
Returns true if an even number of escape (backslash) characters precede the character at the index "i...
Definition cpeutils.c:1466
gboolean cpe_struct_match(cpe_struct_t source, cpe_struct_t target)
Returns if source is a match for target. That means that source is a superset of target.
Definition cpeutils.c:1236
static enum set_relation compare_component(const char *, const char *)
Returns if the component "source" is a match for the component "target". That means that source is a ...
Definition cpeutils.c:1289
char * fs_cpe_to_uri_product(const char *fs_cpe)
Convert a formatted string CPE to an URI product.
Definition cpeutils.c:163
static void get_code(char *, const char *)
Get the percent code from the start of a string.
Definition cpeutils.c:1198
static void unpack_sixth_uri_component(const char *, cpe_struct_t *)
Unpack the sixth component of a URI CPE.
Definition cpeutils.c:671
char * cpe_struct_to_fs_cpe(const cpe_struct_t *cpe)
Convert a CPE struct into a formatted string CPE.
Definition cpeutils.c:369
static char * unbind_fs_component(char *)
Unbind a formatted string CPE component.
Definition cpeutils.c:809
static char * get_uri_component(const char *, int)
Get the indexth component of a URI CPE.
Definition cpeutils.c:490
static char * decode_uri_component(const char *)
Decode a component of a URI CPE.
Definition cpeutils.c:540
static void str_cpy(char **, const char *, int)
Copy size characters of a string to an newly allocated new string.
Definition cpeutils.c:1216
static char * process_quoted_chars(const char *)
Process the quoted characters of a CPE component for a formatted string CPE.
Definition cpeutils.c:1073
void fs_cpe_to_cpe_struct(const char *fs_cpe, cpe_struct_t *cpe)
Read a formatted string CPE into the CPE struct.
Definition cpeutils.c:323
static char * add_quoting(const char *)
Handle the quoting for an unbind formatted string CPE component.
Definition cpeutils.c:827
char * cpe_struct_to_uri_product(const cpe_struct_t *cpe)
Convert a CPE struct into a URI product.
Definition cpeutils.c:285
char * cpe_struct_to_uri_cpe(const cpe_struct_t *cpe)
Convert a CPE struct into a URI CPE.
Definition cpeutils.c:223
void cpe_struct_init(cpe_struct_t *cpe)
Initialize a CPE struct.
Definition cpeutils.c:1116
char * cpe_struct_to_fs_product(const cpe_struct_t *cpe)
Convert a CPE struct into a formatted string product.
Definition cpeutils.c:453
static int index_of(const char *, const char *, int)
Searches the string "str" for the first occurrence of the string "sub_str", starting at the offset "o...
Definition cpeutils.c:1518
static gboolean is_string(const char *)
Returns if a string is an ordinary string and does not represent one of the logical values "ANY" or "...
Definition cpeutils.c:1543
void cpe_struct_free(cpe_struct_t *cpe)
Free a CPE struct.
Definition cpeutils.c:1140
static char * pack_sixth_uri_component(const cpe_struct_t *)
Pack the sixth component of a URI CPE.
Definition cpeutils.c:1000
static char * transform_for_uri(const char *)
Transform a CPE component for a URI CPE.
Definition cpeutils.c:937
static gboolean has_wildcards(const char *)
Returns if a given string contains wildcards ("*" or "?").
Definition cpeutils.c:1486
void uri_cpe_to_cpe_struct(const char *uri_cpe, cpe_struct_t *cpe)
Read a URI CPE into the CPE struct.
Definition cpeutils.c:183
static int count_escapes(const char *, int, int)
Counts the number of unescaped escape signs ("\") in a specified part of a string.
Definition cpeutils.c:1441
static void trim_pct(char *)
Cut of trailing ':' signs.
Definition cpeutils.c:1172
char * uri_cpe_to_fs_product(const char *uri_cpe)
Convert a URI CPE to a formatted string product.
Definition cpeutils.c:123
Headers for CPE utils.
set_relation
Definition cpeutils.h:77
@ SUBSET
Definition cpeutils.h:80
@ DISJOINT
Definition cpeutils.h:78
@ EQUAL
Definition cpeutils.h:79
@ UNDEFINED
Definition cpeutils.h:82
@ SUPERSET
Definition cpeutils.h:81
XML context.
Definition cpeutils.h:23
char * sw_edition
Definition cpeutils.h:30
char * target_sw
Definition cpeutils.h:31
char * vendor
Definition cpeutils.h:25
char * version
Definition cpeutils.h:27
char * update
Definition cpeutils.h:28
char * product
Definition cpeutils.h:26
char * part
Definition cpeutils.h:24
char * edition
Definition cpeutils.h:29
char * language
Definition cpeutils.h:34
char * target_hw
Definition cpeutils.h:32
char * other
Definition cpeutils.h:33