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