Greenbone Vulnerability Management Libraries 22.14.0
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
99char *
100uri_cpe_to_fs_cpe (const char *uri_cpe)
101{
102 cpe_struct_t cpe;
103 char *fs_cpe;
104
105 cpe_struct_init (&cpe);
106 uri_cpe_to_cpe_struct (uri_cpe, &cpe);
107 fs_cpe = cpe_struct_to_fs_cpe (&cpe);
108 cpe_struct_free (&cpe);
109 return (fs_cpe);
110}
111
119char *
120uri_cpe_to_fs_product (const char *uri_cpe)
121{
122 cpe_struct_t cpe;
123 char *fs_cpe;
124
125 cpe_struct_init (&cpe);
126 uri_cpe_to_cpe_struct (uri_cpe, &cpe);
127 fs_cpe = cpe_struct_to_fs_product (&cpe);
128 cpe_struct_free (&cpe);
129 return (fs_cpe);
130}
131
139char *
140fs_cpe_to_uri_cpe (const char *fs_cpe)
141{
142 cpe_struct_t cpe;
143 char *uri_cpe;
144
145 cpe_struct_init (&cpe);
146 fs_cpe_to_cpe_struct (fs_cpe, &cpe);
147 uri_cpe = cpe_struct_to_uri_cpe (&cpe);
148 cpe_struct_free (&cpe);
149 return (uri_cpe);
150}
151
159char *
160fs_cpe_to_uri_product (const char *fs_cpe)
161{
162 cpe_struct_t cpe;
163 char *uri_cpe;
164
165 cpe_struct_init (&cpe);
166 fs_cpe_to_cpe_struct (fs_cpe, &cpe);
167 uri_cpe = cpe_struct_to_uri_product (&cpe);
168 cpe_struct_free (&cpe);
169 return (uri_cpe);
170}
171
179void
180uri_cpe_to_cpe_struct (const char *uri_cpe, cpe_struct_t *cpe)
181{
182 char *uri_component;
183
184 uri_component = get_uri_component (uri_cpe, 1);
185 cpe->part = decode_uri_component (uri_component);
186 g_free (uri_component);
187 uri_component = get_uri_component (uri_cpe, 2);
188 cpe->vendor = decode_uri_component (uri_component);
189 g_free (uri_component);
190 uri_component = get_uri_component (uri_cpe, 3);
191 cpe->product = decode_uri_component (uri_component);
192 g_free (uri_component);
193 uri_component = get_uri_component (uri_cpe, 4);
194 cpe->version = decode_uri_component (uri_component);
195 g_free (uri_component);
196 uri_component = get_uri_component (uri_cpe, 5);
197 cpe->update = decode_uri_component (uri_component);
198 g_free (uri_component);
199 uri_component = get_uri_component (uri_cpe, 6);
200 if (strcmp (uri_component, "") == 0 || strcmp (uri_component, "-") == 0
201 || *uri_component != '~')
202 cpe->edition = decode_uri_component (uri_component);
203 else
204 unpack_sixth_uri_component (uri_component, cpe);
205 g_free (uri_component);
206
207 uri_component = get_uri_component (uri_cpe, 7);
208 cpe->language = decode_uri_component (uri_component);
209 g_free (uri_component);
210}
211
219char *
221{
222 GString *uri_cpe;
223 char *bind_cpe_component;
224 uri_cpe = g_string_new ("cpe:/");
225
226 bind_cpe_component = bind_cpe_component_for_uri (cpe->part);
227 if (bind_cpe_component)
228 {
229 g_string_append (uri_cpe, bind_cpe_component);
230 g_string_append_c (uri_cpe, ':');
231 g_free (bind_cpe_component);
232 }
233 bind_cpe_component = bind_cpe_component_for_uri (cpe->vendor);
234 if (bind_cpe_component)
235 {
236 g_string_append (uri_cpe, bind_cpe_component);
237 g_string_append_c (uri_cpe, ':');
238 g_free (bind_cpe_component);
239 }
240 bind_cpe_component = bind_cpe_component_for_uri (cpe->product);
241 if (bind_cpe_component)
242 {
243 g_string_append (uri_cpe, bind_cpe_component);
244 g_string_append_c (uri_cpe, ':');
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 (uri_cpe, bind_cpe_component);
251 g_string_append_c (uri_cpe, ':');
252 g_free (bind_cpe_component);
253 }
254 bind_cpe_component = bind_cpe_component_for_uri (cpe->update);
255 if (bind_cpe_component)
256 {
257 g_string_append (uri_cpe, bind_cpe_component);
258 g_string_append_c (uri_cpe, ':');
259 g_free (bind_cpe_component);
260 }
261 bind_cpe_component = pack_sixth_uri_component (cpe);
262 if (bind_cpe_component)
263 {
264 g_string_append (uri_cpe, bind_cpe_component);
265 g_string_append_c (uri_cpe, ':');
266 g_free (bind_cpe_component);
267 }
268 bind_cpe_component = bind_cpe_component_for_uri (cpe->language);
269 if (bind_cpe_component)
270 {
271 g_string_append (uri_cpe, bind_cpe_component);
272 g_string_append_c (uri_cpe, ':');
273 g_free (bind_cpe_component);
274 }
275
276 char *result = g_string_free (uri_cpe, FALSE);
277 trim_pct (result);
278 return (result);
279}
280
288char *
290{
291 GString *uri_cpe;
292 char *bind_cpe_component;
293 uri_cpe = g_string_new ("cpe:/");
294
295 bind_cpe_component = bind_cpe_component_for_uri (cpe->part);
296 if (bind_cpe_component)
297 {
298 g_string_append (uri_cpe, bind_cpe_component);
299 g_string_append_c (uri_cpe, ':');
300 g_free (bind_cpe_component);
301 }
302 bind_cpe_component = bind_cpe_component_for_uri (cpe->vendor);
303 if (bind_cpe_component)
304 {
305 g_string_append (uri_cpe, bind_cpe_component);
306 g_string_append_c (uri_cpe, ':');
307 g_free (bind_cpe_component);
308 }
309 bind_cpe_component = bind_cpe_component_for_uri (cpe->product);
310 if (bind_cpe_component)
311 {
312 g_string_append (uri_cpe, bind_cpe_component);
313 g_string_append_c (uri_cpe, ':');
314 g_free (bind_cpe_component);
315 }
316
317 char *result = g_string_free (uri_cpe, FALSE);
318 trim_pct (result);
319 return (result);
320}
321
329char *
330get_version_from_uri_cpe (const char *uri_cpe)
331{
332 char *version = get_uri_component (uri_cpe, 4);
333 char *decoded_version = decode_uri_component (version);
334 g_free (version);
335 return decoded_version;
336}
337
345void
346fs_cpe_to_cpe_struct (const char *fs_cpe, cpe_struct_t *cpe)
347{
348 char *fs_component;
349
350 fs_component = get_fs_component (fs_cpe, 2);
351 cpe->part = unbind_fs_component (fs_component);
352 fs_component = get_fs_component (fs_cpe, 3);
353 cpe->vendor = unbind_fs_component (fs_component);
354 fs_component = get_fs_component (fs_cpe, 4);
355 cpe->product = unbind_fs_component (fs_component);
356 fs_component = get_fs_component (fs_cpe, 5);
357 cpe->version = unbind_fs_component (fs_component);
358 fs_component = get_fs_component (fs_cpe, 6);
359 cpe->update = unbind_fs_component (fs_component);
360 fs_component = get_fs_component (fs_cpe, 7);
361 cpe->edition = unbind_fs_component (fs_component);
362 fs_component = get_fs_component (fs_cpe, 8);
363 cpe->language = unbind_fs_component (fs_component);
364 fs_component = get_fs_component (fs_cpe, 9);
365 cpe->sw_edition = unbind_fs_component (fs_component);
366 fs_component = get_fs_component (fs_cpe, 10);
367 cpe->target_sw = unbind_fs_component (fs_component);
368 fs_component = get_fs_component (fs_cpe, 11);
369 cpe->target_hw = unbind_fs_component (fs_component);
370 fs_component = get_fs_component (fs_cpe, 12);
371 cpe->other = unbind_fs_component (fs_component);
372}
373
381char *
383{
384 GString *fs_cpe;
385 char *bind_cpe_component;
386
387 fs_cpe = g_string_new ("cpe:2.3:");
388
389 bind_cpe_component = bind_cpe_component_for_fs (cpe->part);
390 if (bind_cpe_component)
391 {
392 g_string_append (fs_cpe, bind_cpe_component);
393 g_string_append_c (fs_cpe, ':');
394 g_free (bind_cpe_component);
395 }
396 bind_cpe_component = bind_cpe_component_for_fs (cpe->vendor);
397 if (bind_cpe_component)
398 {
399 g_string_append (fs_cpe, bind_cpe_component);
400 g_string_append_c (fs_cpe, ':');
401 g_free (bind_cpe_component);
402 }
403 bind_cpe_component = bind_cpe_component_for_fs (cpe->product);
404 if (bind_cpe_component)
405 {
406 g_string_append (fs_cpe, bind_cpe_component);
407 g_string_append_c (fs_cpe, ':');
408 g_free (bind_cpe_component);
409 }
410 bind_cpe_component = bind_cpe_component_for_fs (cpe->version);
411 if (bind_cpe_component)
412 {
413 g_string_append (fs_cpe, bind_cpe_component);
414 g_string_append_c (fs_cpe, ':');
415 g_free (bind_cpe_component);
416 }
417 bind_cpe_component = bind_cpe_component_for_fs (cpe->update);
418 if (bind_cpe_component)
419 {
420 g_string_append (fs_cpe, bind_cpe_component);
421 g_string_append_c (fs_cpe, ':');
422 g_free (bind_cpe_component);
423 }
424 bind_cpe_component = bind_cpe_component_for_fs (cpe->edition);
425 if (bind_cpe_component)
426 {
427 g_string_append (fs_cpe, bind_cpe_component);
428 g_string_append_c (fs_cpe, ':');
429 g_free (bind_cpe_component);
430 }
431 bind_cpe_component = bind_cpe_component_for_fs (cpe->language);
432 if (bind_cpe_component)
433 {
434 g_string_append (fs_cpe, bind_cpe_component);
435 g_string_append_c (fs_cpe, ':');
436 g_free (bind_cpe_component);
437 }
438 bind_cpe_component = bind_cpe_component_for_fs (cpe->sw_edition);
439 if (bind_cpe_component)
440 {
441 g_string_append (fs_cpe, bind_cpe_component);
442 g_string_append_c (fs_cpe, ':');
443 g_free (bind_cpe_component);
444 }
445 bind_cpe_component = bind_cpe_component_for_fs (cpe->target_sw);
446 if (bind_cpe_component)
447 {
448 g_string_append (fs_cpe, bind_cpe_component);
449 g_string_append_c (fs_cpe, ':');
450 g_free (bind_cpe_component);
451 }
452 bind_cpe_component = bind_cpe_component_for_fs (cpe->target_hw);
453 if (bind_cpe_component)
454 {
455 g_string_append (fs_cpe, bind_cpe_component);
456 g_string_append_c (fs_cpe, ':');
457 g_free (bind_cpe_component);
458 }
459 bind_cpe_component = bind_cpe_component_for_fs (cpe->other);
460 if (bind_cpe_component)
461 {
462 g_string_append (fs_cpe, bind_cpe_component);
463 g_free (bind_cpe_component);
464 }
465 return (g_string_free (fs_cpe, FALSE));
466}
467
475char *
477{
478 GString *fs_cpe;
479 char *bind_cpe_component;
480
481 fs_cpe = g_string_new ("cpe:2.3:");
482
483 bind_cpe_component = bind_cpe_component_for_fs (cpe->part);
484 if (bind_cpe_component)
485 {
486 g_string_append (fs_cpe, bind_cpe_component);
487 g_string_append_c (fs_cpe, ':');
488 g_free (bind_cpe_component);
489 }
490 bind_cpe_component = bind_cpe_component_for_fs (cpe->vendor);
491 if (bind_cpe_component)
492 {
493 g_string_append (fs_cpe, bind_cpe_component);
494 g_string_append_c (fs_cpe, ':');
495 g_free (bind_cpe_component);
496 }
497 bind_cpe_component = bind_cpe_component_for_fs (cpe->product);
498 if (bind_cpe_component)
499 {
500 g_string_append (fs_cpe, bind_cpe_component);
501 g_string_append_c (fs_cpe, ':');
502 g_free (bind_cpe_component);
503 }
504 return (g_string_free (fs_cpe, FALSE));
505}
506
515static char *
516get_uri_component (const char *uri_cpe, int index)
517{
518 char *component = NULL;
519 char *c;
520 char *component_start, *component_end;
521
522 if (!uri_cpe)
523 return NULL;
524
525 c = (char *) uri_cpe;
526
527 /* find start of component */
528 for (int i = 0; *c != '\0' && i < index; c++)
529 {
530 if (*c == ':')
531 i++;
532 }
533
534 if (index == 1 && *c != '\0')
535 c++;
536
537 component_start = c;
538
539 /* find end of component */
540 if (*component_start == '\0')
541 component_end = component_start;
542 else
543 {
544 for (c = component_start; *c != '\0' && *c != ':'; c++)
545 ;
546 }
547
548 component_end = c;
549
550 if (component_start >= component_end || component_end == 0)
551 component = (char *) g_strdup ("");
552 else
553 component = g_strndup (component_start, component_end - component_start);
554
555 return component;
556}
557
565static char *
566decode_uri_component (const char *component)
567{
568 GString *decoded_component;
569 char *escapes = "!\"#$%&'()*+,/:;<=>?@[\\]^`{|}~";
570 char *tmp_component;
571 char code_a[4], code_b[4], code_c[4];
572 long unsigned int index;
573 gboolean embedded;
574
575 if (!component)
576 return (NULL);
577
578 if (strcmp (component, "") == 0 || strcmp (component, " ") == 0)
579 {
580 return (g_strdup ("ANY"));
581 }
582 if (strcmp (component, "-") == 0)
583 {
584 return (g_strdup ("NA"));
585 }
586
587 tmp_component = g_strdup (component);
588
589 /* set all characters to lowercase */
590 char *c = tmp_component;
591 for (; *c; c++)
592 *c = tolower (*c);
593
594 index = 0;
595 embedded = FALSE;
596 decoded_component = g_string_sized_new (2 * strlen (component));
597
598 char l;
599 char *unescaped;
600 while (index < strlen (tmp_component))
601 {
602 l = *(tmp_component + index);
603
604 if (l == '.' || l == '-' || l == '~')
605 {
606 g_string_append_c (decoded_component, '\\');
607 g_string_append_c (decoded_component, l);
608 index++;
609 embedded = TRUE;
610 continue;
611 }
612 if (l != '%')
613 {
614 g_string_append_c (decoded_component, l);
615 index++;
616 embedded = TRUE;
617 continue;
618 }
619
620 get_code (code_a, tmp_component + index);
621
622 if (strcmp (code_a, "%01") == 0)
623 {
624 if (index >= 3)
625 get_code (code_b, tmp_component + index - 3);
626 else
627 code_b[0] = '0';
628 if (strlen (tmp_component) >= index + 6)
629 get_code (code_c, tmp_component + index + 3);
630 else
631 code_c[0] = '0';
632 if ((index == 0 || index == strlen (tmp_component) - 3)
633 || (!embedded && strcmp (code_b, "%01"))
634 || (embedded && strcmp (code_c, "%01")))
635 {
636 g_string_append_c (decoded_component, '?');
637 index = index + 3;
638 continue;
639 }
640 else
641 {
642 g_string_free (decoded_component, TRUE);
643 g_free (tmp_component);
644 return (NULL);
645 }
646 }
647
648 if (strcmp (code_a, "%02") == 0)
649 {
650 if (index == 0 || index == strlen (tmp_component) - 3)
651 {
652 g_string_append_c (decoded_component, '*');
653 index = index + 3;
654 continue;
655 }
656 else
657 {
658 g_string_free (decoded_component, TRUE);
659 g_free (tmp_component);
660 return (NULL);
661 }
662 }
663
664 unescaped = g_uri_unescape_string (code_a, NULL);
665 if (unescaped && strchr (escapes, *unescaped))
666 {
667 g_string_append_c (decoded_component, '\\');
668 g_string_append (decoded_component, unescaped);
669 g_free (unescaped);
670 }
671 else if (unescaped)
672 {
673 g_string_append (decoded_component, unescaped);
674 g_free (unescaped);
675 }
676 else
677 {
678 g_string_free (decoded_component, TRUE);
679 g_free (tmp_component);
680 return (NULL);
681 }
682 index = index + 3;
683 embedded = TRUE;
684 }
685
686 g_free (tmp_component);
687 return (g_string_free (decoded_component, FALSE));
688}
689
698static void
699unpack_sixth_uri_component (const char *component, cpe_struct_t *cpe)
700{
701 const char *start = component + 1;
702 const char *end;
703
704 char *edition, *sw_edition, *target_sw, *target_hw, *other;
705
706 end = strchr (start, '~');
707 if (start >= end || end == NULL)
708 edition = strdup ("");
709 else
710 edition = g_strndup (start, end - start);
711
712 if (end != NULL)
713 {
714 start = end + 1;
715 end = strchr (start, '~');
716 if (start >= end || end == NULL)
717 sw_edition = strdup ("");
718 else
719 sw_edition = g_strndup (start, end - start);
720 }
721 else
722 sw_edition = strdup ("");
723
724 if (end != NULL)
725 {
726 start = end + 1;
727 end = strchr (start, '~');
728 if (start >= end || end == NULL)
729 target_sw = strdup ("");
730 else
731 target_sw = g_strndup (start, end - start);
732 }
733 else
734 target_sw = strdup ("");
735
736 if (end != NULL)
737 {
738 start = end + 1;
739 end = strchr (start, '~');
740 if (start >= end || end == NULL)
741 target_hw = strdup ("");
742 else
743 target_hw = g_strndup (start, end - start);
744 }
745 else
746 target_hw = strdup ("");
747
748 if (end != NULL)
749 {
750 start = end + 1;
751 end = component + strlen (component);
752 if (start >= end)
753 other = strdup ("");
754 else
755 other = g_strndup (start, end - start);
756 }
757 else
758 other = strdup ("");
759
760 cpe->edition = decode_uri_component (edition);
761 g_free (edition);
762 cpe->sw_edition = decode_uri_component (sw_edition);
763 g_free (sw_edition);
764 cpe->target_sw = decode_uri_component (target_sw);
765 g_free (target_sw);
766 cpe->target_hw = decode_uri_component (target_hw);
767 g_free (target_hw);
768 cpe->other = decode_uri_component (other);
769 g_free (other);
770}
771
780static char *
781get_fs_component (const char *fs_cpe, int index)
782{
783 char *component = NULL;
784 char *c;
785 char *component_start, *component_end;
786
787 if (!fs_cpe)
788 return NULL;
789
790 if (*fs_cpe == '\0')
791 return ((char *) g_strdup (""));
792
793 c = (char *) fs_cpe;
794
795 /* find start of component */
796 if (index == 0)
797 component_start = c;
798 else
799 {
800 for (int i = 0; *c != '\0' && i < index; c++)
801 {
802 if (*c == ':' && c == fs_cpe)
803 i++;
804 else if (c > fs_cpe && *c == ':' && *(c - 1) != '\\')
805 i++;
806 }
807 component_start = c;
808 }
809
810 /* find end of component */
811 if (*component_start == '\0')
812 component_end = component_start;
813 else
814 {
815 for (c = component_start; *c != '\0' && *c != ':'; c++)
816 ;
817 }
818
819 component_end = c;
820
821 if (component_start >= component_end || component_end == NULL)
822 component = (char *) g_strdup ("");
823 else
824 component = g_strndup (component_start, component_end - component_start);
825
826 return component;
827}
828
836static char *
837unbind_fs_component (char *component)
838{
839 char *unbound_component;
840
841 if (strcmp (component, "*") == 0)
842 {
843 g_free (component);
844 return ((char *) g_strdup ("ANY"));
845 }
846 if (strcmp (component, "-") == 0)
847 {
848 g_free (component);
849 return ((char *) g_strdup ("NA"));
850 }
851
852 unbound_component = add_quoting (component);
853 g_free (component);
854 return (unbound_component);
855}
856
865static char *
866add_quoting (const char *component)
867{
868 GString *quoted_component;
869 char *tmp_component;
870 char *c;
871 gboolean embedded;
872
873 if (!component)
874 return (NULL);
875
876 quoted_component = g_string_sized_new (2 * strlen (component));
877 tmp_component = (char *) g_strdup (component);
878 embedded = FALSE;
879
880 /* set all characters to lowercase */
881 for (c = tmp_component; *c; c++)
882 *c = tolower (*c);
883
884 c = tmp_component;
885 while (*c != '\0')
886 {
887 if (g_ascii_isalnum (*c) || *c == '_')
888 {
889 g_string_append_c (quoted_component, *c);
890 c++;
891 embedded = TRUE;
892 continue;
893 }
894 if (*c == '\\')
895 {
896 c++;
897 if (*c != '\0')
898 {
899 g_string_append_c (quoted_component, '\\');
900 g_string_append_c (quoted_component, *c);
901 embedded = TRUE;
902 c++;
903 continue;
904 }
905 }
906 if (*c == '*')
907 {
908 if ((c == tmp_component)
909 || (c == tmp_component + strlen (tmp_component - 1)))
910 {
911 g_string_append_c (quoted_component, *c);
912 c++;
913 embedded = TRUE;
914 continue;
915 }
916 else
917 {
918 g_free (tmp_component);
919 return (NULL);
920 }
921 }
922 if (*c == '?')
923 {
924 if ((c == tmp_component)
925 || (c == tmp_component + strlen (tmp_component - 1))
926 || (!embedded && (c > tmp_component) && (*(c - 1) == '?'))
927 || (embedded && *(c + 1) == '?'))
928 {
929 g_string_append_c (quoted_component, *c);
930 c++;
931 embedded = FALSE;
932 continue;
933 }
934 else
935 {
936 g_free (tmp_component);
937 return (NULL);
938 }
939 }
940 g_string_append_c (quoted_component, '\\');
941 g_string_append_c (quoted_component, *c);
942 c++;
943 embedded = TRUE;
944 }
945 g_free (tmp_component);
946 return (g_string_free (quoted_component, FALSE));
947}
948
956static char *
957bind_cpe_component_for_uri (const char *component)
958{
959 if (!component)
960 return (g_strdup (""));
961 if (strcmp (component, "") == 0)
962 return (g_strdup (""));
963 if (strcmp (component, "ANY") == 0)
964 return (g_strdup (""));
965 if (strcmp (component, "NA") == 0)
966 return (g_strdup ("-"));
967 return (transform_for_uri (component));
968}
969
977static char *
978transform_for_uri (const char *component)
979{
980 GString *result;
981 char *tmp_component;
982 char *c;
983
984 if (!component)
985 return (g_strdup (""));
986 if (strcmp (component, "") == 0)
987 return (g_strdup (""));
988
989 tmp_component = g_strdup (component);
990
991 /* set all characters to lowercase */
992 for (c = tmp_component; *c; c++)
993 *c = tolower (*c);
994
995 result = g_string_new ("");
996 c = tmp_component;
997
998 while (*c)
999 {
1000 if ((g_ascii_isalnum (*c) || *c == '_') && *c != '-')
1001 {
1002 g_string_append_c (result, *c);
1003 c++;
1004 continue;
1005 }
1006 if (*c == '\\')
1007 {
1008 c++;
1009 if (*c != '\0')
1010 {
1011 char to_escape[2];
1012 char *escaped;
1013 to_escape[0] = *c;
1014 to_escape[1] = '\0';
1015 escaped = g_uri_escape_string (to_escape, NULL, FALSE);
1016 g_string_append (result, escaped);
1017 g_free (escaped);
1018 c++;
1019 }
1020 continue;
1021 }
1022 if (*c == '?')
1023 g_string_append (result, "%01");
1024 if (*c == '*')
1025 g_string_append (result, "%02");
1026 c++;
1027 }
1028 g_free (tmp_component);
1029 return (g_string_free (result, FALSE));
1030}
1031
1040static char *
1042{
1043 if ((cpe->sw_edition == NULL || strcmp (cpe->sw_edition, "") == 0)
1044 && (cpe->target_sw == NULL || strcmp (cpe->target_sw, "") == 0)
1045 && (cpe->target_hw == NULL || strcmp (cpe->target_hw, "") == 0)
1046 && (cpe->other == NULL || strcmp (cpe->other, "") == 0))
1047 {
1048 if (strcmp (cpe->edition, "ANY") == 0)
1049 return (g_strdup (""));
1050 if (strcmp (cpe->edition, "NA") == 0)
1051 return (g_strdup ("-"));
1052 return (g_strdup (cpe->edition));
1053 }
1054
1055 char *edition = bind_cpe_component_for_uri (cpe->edition);
1056 char *sw_edition = bind_cpe_component_for_uri (cpe->sw_edition);
1057 char *target_sw = bind_cpe_component_for_uri (cpe->target_sw);
1058 char *target_hw = bind_cpe_component_for_uri (cpe->target_hw);
1059 char *other = bind_cpe_component_for_uri (cpe->other);
1060 GString *component;
1061 component = g_string_new ("");
1062 if (!((!sw_edition || strcmp (sw_edition, "") == 0)
1063 && (!target_sw || strcmp (target_sw, "") == 0)
1064 && (!target_hw || strcmp (target_hw, "") == 0)
1065 && (!other || strcmp (other, "") == 0)))
1066 g_string_append_printf (component, "~%s~%s~%s~%s~%s", edition, sw_edition,
1067 target_sw, target_hw, other);
1068 else if (edition)
1069 g_string_append (component, edition);
1070
1071 if (edition)
1072 g_free (edition);
1073 if (sw_edition)
1074 g_free (sw_edition);
1075 if (target_sw)
1076 g_free (target_sw);
1077 if (target_hw)
1078 g_free (target_hw);
1079 if (other)
1080 g_free (other);
1081 return (g_string_free (component, FALSE));
1082}
1083
1091static char *
1092bind_cpe_component_for_fs (const char *component)
1093{
1094 if (!component)
1095 return (g_strdup ("*"));
1096 if (strcmp (component, "") == 0)
1097 return (g_strdup ("*"));
1098 if (strcmp (component, "ANY") == 0)
1099 return (g_strdup ("*"));
1100 if (strcmp (component, "NA") == 0)
1101 return (g_strdup ("-"));
1102 return (process_quoted_chars (component));
1103}
1104
1113static char *
1114process_quoted_chars (const char *component)
1115{
1116 if (!component)
1117 return (g_strdup (""));
1118 if (strcmp (component, "") == 0)
1119 return (g_strdup (""));
1120
1121 GString *fs_component;
1122 fs_component = g_string_new ("");
1123 char *c = (char *) component;
1124 char next_c;
1125
1126 while (*c)
1127 {
1128 if (*c != '\\')
1129 {
1130 g_string_append_c (fs_component, *c);
1131 c++;
1132 }
1133 else
1134 {
1135 next_c = *(c + 1);
1136 if (next_c == '.' || next_c == '-' || next_c == '_')
1137 {
1138 g_string_append_c (fs_component, next_c);
1139 c += 2;
1140 }
1141 else if (next_c)
1142 {
1143 g_string_append_c (fs_component, '\\');
1144 g_string_append_c (fs_component, next_c);
1145 c += 2;
1146 }
1147 }
1148 }
1149 return (g_string_free (fs_component, FALSE));
1150}
1151
1157void
1159{
1160 cpe->part = NULL;
1161 cpe->vendor = NULL;
1162 cpe->product = NULL;
1163 cpe->version = NULL;
1164 cpe->update = NULL;
1165 cpe->edition = NULL;
1166 cpe->sw_edition = NULL;
1167 cpe->target_sw = NULL;
1168 cpe->target_hw = NULL;
1169 cpe->other = NULL;
1170 cpe->language = NULL;
1171
1172 /* to keep the compiler satisfied */
1173 cpe->part = cpe->part;
1174}
1175
1181void
1183{
1184 if (!cpe)
1185 return;
1186 if (cpe->part)
1187 g_free (cpe->part);
1188 if (cpe->vendor)
1189 g_free (cpe->vendor);
1190 if (cpe->product)
1191 g_free (cpe->product);
1192 if (cpe->version)
1193 g_free (cpe->version);
1194 if (cpe->update)
1195 g_free (cpe->update);
1196 if (cpe->edition)
1197 g_free (cpe->edition);
1198 if (cpe->sw_edition)
1199 g_free (cpe->sw_edition);
1200 if (cpe->target_sw)
1201 g_free (cpe->target_sw);
1202 if (cpe->target_hw)
1203 g_free (cpe->target_hw);
1204 if (cpe->other)
1205 g_free (cpe->other);
1206 if (cpe->language)
1207 g_free (cpe->language);
1208}
1209
1215static void
1216trim_pct (char *str)
1217{
1218 char *c;
1219
1220 if (!str)
1221 return;
1222 c = str + strlen (str) - 1;
1223 while (c >= str)
1224 {
1225 if (*c == ':')
1226 {
1227 *c = '\0';
1228 c--;
1229 }
1230 else
1231 break;
1232 }
1233}
1234
1241static void
1242get_code (char *code, const char *str)
1243{
1244 code[0] = *str;
1245 code[1] = *(str + 1);
1246 code[2] = *(str + 2);
1247 code[3] = '\0';
1248}
1249
1262gboolean
1264{
1265 enum set_relation relation;
1266
1267 relation = compare_component (source->part, target->part);
1268 if (relation != SUPERSET && relation != EQUAL)
1269 return (FALSE);
1270 relation = compare_component (source->vendor, target->vendor);
1271 if (relation != SUPERSET && relation != EQUAL)
1272 return (FALSE);
1273 relation = compare_component (source->product, target->product);
1274 if (relation != SUPERSET && relation != EQUAL)
1275 return (FALSE);
1276 relation = compare_component (source->version, target->version);
1277 if (relation != SUPERSET && relation != EQUAL)
1278 return (FALSE);
1279 relation = compare_component (source->update, target->update);
1280 if (relation != SUPERSET && relation != EQUAL)
1281 return (FALSE);
1282 relation = compare_component (source->edition, target->edition);
1283 if (relation != SUPERSET && relation != EQUAL)
1284 return (FALSE);
1285 relation = compare_component (source->sw_edition, target->sw_edition);
1286 if (relation != SUPERSET && relation != EQUAL)
1287 return (FALSE);
1288 relation = compare_component (source->target_sw, target->target_sw);
1289 if (relation != SUPERSET && relation != EQUAL)
1290 return (FALSE);
1291 relation = compare_component (source->target_hw, target->target_hw);
1292 if (relation != SUPERSET && relation != EQUAL)
1293 return (FALSE);
1294 relation = compare_component (source->other, target->other);
1295 if (relation != SUPERSET && relation != EQUAL)
1296 return (FALSE);
1297 relation = compare_component (source->language, target->language);
1298 if (relation != SUPERSET && relation != EQUAL)
1299 return (FALSE);
1300
1301 return (TRUE);
1302}
1303
1317gboolean
1319{
1320 enum set_relation relation;
1321
1322 relation = compare_component (source->update, target->update);
1323 if (relation != SUPERSET && relation != EQUAL)
1324 return (FALSE);
1325 relation = compare_component (source->edition, target->edition);
1326 if (relation != SUPERSET && relation != EQUAL)
1327 return (FALSE);
1328 relation = compare_component (source->sw_edition, target->sw_edition);
1329 if (relation != SUPERSET && relation != EQUAL)
1330 return (FALSE);
1331 relation = compare_component (source->target_sw, target->target_sw);
1332 if (relation != SUPERSET && relation != EQUAL)
1333 return (FALSE);
1334 relation = compare_component (source->target_hw, target->target_hw);
1335 if (relation != SUPERSET && relation != EQUAL)
1336 return (FALSE);
1337 relation = compare_component (source->other, target->other);
1338 if (relation != SUPERSET && relation != EQUAL)
1339 return (FALSE);
1340 relation = compare_component (source->language, target->language);
1341 if (relation != SUPERSET && relation != EQUAL)
1342 return (FALSE);
1343
1344 return (TRUE);
1345}
1346
1358static enum set_relation
1359compare_component (const char *source, const char *target)
1360{
1361 enum set_relation result;
1362 char *source_cpy, *target_cpy;
1363 char *c;
1364
1365 if (source)
1366 source_cpy = g_strdup (source);
1367 else
1368 source_cpy = g_strdup ("ANY");
1369 if (target)
1370 target_cpy = g_strdup (target);
1371 else
1372 target_cpy = g_strdup ("ANY");
1373
1374 if (is_string (source_cpy))
1375 {
1376 /* set all characters to lowercase */
1377 for (c = source_cpy; *c; c++)
1378 *c = tolower (*c);
1379 }
1380 if (is_string (target_cpy))
1381 {
1382 /* set all characters to lowercase */
1383 for (c = target_cpy; *c; c++)
1384 *c = tolower (*c);
1385 }
1386 if (is_string (target_cpy) && has_wildcards (target_cpy))
1387 {
1388 g_free (source_cpy);
1389 g_free (target_cpy);
1390 return (UNDEFINED);
1391 }
1392 if (strcmp (source_cpy, target_cpy) == 0)
1393 {
1394 g_free (source_cpy);
1395 g_free (target_cpy);
1396 return (EQUAL);
1397 }
1398 if (strcmp (source_cpy, "ANY") == 0)
1399 {
1400 g_free (source_cpy);
1401 g_free (target_cpy);
1402 return (SUPERSET);
1403 }
1404 if (strcmp (target_cpy, "ANY") == 0)
1405 {
1406 g_free (source_cpy);
1407 g_free (target_cpy);
1408 return (SUBSET);
1409 }
1410 if (strcmp (target_cpy, "NA") == 0 || strcmp (source_cpy, "NA") == 0)
1411 {
1412 g_free (source_cpy);
1413 g_free (target_cpy);
1414 return (DISJOINT);
1415 }
1416
1417 result = compare_strings (source_cpy, target_cpy);
1418 g_free (source_cpy);
1419 g_free (target_cpy);
1420 return (result);
1421}
1422
1435static enum set_relation
1436compare_strings (const char *source, const char *target)
1437{
1438 int start = 0;
1439 int end = strlen (source);
1440 int begins = 0;
1441 int ends = 0;
1442
1443 char *sub_source;
1444
1445 if (*source == '*')
1446 {
1447 start = 1;
1448 begins = -1;
1449 }
1450 else
1451 {
1452 while (start < (int) strlen (source) && *(source + start) == '?')
1453 {
1454 start++;
1455 begins++;
1456 }
1457 }
1458 if (*(source + end - 1) == '*' && is_even_wildcards (source, end - 1))
1459 {
1460 end--;
1461 ends = -1;
1462 }
1463 else
1464 {
1465 while (end > 0 && *(source + end - 1) == '?'
1466 && is_even_wildcards (source, end - 1))
1467 {
1468 end--;
1469 ends++;
1470 }
1471 }
1472
1473 sub_source = g_strndup (source + start, end - start);
1474 int index = -1;
1475 int escapes = 0;
1476 int leftover = strlen (target);
1477
1478 while (leftover > 0)
1479 {
1480 index = index_of (target, sub_source, index + 1);
1481 if (index == -1)
1482 break;
1483 escapes = count_escapes (target, 0, index);
1484 if (index > 0 && begins != -1 && begins < (index - escapes))
1485 break;
1486 escapes = count_escapes (target, index + 1, strlen (target));
1487 leftover = strlen (target) - index - escapes - strlen (sub_source);
1488 if (leftover > 0 && (ends != -1 && leftover > ends))
1489 continue;
1490 g_free (sub_source);
1491 return SUPERSET;
1492 }
1493 g_free (sub_source);
1494 return DISJOINT;
1495}
1496
1510static int
1511count_escapes (const char *str, int start, int end)
1512{
1513 int result = 0;
1514 gboolean active = FALSE;
1515
1516 for (int i = 0; i < end && *(str + i) != '\0'; i++)
1517 {
1518 active = (!active && *(str + i) == '\\');
1519 if (active && i >= start)
1520 result++;
1521 }
1522 return (result);
1523}
1524
1535static gboolean
1536is_even_wildcards (const char *str, int index)
1537{
1538 int result = 0;
1539
1540 while (index > 0 && *(str + index - 1) == '\\')
1541 {
1542 index--;
1543 result++;
1544 }
1545 return ((result % 2) == 0);
1546}
1547
1555static gboolean
1556has_wildcards (const char *str)
1557{
1558 char *c = (char *) str;
1559 gboolean active = FALSE;
1560
1561 while (*c != '\0')
1562 {
1563 if (!active && (*c == '?' || *c == '*'))
1564 return TRUE;
1565
1566 if (!active && *c == '\\')
1567 active = TRUE;
1568 else
1569 active = FALSE;
1570
1571 c++;
1572 }
1573 return FALSE;
1574}
1575
1587static int
1588index_of (const char *str, const char *sub_str, int offset)
1589{
1590 char *start;
1591 char *begin_substr;
1592
1593 if (offset > (int) strlen (str))
1594 return (-1);
1595
1596 start = (char *) str + offset;
1597 begin_substr = strstr (start, sub_str);
1598 if (begin_substr == NULL)
1599 return (-1);
1600 return (begin_substr - str);
1601}
1602
1612static gboolean
1613is_string (const char *str)
1614{
1615 if (!str)
1616 return TRUE;
1617
1618 return (strcmp (str, "ANY") && strcmp (str, "NA"));
1619}
char * fs_cpe_to_uri_cpe(const char *fs_cpe)
Convert a formatted string CPE to a URI CPE.
Definition cpeutils.c:140
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:1263
static char * bind_cpe_component_for_fs(const char *)
Bind a CPE component for a formatted string CPE.
Definition cpeutils.c:1092
gboolean cpe_struct_match_tail(cpe_struct_t *source, cpe_struct_t *target)
Returns if the part behind the version of source is a match for that part of target....
Definition cpeutils.c:1318
char * uri_cpe_to_fs_cpe(const char *uri_cpe)
Convert a URI CPE to a formatted string CPE.
Definition cpeutils.c:100
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:1436
static char * bind_cpe_component_for_uri(const char *)
Bind a CPE component for a URI CPE.
Definition cpeutils.c:957
static char * get_fs_component(const char *, int)
Get the indexth component of a formatted string CPE.
Definition cpeutils.c:781
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:1536
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:1359
char * fs_cpe_to_uri_product(const char *fs_cpe)
Convert a formatted string CPE to an URI product.
Definition cpeutils.c:160
static void get_code(char *, const char *)
Get the percent code from the start of a string.
Definition cpeutils.c:1242
static void unpack_sixth_uri_component(const char *, cpe_struct_t *)
Unpack the sixth component of a URI CPE.
Definition cpeutils.c:699
char * cpe_struct_to_fs_cpe(const cpe_struct_t *cpe)
Convert a CPE struct into a formatted string CPE.
Definition cpeutils.c:382
static char * unbind_fs_component(char *)
Unbind a formatted string CPE component.
Definition cpeutils.c:837
static char * get_uri_component(const char *, int)
Get the indexth component of a URI CPE.
Definition cpeutils.c:516
static char * decode_uri_component(const char *)
Decode a component of a URI CPE.
Definition cpeutils.c:566
static char * process_quoted_chars(const char *)
Process the quoted characters of a CPE component for a formatted string CPE.
Definition cpeutils.c:1114
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:346
static char * add_quoting(const char *)
Handle the quoting for an unbind formatted string CPE component.
Definition cpeutils.c:866
char * cpe_struct_to_uri_product(const cpe_struct_t *cpe)
Convert a CPE struct into a URI product.
Definition cpeutils.c:289
char * cpe_struct_to_uri_cpe(const cpe_struct_t *cpe)
Convert a CPE struct into a URI CPE.
Definition cpeutils.c:220
void cpe_struct_init(cpe_struct_t *cpe)
Initialize a CPE struct.
Definition cpeutils.c:1158
char * cpe_struct_to_fs_product(const cpe_struct_t *cpe)
Convert a CPE struct into a formatted string product.
Definition cpeutils.c:476
char * get_version_from_uri_cpe(const char *uri_cpe)
Get the version from an uri cpe.
Definition cpeutils.c:330
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:1588
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:1613
void cpe_struct_free(cpe_struct_t *cpe)
Free a CPE struct.
Definition cpeutils.c:1182
static char * pack_sixth_uri_component(const cpe_struct_t *)
Pack the sixth component of a URI CPE.
Definition cpeutils.c:1041
static char * transform_for_uri(const char *)
Transform a CPE component for a URI CPE.
Definition cpeutils.c:978
static gboolean has_wildcards(const char *)
Returns if a given string contains wildcards ("*" or "?").
Definition cpeutils.c:1556
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:180
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:1511
static void trim_pct(char *)
Cut of trailing ':' signs.
Definition cpeutils.c:1216
char * uri_cpe_to_fs_product(const char *uri_cpe)
Convert a URI CPE to a formatted string product.
Definition cpeutils.c:120
Headers for CPE utils.
set_relation
Definition cpeutils.h:83
@ SUBSET
Definition cpeutils.h:86
@ DISJOINT
Definition cpeutils.h:84
@ EQUAL
Definition cpeutils.h:85
@ UNDEFINED
Definition cpeutils.h:88
@ SUPERSET
Definition cpeutils.h:87
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