Greenbone Vulnerability Management Libraries 22.35.6
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 if (edition)
1103 g_free (edition);
1104 if (sw_edition)
1105 g_free (sw_edition);
1106 if (target_sw)
1107 g_free (target_sw);
1108 if (target_hw)
1109 g_free (target_hw);
1110 if (other)
1111 g_free (other);
1112 return (g_string_free (component, FALSE));
1113}
1114
1122static char *
1123bind_cpe_component_for_fs (const char *component)
1124{
1125 if (!component)
1126 return (g_strdup ("*"));
1127 if (strcmp (component, "") == 0)
1128 return (g_strdup ("*"));
1129 if (strcmp (component, "ANY") == 0)
1130 return (g_strdup ("*"));
1131 if (strcmp (component, "NA") == 0)
1132 return (g_strdup ("-"));
1133 return (process_quoted_chars (component));
1134}
1135
1144static char *
1145process_quoted_chars (const char *component)
1146{
1147 if (!component)
1148 return (g_strdup (""));
1149 if (strcmp (component, "") == 0)
1150 return (g_strdup (""));
1151
1152 GString *fs_component;
1153 fs_component = g_string_new ("");
1154 char *c = (char *) component;
1155 char next_c;
1156
1157 while (*c)
1158 {
1159 if (*c != '\\')
1160 {
1161 g_string_append_c (fs_component, *c);
1162 c++;
1163 }
1164 else
1165 {
1166 next_c = *(c + 1);
1167 if (next_c == '.' || next_c == '-' || next_c == '_')
1168 {
1169 g_string_append_c (fs_component, next_c);
1170 c += 2;
1171 }
1172 else if (next_c)
1173 {
1174 g_string_append_c (fs_component, '\\');
1175 g_string_append_c (fs_component, next_c);
1176 c += 2;
1177 }
1178 }
1179 }
1180 return (g_string_free (fs_component, FALSE));
1181}
1182
1188void
1190{
1191 cpe->part = NULL;
1192 cpe->vendor = NULL;
1193 cpe->product = NULL;
1194 cpe->version = NULL;
1195 cpe->update = NULL;
1196 cpe->edition = NULL;
1197 cpe->sw_edition = NULL;
1198 cpe->target_sw = NULL;
1199 cpe->target_hw = NULL;
1200 cpe->other = NULL;
1201 cpe->language = NULL;
1202
1203 /* to keep the compiler satisfied */
1204 cpe->part = cpe->part;
1205}
1206
1212void
1214{
1215 if (!cpe)
1216 return;
1217 if (cpe->part)
1218 g_free (cpe->part);
1219 if (cpe->vendor)
1220 g_free (cpe->vendor);
1221 if (cpe->product)
1222 g_free (cpe->product);
1223 if (cpe->version)
1224 g_free (cpe->version);
1225 if (cpe->update)
1226 g_free (cpe->update);
1227 if (cpe->edition)
1228 g_free (cpe->edition);
1229 if (cpe->sw_edition)
1230 g_free (cpe->sw_edition);
1231 if (cpe->target_sw)
1232 g_free (cpe->target_sw);
1233 if (cpe->target_hw)
1234 g_free (cpe->target_hw);
1235 if (cpe->other)
1236 g_free (cpe->other);
1237 if (cpe->language)
1238 g_free (cpe->language);
1239}
1240
1246static void
1247trim_pct (char *str)
1248{
1249 char *c;
1250
1251 if (!str)
1252 return;
1253 c = str + strlen (str) - 1;
1254 while (c >= str)
1255 {
1256 if (*c == ':')
1257 {
1258 *c = '\0';
1259 c--;
1260 }
1261 else
1262 break;
1263 }
1264}
1265
1272static void
1273get_code (char *code, const char *str)
1274{
1275 code[0] = *str;
1276 code[1] = *(str + 1);
1277 code[2] = *(str + 2);
1278 code[3] = '\0';
1279}
1280
1293gboolean
1295{
1296 enum set_relation relation;
1297
1298 relation = compare_component (source->part, target->part);
1299 if (relation != SUPERSET && relation != EQUAL)
1300 return FALSE;
1301 relation = compare_component (source->vendor, target->vendor);
1302 if (relation != SUPERSET && relation != EQUAL)
1303 return FALSE;
1304 relation = compare_component (source->product, target->product);
1305 if (relation != SUPERSET && relation != EQUAL)
1306 return FALSE;
1307 relation = compare_component (source->version, target->version);
1308 if (relation != SUPERSET && relation != EQUAL)
1309 return FALSE;
1310 relation = compare_component (source->update, target->update);
1311 if (relation != SUPERSET && relation != EQUAL)
1312 return FALSE;
1313 relation = compare_component (source->edition, target->edition);
1314 if (relation != SUPERSET && relation != EQUAL)
1315 return FALSE;
1316 relation = compare_component (source->sw_edition, target->sw_edition);
1317 if (relation != SUPERSET && relation != EQUAL)
1318 return FALSE;
1319 relation = compare_component (source->target_sw, target->target_sw);
1320 if (relation != SUPERSET && relation != EQUAL)
1321 return FALSE;
1322 relation = compare_component (source->target_hw, target->target_hw);
1323 if (relation != SUPERSET && relation != EQUAL)
1324 return FALSE;
1325 relation = compare_component (source->other, target->other);
1326 if (relation != SUPERSET && relation != EQUAL)
1327 return FALSE;
1328 relation = compare_component (source->language, target->language);
1329 if (relation != SUPERSET && relation != EQUAL)
1330 return FALSE;
1331
1332 return TRUE;
1333}
1334
1348gboolean
1350{
1351 enum set_relation relation;
1352
1353 relation = compare_component (source->update, target->update);
1354 if (relation != SUPERSET && relation != EQUAL)
1355 return FALSE;
1356 relation = compare_component (source->edition, target->edition);
1357 if (relation != SUPERSET && relation != EQUAL)
1358 return FALSE;
1359 relation = compare_component (source->sw_edition, target->sw_edition);
1360 if (relation != SUPERSET && relation != EQUAL)
1361 return FALSE;
1362 relation = compare_component (source->target_sw, target->target_sw);
1363 if (relation != SUPERSET && relation != EQUAL)
1364 return FALSE;
1365 relation = compare_component (source->target_hw, target->target_hw);
1366 if (relation != SUPERSET && relation != EQUAL)
1367 return FALSE;
1368 relation = compare_component (source->other, target->other);
1369 if (relation != SUPERSET && relation != EQUAL)
1370 return FALSE;
1371 relation = compare_component (source->language, target->language);
1372 if (relation != SUPERSET && relation != EQUAL)
1373 return FALSE;
1374
1375 return TRUE;
1376}
1377
1389static enum set_relation
1390compare_component (const char *source, const char *target)
1391{
1392 enum set_relation result;
1393 char *source_cpy, *target_cpy;
1394 char *c;
1395
1396 if (source)
1397 source_cpy = g_strdup (source);
1398 else
1399 source_cpy = g_strdup ("ANY");
1400 if (target)
1401 target_cpy = g_strdup (target);
1402 else
1403 target_cpy = g_strdup ("ANY");
1404
1405 if (is_string (source_cpy))
1406 {
1407 /* set all characters to lowercase */
1408 for (c = source_cpy; *c; c++)
1409 *c = tolower (*c);
1410 }
1411 if (is_string (target_cpy))
1412 {
1413 /* set all characters to lowercase */
1414 for (c = target_cpy; *c; c++)
1415 *c = tolower (*c);
1416 }
1417 if (is_string (target_cpy) && has_wildcards (target_cpy))
1418 {
1419 g_free (source_cpy);
1420 g_free (target_cpy);
1421 return UNDEFINED;
1422 }
1423 if (strcmp (source_cpy, target_cpy) == 0)
1424 {
1425 g_free (source_cpy);
1426 g_free (target_cpy);
1427 return EQUAL;
1428 }
1429 if (strcmp (source_cpy, "ANY") == 0)
1430 {
1431 g_free (source_cpy);
1432 g_free (target_cpy);
1433 return SUPERSET;
1434 }
1435 if (strcmp (target_cpy, "ANY") == 0)
1436 {
1437 g_free (source_cpy);
1438 g_free (target_cpy);
1439 return SUBSET;
1440 }
1441 if (strcmp (target_cpy, "NA") == 0 || strcmp (source_cpy, "NA") == 0)
1442 {
1443 g_free (source_cpy);
1444 g_free (target_cpy);
1445 return DISJOINT;
1446 }
1447
1448 result = compare_strings (source_cpy, target_cpy);
1449 g_free (source_cpy);
1450 g_free (target_cpy);
1451 return result;
1452}
1453
1466static enum set_relation
1467compare_strings (const char *source, const char *target)
1468{
1469 int start = 0;
1470 int end = strlen (source);
1471 int begins = 0;
1472 int ends = 0;
1473
1474 char *sub_source;
1475
1476 if (*source == '*')
1477 {
1478 start = 1;
1479 begins = -1;
1480 }
1481 else
1482 {
1483 while (start < (int) strlen (source) && *(source + start) == '?')
1484 {
1485 start++;
1486 begins++;
1487 }
1488 }
1489 if (*(source + end - 1) == '*' && is_even_wildcards (source, end - 1))
1490 {
1491 end--;
1492 ends = -1;
1493 }
1494 else
1495 {
1496 while (end > 0 && *(source + end - 1) == '?'
1497 && is_even_wildcards (source, end - 1))
1498 {
1499 end--;
1500 ends++;
1501 }
1502 }
1503
1504 sub_source = g_strndup (source + start, end - start);
1505 int index = -1;
1506 int escapes = 0;
1507 int leftover = strlen (target);
1508
1509 while (leftover > 0)
1510 {
1511 index = index_of (target, sub_source, index + 1);
1512 if (index == -1)
1513 break;
1514 escapes = count_escapes (target, 0, index);
1515 if (index > 0 && begins != -1 && begins < (index - escapes))
1516 break;
1517 escapes = count_escapes (target, index + 1, strlen (target));
1518 leftover = strlen (target) - index - escapes - strlen (sub_source);
1519 if (leftover > 0 && (ends != -1 && leftover > ends))
1520 continue;
1521 g_free (sub_source);
1522 return SUPERSET;
1523 }
1524 g_free (sub_source);
1525 return DISJOINT;
1526}
1527
1541static int
1542count_escapes (const char *str, int start, int end)
1543{
1544 int result = 0;
1545 gboolean active = FALSE;
1546
1547 for (int i = 0; i < end && *(str + i) != '\0'; i++)
1548 {
1549 active = (!active && *(str + i) == '\\');
1550 if (active && i >= start)
1551 result++;
1552 }
1553 return result;
1554}
1555
1566static gboolean
1567is_even_wildcards (const char *str, int index)
1568{
1569 int result = 0;
1570
1571 while (index > 0 && *(str + index - 1) == '\\')
1572 {
1573 index--;
1574 result++;
1575 }
1576 return ((result % 2) == 0);
1577}
1578
1586static gboolean
1587has_wildcards (const char *str)
1588{
1589 char *c = (char *) str;
1590 gboolean active = FALSE;
1591
1592 while (*c != '\0')
1593 {
1594 if (!active && (*c == '?' || *c == '*'))
1595 return TRUE;
1596
1597 if (!active && *c == '\\')
1598 active = TRUE;
1599 else
1600 active = FALSE;
1601
1602 c++;
1603 }
1604 return FALSE;
1605}
1606
1618static int
1619index_of (const char *str, const char *sub_str, int offset)
1620{
1621 char *start;
1622 char *begin_substr;
1623
1624 if (offset > (int) strlen (str))
1625 return -1;
1626
1627 start = (char *) str + offset;
1628 begin_substr = strstr (start, sub_str);
1629 if (begin_substr == NULL)
1630 return -1;
1631 return begin_substr - str;
1632}
1633
1643static gboolean
1644is_string (const char *str)
1645{
1646 if (!str)
1647 return TRUE;
1648
1649 return (strcmp (str, "ANY") && strcmp (str, "NA"));
1650}
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:1294
static char * bind_cpe_component_for_fs(const char *)
Bind a CPE component for a formatted string CPE.
Definition cpeutils.c:1123
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:1349
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:1467
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:1567
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:1390
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:1273
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:1145
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:1189
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:1619
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:1644
void cpe_struct_free(cpe_struct_t *cpe)
Free a CPE struct.
Definition cpeutils.c:1213
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:1587
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:1542
static void trim_pct(char *)
Cut of trailing ':' signs.
Definition cpeutils.c:1247
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