Greenbone Vulnerability Management Libraries 22.41.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
17
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 *
140uri_cpe_to_uri_product (const char *uri_cpe)
141{
142 cpe_struct_t cpe;
143 char *fs_cpe;
144
145 cpe_struct_init (&cpe);
146 uri_cpe_to_cpe_struct (uri_cpe, &cpe);
147 fs_cpe = cpe_struct_to_uri_product (&cpe);
148 cpe_struct_free (&cpe);
149 return fs_cpe;
150}
151
159char *
160fs_cpe_to_uri_cpe (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_cpe (&cpe);
168 cpe_struct_free (&cpe);
169 return uri_cpe;
170}
171
179char *
180fs_cpe_to_uri_product (const char *fs_cpe)
181{
182 cpe_struct_t cpe;
183 char *uri_cpe;
184
185 cpe_struct_init (&cpe);
186 fs_cpe_to_cpe_struct (fs_cpe, &cpe);
187 uri_cpe = cpe_struct_to_uri_product (&cpe);
188 cpe_struct_free (&cpe);
189 return uri_cpe;
190}
191
199void
200uri_cpe_to_cpe_struct (const char *uri_cpe, cpe_struct_t *cpe)
201{
202 char *uri_component;
203
204 uri_component = get_uri_component (uri_cpe, 1);
205 cpe->part = decode_uri_component (uri_component);
206 g_free (uri_component);
207 uri_component = get_uri_component (uri_cpe, 2);
208 cpe->vendor = decode_uri_component (uri_component);
209 g_free (uri_component);
210 uri_component = get_uri_component (uri_cpe, 3);
211 cpe->product = decode_uri_component (uri_component);
212 g_free (uri_component);
213 uri_component = get_uri_component (uri_cpe, 4);
214 cpe->version = decode_uri_component (uri_component);
215 g_free (uri_component);
216 uri_component = get_uri_component (uri_cpe, 5);
217 cpe->update = decode_uri_component (uri_component);
218 g_free (uri_component);
219 uri_component = get_uri_component (uri_cpe, 6);
220 if (strcmp (uri_component, "") == 0 || strcmp (uri_component, "-") == 0
221 || *uri_component != '~')
222 cpe->edition = decode_uri_component (uri_component);
223 else
224 unpack_sixth_uri_component (uri_component, cpe);
225 g_free (uri_component);
226
227 uri_component = get_uri_component (uri_cpe, 7);
228 cpe->language = decode_uri_component (uri_component);
229 g_free (uri_component);
230}
231
239char *
241{
242 GString *uri_cpe;
243 char *bind_cpe_component;
244 uri_cpe = g_string_new ("cpe:/");
245
246 bind_cpe_component = bind_cpe_component_for_uri (cpe->part);
247 if (bind_cpe_component)
248 {
249 g_string_append (uri_cpe, bind_cpe_component);
250 g_string_append_c (uri_cpe, ':');
251 g_free (bind_cpe_component);
252 }
253 bind_cpe_component = bind_cpe_component_for_uri (cpe->vendor);
254 if (bind_cpe_component)
255 {
256 g_string_append (uri_cpe, bind_cpe_component);
257 g_string_append_c (uri_cpe, ':');
258 g_free (bind_cpe_component);
259 }
260 bind_cpe_component = bind_cpe_component_for_uri (cpe->product);
261 if (bind_cpe_component)
262 {
263 g_string_append (uri_cpe, bind_cpe_component);
264 g_string_append_c (uri_cpe, ':');
265 g_free (bind_cpe_component);
266 }
267 bind_cpe_component = bind_cpe_component_for_uri (cpe->version);
268 if (bind_cpe_component)
269 {
270 g_string_append (uri_cpe, bind_cpe_component);
271 g_string_append_c (uri_cpe, ':');
272 g_free (bind_cpe_component);
273 }
274 bind_cpe_component = bind_cpe_component_for_uri (cpe->update);
275 if (bind_cpe_component)
276 {
277 g_string_append (uri_cpe, bind_cpe_component);
278 g_string_append_c (uri_cpe, ':');
279 g_free (bind_cpe_component);
280 }
281 bind_cpe_component = pack_sixth_uri_component (cpe);
282 if (bind_cpe_component)
283 {
284 g_string_append (uri_cpe, bind_cpe_component);
285 g_string_append_c (uri_cpe, ':');
286 g_free (bind_cpe_component);
287 }
288 bind_cpe_component = bind_cpe_component_for_uri (cpe->language);
289 if (bind_cpe_component)
290 {
291 g_string_append (uri_cpe, bind_cpe_component);
292 g_string_append_c (uri_cpe, ':');
293 g_free (bind_cpe_component);
294 }
295
296 char *result = g_string_free (uri_cpe, FALSE);
297 trim_pct (result);
298 return result;
299}
300
308char *
310{
311 GString *uri_cpe;
312 char *bind_cpe_component;
313 uri_cpe = g_string_new ("cpe:/");
314
315 bind_cpe_component = bind_cpe_component_for_uri (cpe->part);
316 if (bind_cpe_component)
317 {
318 g_string_append (uri_cpe, bind_cpe_component);
319 g_string_append_c (uri_cpe, ':');
320 g_free (bind_cpe_component);
321 }
322 bind_cpe_component = bind_cpe_component_for_uri (cpe->vendor);
323 if (bind_cpe_component)
324 {
325 g_string_append (uri_cpe, bind_cpe_component);
326 g_string_append_c (uri_cpe, ':');
327 g_free (bind_cpe_component);
328 }
329 bind_cpe_component = bind_cpe_component_for_uri (cpe->product);
330 if (bind_cpe_component)
331 {
332 g_string_append (uri_cpe, bind_cpe_component);
333 g_string_append_c (uri_cpe, ':');
334 g_free (bind_cpe_component);
335 }
336
337 char *result = g_string_free (uri_cpe, FALSE);
338 trim_pct (result);
339 return result;
340}
341
349char *
350get_version_from_uri_cpe (const char *uri_cpe)
351{
352 char *version = get_uri_component (uri_cpe, 4);
353 char *decoded_version = decode_uri_component (version);
354 g_free (version);
355 return decoded_version;
356}
357
365void
366fs_cpe_to_cpe_struct (const char *fs_cpe, cpe_struct_t *cpe)
367{
368 char *fs_component;
369
370 fs_component = get_fs_component (fs_cpe, 2);
371 cpe->part = unbind_fs_component (fs_component);
372 fs_component = get_fs_component (fs_cpe, 3);
373 cpe->vendor = unbind_fs_component (fs_component);
374 fs_component = get_fs_component (fs_cpe, 4);
375 cpe->product = unbind_fs_component (fs_component);
376 fs_component = get_fs_component (fs_cpe, 5);
377 cpe->version = unbind_fs_component (fs_component);
378 fs_component = get_fs_component (fs_cpe, 6);
379 cpe->update = unbind_fs_component (fs_component);
380 fs_component = get_fs_component (fs_cpe, 7);
381 cpe->edition = unbind_fs_component (fs_component);
382 fs_component = get_fs_component (fs_cpe, 8);
383 cpe->language = unbind_fs_component (fs_component);
384 fs_component = get_fs_component (fs_cpe, 9);
385 cpe->sw_edition = unbind_fs_component (fs_component);
386 fs_component = get_fs_component (fs_cpe, 10);
387 cpe->target_sw = unbind_fs_component (fs_component);
388 fs_component = get_fs_component (fs_cpe, 11);
389 cpe->target_hw = unbind_fs_component (fs_component);
390 fs_component = get_fs_component (fs_cpe, 12);
391 cpe->other = unbind_fs_component (fs_component);
392}
393
401char *
403{
404 GString *fs_cpe;
405 char *bind_cpe_component;
406
407 fs_cpe = g_string_new ("cpe:2.3:");
408
409 bind_cpe_component = bind_cpe_component_for_fs (cpe->part);
410 if (bind_cpe_component)
411 {
412 g_string_append (fs_cpe, bind_cpe_component);
413 g_string_append_c (fs_cpe, ':');
414 g_free (bind_cpe_component);
415 }
416 bind_cpe_component = bind_cpe_component_for_fs (cpe->vendor);
417 if (bind_cpe_component)
418 {
419 g_string_append (fs_cpe, bind_cpe_component);
420 g_string_append_c (fs_cpe, ':');
421 g_free (bind_cpe_component);
422 }
423 bind_cpe_component = bind_cpe_component_for_fs (cpe->product);
424 if (bind_cpe_component)
425 {
426 g_string_append (fs_cpe, bind_cpe_component);
427 g_string_append_c (fs_cpe, ':');
428 g_free (bind_cpe_component);
429 }
430 bind_cpe_component = bind_cpe_component_for_fs (cpe->version);
431 if (bind_cpe_component)
432 {
433 g_string_append (fs_cpe, bind_cpe_component);
434 g_string_append_c (fs_cpe, ':');
435 g_free (bind_cpe_component);
436 }
437 bind_cpe_component = bind_cpe_component_for_fs (cpe->update);
438 if (bind_cpe_component)
439 {
440 g_string_append (fs_cpe, bind_cpe_component);
441 g_string_append_c (fs_cpe, ':');
442 g_free (bind_cpe_component);
443 }
444 bind_cpe_component = bind_cpe_component_for_fs (cpe->edition);
445 if (bind_cpe_component)
446 {
447 g_string_append (fs_cpe, bind_cpe_component);
448 g_string_append_c (fs_cpe, ':');
449 g_free (bind_cpe_component);
450 }
451 bind_cpe_component = bind_cpe_component_for_fs (cpe->language);
452 if (bind_cpe_component)
453 {
454 g_string_append (fs_cpe, bind_cpe_component);
455 g_string_append_c (fs_cpe, ':');
456 g_free (bind_cpe_component);
457 }
458 bind_cpe_component = bind_cpe_component_for_fs (cpe->sw_edition);
459 if (bind_cpe_component)
460 {
461 g_string_append (fs_cpe, bind_cpe_component);
462 g_string_append_c (fs_cpe, ':');
463 g_free (bind_cpe_component);
464 }
465 bind_cpe_component = bind_cpe_component_for_fs (cpe->target_sw);
466 if (bind_cpe_component)
467 {
468 g_string_append (fs_cpe, bind_cpe_component);
469 g_string_append_c (fs_cpe, ':');
470 g_free (bind_cpe_component);
471 }
472 bind_cpe_component = bind_cpe_component_for_fs (cpe->target_hw);
473 if (bind_cpe_component)
474 {
475 g_string_append (fs_cpe, bind_cpe_component);
476 g_string_append_c (fs_cpe, ':');
477 g_free (bind_cpe_component);
478 }
479 bind_cpe_component = bind_cpe_component_for_fs (cpe->other);
480 if (bind_cpe_component)
481 {
482 g_string_append (fs_cpe, bind_cpe_component);
483 g_free (bind_cpe_component);
484 }
485 return (g_string_free (fs_cpe, FALSE));
486}
487
495char *
497{
498 GString *fs_cpe;
499 char *bind_cpe_component;
500
501 fs_cpe = g_string_new ("cpe:2.3:");
502
503 bind_cpe_component = bind_cpe_component_for_fs (cpe->part);
504 if (bind_cpe_component)
505 {
506 g_string_append (fs_cpe, bind_cpe_component);
507 g_string_append_c (fs_cpe, ':');
508 g_free (bind_cpe_component);
509 }
510 bind_cpe_component = bind_cpe_component_for_fs (cpe->vendor);
511 if (bind_cpe_component)
512 {
513 g_string_append (fs_cpe, bind_cpe_component);
514 g_string_append_c (fs_cpe, ':');
515 g_free (bind_cpe_component);
516 }
517 bind_cpe_component = bind_cpe_component_for_fs (cpe->product);
518 if (bind_cpe_component)
519 {
520 g_string_append (fs_cpe, bind_cpe_component);
521 g_string_append_c (fs_cpe, ':');
522 g_free (bind_cpe_component);
523 }
524 return (g_string_free (fs_cpe, FALSE));
525}
526
535static char *
536get_uri_component (const char *uri_cpe, int index)
537{
538 char *component = NULL;
539 char *c;
540 char *component_start, *component_end;
541
542 if (!uri_cpe)
543 return NULL;
544
545 c = (char *) uri_cpe;
546
547 /* find start of component */
548 for (int i = 0; *c != '\0' && i < index; c++)
549 {
550 if (*c == ':')
551 i++;
552 }
553
554 if (index == 1 && *c != '\0')
555 c++;
556
557 component_start = c;
558
559 /* find end of component */
560 if (*component_start == '\0')
561 component_end = component_start;
562 else
563 {
564 for (c = component_start; *c != '\0' && *c != ':'; c++)
565 ;
566 }
567
568 component_end = c;
569
570 if (component_start >= component_end || component_end == 0)
571 component = (char *) g_strdup ("");
572 else
573 component = g_strndup (component_start, component_end - component_start);
574
575 return component;
576}
577
585static char *
586decode_uri_component (const char *component)
587{
588 GString *decoded_component;
589 char *escapes = "!\"#$%&'()*+,/:;<=>?@[\\]^`{|}~";
590 char *tmp_component;
591 char code_a[4], code_b[4], code_c[4];
592 long unsigned int index;
593 gboolean embedded;
594
595 if (!component)
596 return NULL;
597
598 if (strcmp (component, "") == 0 || strcmp (component, " ") == 0)
599 {
600 return (g_strdup ("ANY"));
601 }
602 if (strcmp (component, "-") == 0)
603 {
604 return (g_strdup ("NA"));
605 }
606
607 tmp_component = g_strdup (component);
608
609 /* set all characters to lowercase */
610 char *c = tmp_component;
611 for (; *c; c++)
612 *c = tolower (*c);
613
614 index = 0;
615 embedded = FALSE;
616 decoded_component = g_string_sized_new (2 * strlen (component));
617
618 char l;
619 char *unescaped;
620 while (index < strlen (tmp_component))
621 {
622 l = *(tmp_component + index);
623
624 if (l == '.' || l == '-' || l == '~')
625 {
626 g_string_append_c (decoded_component, '\\');
627 g_string_append_c (decoded_component, l);
628 index++;
629 embedded = TRUE;
630 continue;
631 }
632 if (l != '%')
633 {
634 g_string_append_c (decoded_component, l);
635 index++;
636 embedded = TRUE;
637 continue;
638 }
639
640 get_code (code_a, tmp_component + index);
641
642 if (strcmp (code_a, "%01") == 0)
643 {
644 if (index >= 3)
645 get_code (code_b, tmp_component + index - 3);
646 else
647 code_b[0] = '0';
648 if (strlen (tmp_component) >= index + 6)
649 get_code (code_c, tmp_component + index + 3);
650 else
651 code_c[0] = '0';
652 if ((index == 0 || index == strlen (tmp_component) - 3)
653 || (!embedded && strcmp (code_b, "%01"))
654 || (embedded && strcmp (code_c, "%01")))
655 {
656 g_string_append_c (decoded_component, '?');
657 index = index + 3;
658 continue;
659 }
660 else
661 {
662 g_string_free (decoded_component, TRUE);
663 g_free (tmp_component);
664 return NULL;
665 }
666 }
667
668 if (strcmp (code_a, "%02") == 0)
669 {
670 if (index == 0 || index == strlen (tmp_component) - 3)
671 {
672 g_string_append_c (decoded_component, '*');
673 index = index + 3;
674 continue;
675 }
676 else
677 {
678 g_string_free (decoded_component, TRUE);
679 g_free (tmp_component);
680 return NULL;
681 }
682 }
683
684 unescaped = g_uri_unescape_string (code_a, NULL);
685 if (unescaped && strchr (escapes, *unescaped))
686 {
687 g_string_append_c (decoded_component, '\\');
688 g_string_append (decoded_component, unescaped);
689 g_free (unescaped);
690 }
691 else if (unescaped)
692 {
693 g_string_append (decoded_component, unescaped);
694 g_free (unescaped);
695 }
696 else
697 {
698 g_string_free (decoded_component, TRUE);
699 g_free (tmp_component);
700 return NULL;
701 }
702 index = index + 3;
703 embedded = TRUE;
704 }
705
706 g_free (tmp_component);
707 return (g_string_free (decoded_component, FALSE));
708}
709
718static void
719unpack_sixth_uri_component (const char *component, cpe_struct_t *cpe)
720{
721 const char *start = component + 1;
722 const char *end;
723
724 char *edition, *sw_edition, *target_sw, *target_hw, *other;
725
726 end = strchr (start, '~');
727 if (start >= end || end == NULL)
728 edition = strdup ("");
729 else
730 edition = g_strndup (start, end - start);
731
732 if (end != NULL)
733 {
734 start = end + 1;
735 end = strchr (start, '~');
736 if (start >= end || end == NULL)
737 sw_edition = strdup ("");
738 else
739 sw_edition = g_strndup (start, end - start);
740 }
741 else
742 sw_edition = strdup ("");
743
744 if (end != NULL)
745 {
746 start = end + 1;
747 end = strchr (start, '~');
748 if (start >= end || end == NULL)
749 target_sw = strdup ("");
750 else
751 target_sw = g_strndup (start, end - start);
752 }
753 else
754 target_sw = strdup ("");
755
756 if (end != NULL)
757 {
758 start = end + 1;
759 end = strchr (start, '~');
760 if (start >= end || end == NULL)
761 target_hw = strdup ("");
762 else
763 target_hw = g_strndup (start, end - start);
764 }
765 else
766 target_hw = strdup ("");
767
768 if (end != NULL)
769 {
770 start = end + 1;
771 end = component + strlen (component);
772 if (start >= end)
773 other = strdup ("");
774 else
775 other = g_strndup (start, end - start);
776 }
777 else
778 other = strdup ("");
779
780 cpe->edition = decode_uri_component (edition);
781 g_free (edition);
782 cpe->sw_edition = decode_uri_component (sw_edition);
783 g_free (sw_edition);
784 cpe->target_sw = decode_uri_component (target_sw);
785 g_free (target_sw);
786 cpe->target_hw = decode_uri_component (target_hw);
787 g_free (target_hw);
788 cpe->other = decode_uri_component (other);
789 g_free (other);
790}
791
800static char *
801get_fs_component (const char *fs_cpe, int index)
802{
803 char *component = NULL;
804 char *c;
805 char *component_start, *component_end;
806 gboolean escaped;
807
808 if (!fs_cpe)
809 return NULL;
810
811 if (*fs_cpe == '\0')
812 return ((char *) g_strdup (""));
813
814 c = (char *) fs_cpe;
815
816 /* find start of component */
817 escaped = FALSE;
818 if (index == 0)
819 component_start = c;
820 else
821 {
822 for (int i = 0; *c != '\0' && i < index; c++)
823 {
824 if (*c == ':' && !escaped)
825 i++;
826 else if (*c == '\\' && !escaped)
827 escaped = TRUE;
828 else
829 escaped = FALSE;
830 }
831 component_start = c;
832 }
833
834 /* find end of component */
835 escaped = FALSE;
836 if (*component_start == '\0')
837 component_end = component_start;
838 else
839 {
840 for (c = component_start; *c != '\0'; c++)
841 {
842 if (*c == ':' && !escaped)
843 break;
844 if (*c == '\\' && !escaped)
845 escaped = TRUE;
846 else
847 escaped = FALSE;
848 }
849 }
850
851 component_end = c;
852
853 if (component_start >= component_end || component_end == NULL)
854 component = (char *) g_strdup ("");
855 else
856 component = g_strndup (component_start, component_end - component_start);
857
858 return component;
859}
860
868static char *
869unbind_fs_component (char *component)
870{
871 char *unbound_component;
872
873 if (strcmp (component, "*") == 0)
874 {
875 g_free (component);
876 return ((char *) g_strdup ("ANY"));
877 }
878 if (strcmp (component, "-") == 0)
879 {
880 g_free (component);
881 return ((char *) g_strdup ("NA"));
882 }
883
884 unbound_component = add_quoting (component);
885 g_free (component);
886 return unbound_component;
887}
888
897static char *
898add_quoting (const char *component)
899{
900 GString *quoted_component;
901 char *tmp_component;
902 char *c;
903 gboolean embedded;
904
905 if (!component)
906 return NULL;
907
908 quoted_component = g_string_sized_new (2 * strlen (component));
909 tmp_component = (char *) g_strdup (component);
910 embedded = FALSE;
911
912 /* set all characters to lowercase */
913 for (c = tmp_component; *c; c++)
914 *c = tolower (*c);
915
916 c = tmp_component;
917 while (*c != '\0')
918 {
919 if (g_ascii_isalnum (*c) || *c == '_')
920 {
921 g_string_append_c (quoted_component, *c);
922 c++;
923 embedded = TRUE;
924 continue;
925 }
926 if (*c == '\\')
927 {
928 c++;
929 if (*c != '\0')
930 {
931 g_string_append_c (quoted_component, '\\');
932 g_string_append_c (quoted_component, *c);
933 embedded = TRUE;
934 c++;
935 continue;
936 }
937 }
938 if (*c == '*')
939 {
940 if ((c == tmp_component)
941 || (c == tmp_component + strlen (tmp_component - 1)))
942 {
943 g_string_append_c (quoted_component, *c);
944 c++;
945 embedded = TRUE;
946 continue;
947 }
948 else
949 {
950 g_free (tmp_component);
951 return NULL;
952 }
953 }
954 if (*c == '?')
955 {
956 if ((c == tmp_component)
957 || (c == tmp_component + strlen (tmp_component - 1))
958 || (!embedded && (c > tmp_component) && (*(c - 1) == '?'))
959 || (embedded && *(c + 1) == '?'))
960 {
961 g_string_append_c (quoted_component, *c);
962 c++;
963 embedded = FALSE;
964 continue;
965 }
966 else
967 {
968 g_free (tmp_component);
969 return NULL;
970 }
971 }
972 g_string_append_c (quoted_component, '\\');
973 g_string_append_c (quoted_component, *c);
974 c++;
975 embedded = TRUE;
976 }
977 g_free (tmp_component);
978 return (g_string_free (quoted_component, FALSE));
979}
980
988static char *
989bind_cpe_component_for_uri (const char *component)
990{
991 if (!component)
992 return (g_strdup (""));
993 if (strcmp (component, "") == 0)
994 return (g_strdup (""));
995 if (strcmp (component, "ANY") == 0)
996 return (g_strdup (""));
997 if (strcmp (component, "NA") == 0)
998 return (g_strdup ("-"));
999 return (transform_for_uri (component));
1000}
1001
1009static char *
1010transform_for_uri (const char *component)
1011{
1012 GString *result;
1013 char *tmp_component;
1014 char *c;
1015
1016 if (!component)
1017 return (g_strdup (""));
1018 if (strcmp (component, "") == 0)
1019 return (g_strdup (""));
1020
1021 tmp_component = g_strdup (component);
1022
1023 /* set all characters to lowercase */
1024 for (c = tmp_component; *c; c++)
1025 *c = tolower (*c);
1026
1027 result = g_string_new ("");
1028 c = tmp_component;
1029
1030 while (*c)
1031 {
1032 if ((g_ascii_isalnum (*c) || *c == '_') && *c != '-')
1033 {
1034 g_string_append_c (result, *c);
1035 c++;
1036 continue;
1037 }
1038 if (*c == '\\')
1039 {
1040 c++;
1041 if (*c != '\0')
1042 {
1043 char to_escape[2];
1044 char *escaped;
1045 to_escape[0] = *c;
1046 to_escape[1] = '\0';
1047 escaped = g_uri_escape_string (to_escape, NULL, FALSE);
1048 g_string_append (result, escaped);
1049 g_free (escaped);
1050 c++;
1051 }
1052 continue;
1053 }
1054 if (*c == '?')
1055 g_string_append (result, "%01");
1056 if (*c == '*')
1057 g_string_append (result, "%02");
1058 c++;
1059 }
1060 g_free (tmp_component);
1061 return (g_string_free (result, FALSE));
1062}
1063
1071static char *
1073{
1074 if ((cpe->sw_edition == NULL || strcmp (cpe->sw_edition, "") == 0)
1075 && (cpe->target_sw == NULL || strcmp (cpe->target_sw, "") == 0)
1076 && (cpe->target_hw == NULL || strcmp (cpe->target_hw, "") == 0)
1077 && (cpe->other == NULL || strcmp (cpe->other, "") == 0))
1078 {
1079 if (strcmp (cpe->edition, "ANY") == 0)
1080 return (g_strdup (""));
1081 if (strcmp (cpe->edition, "NA") == 0)
1082 return (g_strdup ("-"));
1083 return (g_strdup (cpe->edition));
1084 }
1085
1086 char *edition = bind_cpe_component_for_uri (cpe->edition);
1087 char *sw_edition = bind_cpe_component_for_uri (cpe->sw_edition);
1088 char *target_sw = bind_cpe_component_for_uri (cpe->target_sw);
1089 char *target_hw = bind_cpe_component_for_uri (cpe->target_hw);
1090 char *other = bind_cpe_component_for_uri (cpe->other);
1091 GString *component;
1092 component = g_string_new ("");
1093 if (!((!sw_edition || strcmp (sw_edition, "") == 0)
1094 && (!target_sw || strcmp (target_sw, "") == 0)
1095 && (!target_hw || strcmp (target_hw, "") == 0)
1096 && (!other || strcmp (other, "") == 0)))
1097 g_string_append_printf (component, "~%s~%s~%s~%s~%s", edition, sw_edition,
1098 target_sw, target_hw, other);
1099 else if (edition)
1100 g_string_append (component, edition);
1101
1102 g_free (edition);
1103 g_free (sw_edition);
1104 g_free (target_sw);
1105 g_free (target_hw);
1106 g_free (other);
1107 return (g_string_free (component, FALSE));
1108}
1109
1117static char *
1118bind_cpe_component_for_fs (const char *component)
1119{
1120 if (!component)
1121 return (g_strdup ("*"));
1122 if (strcmp (component, "") == 0)
1123 return (g_strdup ("*"));
1124 if (strcmp (component, "ANY") == 0)
1125 return (g_strdup ("*"));
1126 if (strcmp (component, "NA") == 0)
1127 return (g_strdup ("-"));
1128 return (process_quoted_chars (component));
1129}
1130
1139static char *
1140process_quoted_chars (const char *component)
1141{
1142 if (!component)
1143 return (g_strdup (""));
1144 if (strcmp (component, "") == 0)
1145 return (g_strdup (""));
1146
1147 GString *fs_component;
1148 fs_component = g_string_new ("");
1149 char *c = (char *) component;
1150 char next_c;
1151
1152 while (*c)
1153 {
1154 if (*c != '\\')
1155 {
1156 g_string_append_c (fs_component, *c);
1157 c++;
1158 }
1159 else
1160 {
1161 next_c = *(c + 1);
1162 if (next_c == '.' || next_c == '-' || next_c == '_')
1163 {
1164 g_string_append_c (fs_component, next_c);
1165 c += 2;
1166 }
1167 else if (next_c)
1168 {
1169 g_string_append_c (fs_component, '\\');
1170 g_string_append_c (fs_component, next_c);
1171 c += 2;
1172 }
1173 }
1174 }
1175 return (g_string_free (fs_component, FALSE));
1176}
1177
1183void
1185{
1186 cpe->part = NULL;
1187 cpe->vendor = NULL;
1188 cpe->product = NULL;
1189 cpe->version = NULL;
1190 cpe->update = NULL;
1191 cpe->edition = NULL;
1192 cpe->sw_edition = NULL;
1193 cpe->target_sw = NULL;
1194 cpe->target_hw = NULL;
1195 cpe->other = NULL;
1196 cpe->language = NULL;
1197
1198 /* to keep the compiler satisfied */
1199 cpe->part = cpe->part;
1200}
1201
1207void
1209{
1210 if (!cpe)
1211 return;
1212 g_free (cpe->part);
1213 g_free (cpe->vendor);
1214 g_free (cpe->product);
1215 g_free (cpe->version);
1216 g_free (cpe->update);
1217 g_free (cpe->edition);
1218 g_free (cpe->sw_edition);
1219 g_free (cpe->target_sw);
1220 g_free (cpe->target_hw);
1221 g_free (cpe->other);
1222 g_free (cpe->language);
1223}
1224
1230static void
1231trim_pct (char *str)
1232{
1233 char *c;
1234
1235 if (!str)
1236 return;
1237 c = str + strlen (str) - 1;
1238 while (c >= str)
1239 {
1240 if (*c == ':')
1241 {
1242 *c = '\0';
1243 c--;
1244 }
1245 else
1246 break;
1247 }
1248}
1249
1256static void
1257get_code (char *code, const char *str)
1258{
1259 code[0] = *str;
1260 code[1] = *(str + 1);
1261 code[2] = *(str + 2);
1262 code[3] = '\0';
1263}
1264
1277gboolean
1279{
1280 enum set_relation relation;
1281
1282 relation = compare_component (source->part, target->part);
1283 if (relation != SUPERSET && relation != EQUAL)
1284 return FALSE;
1285 relation = compare_component (source->vendor, target->vendor);
1286 if (relation != SUPERSET && relation != EQUAL)
1287 return FALSE;
1288 relation = compare_component (source->product, target->product);
1289 if (relation != SUPERSET && relation != EQUAL)
1290 return FALSE;
1291 relation = compare_component (source->version, target->version);
1292 if (relation != SUPERSET && relation != EQUAL)
1293 return FALSE;
1294 relation = compare_component (source->update, target->update);
1295 if (relation != SUPERSET && relation != EQUAL)
1296 return FALSE;
1297 relation = compare_component (source->edition, target->edition);
1298 if (relation != SUPERSET && relation != EQUAL)
1299 return FALSE;
1300 relation = compare_component (source->sw_edition, target->sw_edition);
1301 if (relation != SUPERSET && relation != EQUAL)
1302 return FALSE;
1303 relation = compare_component (source->target_sw, target->target_sw);
1304 if (relation != SUPERSET && relation != EQUAL)
1305 return FALSE;
1306 relation = compare_component (source->target_hw, target->target_hw);
1307 if (relation != SUPERSET && relation != EQUAL)
1308 return FALSE;
1309 relation = compare_component (source->other, target->other);
1310 if (relation != SUPERSET && relation != EQUAL)
1311 return FALSE;
1312 relation = compare_component (source->language, target->language);
1313 if (relation != SUPERSET && relation != EQUAL)
1314 return FALSE;
1315
1316 return TRUE;
1317}
1318
1332gboolean
1334{
1335 enum set_relation relation;
1336
1337 relation = compare_component (source->update, target->update);
1338 if (relation != SUPERSET && relation != EQUAL)
1339 return FALSE;
1340 relation = compare_component (source->edition, target->edition);
1341 if (relation != SUPERSET && relation != EQUAL)
1342 return FALSE;
1343 relation = compare_component (source->sw_edition, target->sw_edition);
1344 if (relation != SUPERSET && relation != EQUAL)
1345 return FALSE;
1346 relation = compare_component (source->target_sw, target->target_sw);
1347 if (relation != SUPERSET && relation != EQUAL)
1348 return FALSE;
1349 relation = compare_component (source->target_hw, target->target_hw);
1350 if (relation != SUPERSET && relation != EQUAL)
1351 return FALSE;
1352 relation = compare_component (source->other, target->other);
1353 if (relation != SUPERSET && relation != EQUAL)
1354 return FALSE;
1355 relation = compare_component (source->language, target->language);
1356 if (relation != SUPERSET && relation != EQUAL)
1357 return FALSE;
1358
1359 return TRUE;
1360}
1361
1373static enum set_relation
1374compare_component (const char *source, const char *target)
1375{
1376 enum set_relation result;
1377 char *source_cpy, *target_cpy;
1378 char *c;
1379
1380 if (source)
1381 source_cpy = g_strdup (source);
1382 else
1383 source_cpy = g_strdup ("ANY");
1384 if (target)
1385 target_cpy = g_strdup (target);
1386 else
1387 target_cpy = g_strdup ("ANY");
1388
1389 if (is_string (source_cpy))
1390 {
1391 /* set all characters to lowercase */
1392 for (c = source_cpy; *c; c++)
1393 *c = tolower (*c);
1394 }
1395 if (is_string (target_cpy))
1396 {
1397 /* set all characters to lowercase */
1398 for (c = target_cpy; *c; c++)
1399 *c = tolower (*c);
1400 }
1401 if (is_string (target_cpy) && has_wildcards (target_cpy))
1402 {
1403 g_free (source_cpy);
1404 g_free (target_cpy);
1405 return UNDEFINED;
1406 }
1407 if (strcmp (source_cpy, target_cpy) == 0)
1408 {
1409 g_free (source_cpy);
1410 g_free (target_cpy);
1411 return EQUAL;
1412 }
1413 if (strcmp (source_cpy, "ANY") == 0)
1414 {
1415 g_free (source_cpy);
1416 g_free (target_cpy);
1417 return SUPERSET;
1418 }
1419 if (strcmp (target_cpy, "ANY") == 0)
1420 {
1421 g_free (source_cpy);
1422 g_free (target_cpy);
1423 return SUBSET;
1424 }
1425 if (strcmp (target_cpy, "NA") == 0 || strcmp (source_cpy, "NA") == 0)
1426 {
1427 g_free (source_cpy);
1428 g_free (target_cpy);
1429 return DISJOINT;
1430 }
1431
1432 result = compare_strings (source_cpy, target_cpy);
1433 g_free (source_cpy);
1434 g_free (target_cpy);
1435 return result;
1436}
1437
1450static enum set_relation
1451compare_strings (const char *source, const char *target)
1452{
1453 int start = 0;
1454 int end = strlen (source);
1455 int begins = 0;
1456 int ends = 0;
1457
1458 char *sub_source;
1459
1460 if (*source == '*')
1461 {
1462 start = 1;
1463 begins = -1;
1464 }
1465 else
1466 {
1467 while (start < (int) strlen (source) && *(source + start) == '?')
1468 {
1469 start++;
1470 begins++;
1471 }
1472 }
1473 if (*(source + end - 1) == '*' && is_even_wildcards (source, end - 1))
1474 {
1475 end--;
1476 ends = -1;
1477 }
1478 else
1479 {
1480 while (end > 0 && *(source + end - 1) == '?'
1481 && is_even_wildcards (source, end - 1))
1482 {
1483 end--;
1484 ends++;
1485 }
1486 }
1487
1488 sub_source = g_strndup (source + start, end - start);
1489 int index = -1;
1490 int escapes = 0;
1491 int leftover = strlen (target);
1492
1493 while (leftover > 0)
1494 {
1495 index = index_of (target, sub_source, index + 1);
1496 if (index == -1)
1497 break;
1498 escapes = count_escapes (target, 0, index);
1499 if (index > 0 && begins != -1 && begins < (index - escapes))
1500 break;
1501 escapes = count_escapes (target, index + 1, strlen (target));
1502 leftover = strlen (target) - index - escapes - strlen (sub_source);
1503 if (leftover > 0 && (ends != -1 && leftover > ends))
1504 continue;
1505 g_free (sub_source);
1506 return SUPERSET;
1507 }
1508 g_free (sub_source);
1509 return DISJOINT;
1510}
1511
1525static int
1526count_escapes (const char *str, int start, int end)
1527{
1528 int result = 0;
1529 gboolean active = FALSE;
1530
1531 for (int i = 0; i < end && *(str + i) != '\0'; i++)
1532 {
1533 active = (!active && *(str + i) == '\\');
1534 if (active && i >= start)
1535 result++;
1536 }
1537 return result;
1538}
1539
1550static gboolean
1551is_even_wildcards (const char *str, int index)
1552{
1553 int result = 0;
1554
1555 while (index > 0 && *(str + index - 1) == '\\')
1556 {
1557 index--;
1558 result++;
1559 }
1560 return ((result % 2) == 0);
1561}
1562
1570static gboolean
1571has_wildcards (const char *str)
1572{
1573 char *c = (char *) str;
1574 gboolean active = FALSE;
1575
1576 while (*c != '\0')
1577 {
1578 if (!active && (*c == '?' || *c == '*'))
1579 return TRUE;
1580
1581 if (!active && *c == '\\')
1582 active = TRUE;
1583 else
1584 active = FALSE;
1585
1586 c++;
1587 }
1588 return FALSE;
1589}
1590
1602static int
1603index_of (const char *str, const char *sub_str, int offset)
1604{
1605 char *start;
1606 char *begin_substr;
1607
1608 if (offset > (int) strlen (str))
1609 return -1;
1610
1611 start = (char *) str + offset;
1612 begin_substr = strstr (start, sub_str);
1613 if (begin_substr == NULL)
1614 return -1;
1615 return begin_substr - str;
1616}
1617
1627static gboolean
1628is_string (const char *str)
1629{
1630 if (!str)
1631 return TRUE;
1632
1633 return (strcmp (str, "ANY") && strcmp (str, "NA"));
1634}
char * fs_cpe_to_uri_cpe(const char *fs_cpe)
Convert a formatted string CPE to a URI CPE.
Definition cpeutils.c:160
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:1278
static char * bind_cpe_component_for_fs(const char *)
Bind a CPE component for a formatted string CPE.
Definition cpeutils.c:1118
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:1333
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:1451
static char * bind_cpe_component_for_uri(const char *)
Bind a CPE component for a URI CPE.
Definition cpeutils.c:989
static char * get_fs_component(const char *, int)
Get the indexth component of a formatted string CPE.
Definition cpeutils.c:801
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:1551
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:1374
char * fs_cpe_to_uri_product(const char *fs_cpe)
Convert a formatted string CPE to an URI product.
Definition cpeutils.c:180
static void get_code(char *, const char *)
Get the percent code from the start of a string.
Definition cpeutils.c:1257
static void unpack_sixth_uri_component(const char *, cpe_struct_t *)
Unpack the sixth component of a URI CPE.
Definition cpeutils.c:719
char * cpe_struct_to_fs_cpe(const cpe_struct_t *cpe)
Convert a CPE struct into a formatted string CPE.
Definition cpeutils.c:402
static char * unbind_fs_component(char *)
Unbind a formatted string CPE component.
Definition cpeutils.c:869
static char * get_uri_component(const char *, int)
Get the indexth component of a URI CPE.
Definition cpeutils.c:536
static char * decode_uri_component(const char *)
Decode a component of a URI CPE.
Definition cpeutils.c:586
static char * process_quoted_chars(const char *)
Process the quoted characters of a CPE component for a formatted string CPE.
Definition cpeutils.c:1140
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:366
static char * add_quoting(const char *)
Handle the quoting for an unbind formatted string CPE component.
Definition cpeutils.c:898
char * cpe_struct_to_uri_product(const cpe_struct_t *cpe)
Convert a CPE struct into a URI product.
Definition cpeutils.c:309
char * cpe_struct_to_uri_cpe(const cpe_struct_t *cpe)
Convert a CPE struct into a URI CPE.
Definition cpeutils.c:240
void cpe_struct_init(cpe_struct_t *cpe)
Initialize a CPE struct.
Definition cpeutils.c:1184
char * cpe_struct_to_fs_product(const cpe_struct_t *cpe)
Convert a CPE struct into a formatted string product.
Definition cpeutils.c:496
char * get_version_from_uri_cpe(const char *uri_cpe)
Get the version from an uri cpe.
Definition cpeutils.c:350
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:1603
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:1628
void cpe_struct_free(cpe_struct_t *cpe)
Free a CPE struct.
Definition cpeutils.c:1208
static char * pack_sixth_uri_component(const cpe_struct_t *)
Pack the sixth component of a URI CPE.
Definition cpeutils.c:1072
char * uri_cpe_to_uri_product(const char *uri_cpe)
Convert a URI CPE to a formatted string product.
Definition cpeutils.c:140
static char * transform_for_uri(const char *)
Transform a CPE component for a URI CPE.
Definition cpeutils.c:1010
static gboolean has_wildcards(const char *)
Returns if a given string contains wildcards ("*" or "?").
Definition cpeutils.c:1571
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:200
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:1526
static void trim_pct(char *)
Cut of trailing ':' signs.
Definition cpeutils.c:1231
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:86
@ SUBSET
Definition cpeutils.h:89
@ DISJOINT
Definition cpeutils.h:87
@ EQUAL
Definition cpeutils.h:88
@ UNDEFINED
Definition cpeutils.h:91
@ SUPERSET
Definition cpeutils.h:90
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