cpeutils.c
Go to the documentation of this file.
/* SPDX-FileCopyrightText: 2009-2024 Greenbone AG
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "cpeutils.h"
#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <glib.h>
#include <string.h>
#undef G_LOG_DOMAIN
#define G_LOG_DOMAIN "libgvm util"
static enum set_relation
compare_component (const char *, const char *);
static enum set_relation
compare_strings (const char *, const char *);
static int
count_escapes (const char *, int, int);
static gboolean
is_even_wildcards (const char *, int);
static gboolean
has_wildcards (const char *);
static int
index_of (const char *, const char *, int);
static gboolean
is_string (const char *);
static char *
get_uri_component (const char *, int);
static char *
decode_uri_component (const char *);
static void
unpack_sixth_uri_component (const char *, cpe_struct_t *);
static char *
get_fs_component (const char *, int);
static char *
unbind_fs_component (char *);
static char *
add_quoting (const char *);
static char *
bind_cpe_component_for_uri (const char *);
static char *
transform_for_uri (const char *);
static char *
pack_sixth_uri_component (const cpe_struct_t *);
static char *
bind_cpe_component_for_fs (const char *);
static char *
process_quoted_chars (const char *);
static void
trim_pct (char *);
static void
get_code (char *, const char *);
char *
uri_cpe_to_fs_cpe (const char *uri_cpe)
{
cpe_struct_t cpe;
char *fs_cpe;
cpe_struct_init (&cpe);
uri_cpe_to_cpe_struct (uri_cpe, &cpe);
fs_cpe = cpe_struct_to_fs_cpe (&cpe);
cpe_struct_free (&cpe);
return fs_cpe;
}
char *
uri_cpe_to_fs_product (const char *uri_cpe)
{
cpe_struct_t cpe;
char *fs_cpe;
cpe_struct_init (&cpe);
uri_cpe_to_cpe_struct (uri_cpe, &cpe);
fs_cpe = cpe_struct_to_fs_product (&cpe);
cpe_struct_free (&cpe);
return fs_cpe;
}
char *
uri_cpe_to_uri_product (const char *uri_cpe)
{
cpe_struct_t cpe;
char *fs_cpe;
cpe_struct_init (&cpe);
uri_cpe_to_cpe_struct (uri_cpe, &cpe);
fs_cpe = cpe_struct_to_uri_product (&cpe);
cpe_struct_free (&cpe);
return fs_cpe;
}
char *
fs_cpe_to_uri_cpe (const char *fs_cpe)
{
cpe_struct_t cpe;
char *uri_cpe;
cpe_struct_init (&cpe);
fs_cpe_to_cpe_struct (fs_cpe, &cpe);
uri_cpe = cpe_struct_to_uri_cpe (&cpe);
cpe_struct_free (&cpe);
return uri_cpe;
}
char *
fs_cpe_to_uri_product (const char *fs_cpe)
{
cpe_struct_t cpe;
char *uri_cpe;
cpe_struct_init (&cpe);
fs_cpe_to_cpe_struct (fs_cpe, &cpe);
uri_cpe = cpe_struct_to_uri_product (&cpe);
cpe_struct_free (&cpe);
return uri_cpe;
}
void
uri_cpe_to_cpe_struct (const char *uri_cpe, cpe_struct_t *cpe)
{
char *uri_component;
uri_component = get_uri_component (uri_cpe, 1);
cpe->part = decode_uri_component (uri_component);
g_free (uri_component);
uri_component = get_uri_component (uri_cpe, 2);
cpe->vendor = decode_uri_component (uri_component);
g_free (uri_component);
uri_component = get_uri_component (uri_cpe, 3);
cpe->product = decode_uri_component (uri_component);
g_free (uri_component);
uri_component = get_uri_component (uri_cpe, 4);
cpe->version = decode_uri_component (uri_component);
g_free (uri_component);
uri_component = get_uri_component (uri_cpe, 5);
cpe->update = decode_uri_component (uri_component);
g_free (uri_component);
uri_component = get_uri_component (uri_cpe, 6);
if (strcmp (uri_component, "") == 0 || strcmp (uri_component, "-") == 0
|| *uri_component != '~')
cpe->edition = decode_uri_component (uri_component);
else
unpack_sixth_uri_component (uri_component, cpe);
g_free (uri_component);
uri_component = get_uri_component (uri_cpe, 7);
cpe->language = decode_uri_component (uri_component);
g_free (uri_component);
}
char *
cpe_struct_to_uri_cpe (const cpe_struct_t *cpe)
{
GString *uri_cpe;
char *bind_cpe_component;
uri_cpe = g_string_new ("cpe:/");
bind_cpe_component = bind_cpe_component_for_uri (cpe->part);
if (bind_cpe_component)
{
g_string_append (uri_cpe, bind_cpe_component);
g_string_append_c (uri_cpe, ':');
g_free (bind_cpe_component);
}
bind_cpe_component = bind_cpe_component_for_uri (cpe->vendor);
if (bind_cpe_component)
{
g_string_append (uri_cpe, bind_cpe_component);
g_string_append_c (uri_cpe, ':');
g_free (bind_cpe_component);
}
bind_cpe_component = bind_cpe_component_for_uri (cpe->product);
if (bind_cpe_component)
{
g_string_append (uri_cpe, bind_cpe_component);
g_string_append_c (uri_cpe, ':');
g_free (bind_cpe_component);
}
bind_cpe_component = bind_cpe_component_for_uri (cpe->version);
if (bind_cpe_component)
{
g_string_append (uri_cpe, bind_cpe_component);
g_string_append_c (uri_cpe, ':');
g_free (bind_cpe_component);
}
bind_cpe_component = bind_cpe_component_for_uri (cpe->update);
if (bind_cpe_component)
{
g_string_append (uri_cpe, bind_cpe_component);
g_string_append_c (uri_cpe, ':');
g_free (bind_cpe_component);
}
bind_cpe_component = pack_sixth_uri_component (cpe);
if (bind_cpe_component)
{
g_string_append (uri_cpe, bind_cpe_component);
g_string_append_c (uri_cpe, ':');
g_free (bind_cpe_component);
}
bind_cpe_component = bind_cpe_component_for_uri (cpe->language);
if (bind_cpe_component)
{
g_string_append (uri_cpe, bind_cpe_component);
g_string_append_c (uri_cpe, ':');
g_free (bind_cpe_component);
}
char *result = g_string_free (uri_cpe, FALSE);
trim_pct (result);
return result;
}
char *
cpe_struct_to_uri_product (const cpe_struct_t *cpe)
{
GString *uri_cpe;
char *bind_cpe_component;
uri_cpe = g_string_new ("cpe:/");
bind_cpe_component = bind_cpe_component_for_uri (cpe->part);
if (bind_cpe_component)
{
g_string_append (uri_cpe, bind_cpe_component);
g_string_append_c (uri_cpe, ':');
g_free (bind_cpe_component);
}
bind_cpe_component = bind_cpe_component_for_uri (cpe->vendor);
if (bind_cpe_component)
{
g_string_append (uri_cpe, bind_cpe_component);
g_string_append_c (uri_cpe, ':');
g_free (bind_cpe_component);
}
bind_cpe_component = bind_cpe_component_for_uri (cpe->product);
if (bind_cpe_component)
{
g_string_append (uri_cpe, bind_cpe_component);
g_string_append_c (uri_cpe, ':');
g_free (bind_cpe_component);
}
char *result = g_string_free (uri_cpe, FALSE);
trim_pct (result);
return result;
}
char *
get_version_from_uri_cpe (const char *uri_cpe)
{
char *version = get_uri_component (uri_cpe, 4);
char *decoded_version = decode_uri_component (version);
g_free (version);
return decoded_version;
}
void
fs_cpe_to_cpe_struct (const char *fs_cpe, cpe_struct_t *cpe)
{
char *fs_component;
fs_component = get_fs_component (fs_cpe, 2);
cpe->part = unbind_fs_component (fs_component);
fs_component = get_fs_component (fs_cpe, 3);
cpe->vendor = unbind_fs_component (fs_component);
fs_component = get_fs_component (fs_cpe, 4);
cpe->product = unbind_fs_component (fs_component);
fs_component = get_fs_component (fs_cpe, 5);
cpe->version = unbind_fs_component (fs_component);
fs_component = get_fs_component (fs_cpe, 6);
cpe->update = unbind_fs_component (fs_component);
fs_component = get_fs_component (fs_cpe, 7);
cpe->edition = unbind_fs_component (fs_component);
fs_component = get_fs_component (fs_cpe, 8);
cpe->language = unbind_fs_component (fs_component);
fs_component = get_fs_component (fs_cpe, 9);
cpe->sw_edition = unbind_fs_component (fs_component);
fs_component = get_fs_component (fs_cpe, 10);
cpe->target_sw = unbind_fs_component (fs_component);
fs_component = get_fs_component (fs_cpe, 11);
cpe->target_hw = unbind_fs_component (fs_component);
fs_component = get_fs_component (fs_cpe, 12);
cpe->other = unbind_fs_component (fs_component);
}
char *
cpe_struct_to_fs_cpe (const cpe_struct_t *cpe)
{
GString *fs_cpe;
char *bind_cpe_component;
fs_cpe = g_string_new ("cpe:2.3:");
bind_cpe_component = bind_cpe_component_for_fs (cpe->part);
if (bind_cpe_component)
{
g_string_append (fs_cpe, bind_cpe_component);
g_string_append_c (fs_cpe, ':');
g_free (bind_cpe_component);
}
bind_cpe_component = bind_cpe_component_for_fs (cpe->vendor);
if (bind_cpe_component)
{
g_string_append (fs_cpe, bind_cpe_component);
g_string_append_c (fs_cpe, ':');
g_free (bind_cpe_component);
}
bind_cpe_component = bind_cpe_component_for_fs (cpe->product);
if (bind_cpe_component)
{
g_string_append (fs_cpe, bind_cpe_component);
g_string_append_c (fs_cpe, ':');
g_free (bind_cpe_component);
}
bind_cpe_component = bind_cpe_component_for_fs (cpe->version);
if (bind_cpe_component)
{
g_string_append (fs_cpe, bind_cpe_component);
g_string_append_c (fs_cpe, ':');
g_free (bind_cpe_component);
}
bind_cpe_component = bind_cpe_component_for_fs (cpe->update);
if (bind_cpe_component)
{
g_string_append (fs_cpe, bind_cpe_component);
g_string_append_c (fs_cpe, ':');
g_free (bind_cpe_component);
}
bind_cpe_component = bind_cpe_component_for_fs (cpe->edition);
if (bind_cpe_component)
{
g_string_append (fs_cpe, bind_cpe_component);
g_string_append_c (fs_cpe, ':');
g_free (bind_cpe_component);
}
bind_cpe_component = bind_cpe_component_for_fs (cpe->language);
if (bind_cpe_component)
{
g_string_append (fs_cpe, bind_cpe_component);
g_string_append_c (fs_cpe, ':');
g_free (bind_cpe_component);
}
bind_cpe_component = bind_cpe_component_for_fs (cpe->sw_edition);
if (bind_cpe_component)
{
g_string_append (fs_cpe, bind_cpe_component);
g_string_append_c (fs_cpe, ':');
g_free (bind_cpe_component);
}
bind_cpe_component = bind_cpe_component_for_fs (cpe->target_sw);
if (bind_cpe_component)
{
g_string_append (fs_cpe, bind_cpe_component);
g_string_append_c (fs_cpe, ':');
g_free (bind_cpe_component);
}
bind_cpe_component = bind_cpe_component_for_fs (cpe->target_hw);
if (bind_cpe_component)
{
g_string_append (fs_cpe, bind_cpe_component);
g_string_append_c (fs_cpe, ':');
g_free (bind_cpe_component);
}
bind_cpe_component = bind_cpe_component_for_fs (cpe->other);
if (bind_cpe_component)
{
g_string_append (fs_cpe, bind_cpe_component);
g_free (bind_cpe_component);
}
return (g_string_free (fs_cpe, FALSE));
}
char *
cpe_struct_to_fs_product (const cpe_struct_t *cpe)
{
GString *fs_cpe;
char *bind_cpe_component;
fs_cpe = g_string_new ("cpe:2.3:");
bind_cpe_component = bind_cpe_component_for_fs (cpe->part);
if (bind_cpe_component)
{
g_string_append (fs_cpe, bind_cpe_component);
g_string_append_c (fs_cpe, ':');
g_free (bind_cpe_component);
}
bind_cpe_component = bind_cpe_component_for_fs (cpe->vendor);
if (bind_cpe_component)
{
g_string_append (fs_cpe, bind_cpe_component);
g_string_append_c (fs_cpe, ':');
g_free (bind_cpe_component);
}
bind_cpe_component = bind_cpe_component_for_fs (cpe->product);
if (bind_cpe_component)
{
g_string_append (fs_cpe, bind_cpe_component);
g_string_append_c (fs_cpe, ':');
g_free (bind_cpe_component);
}
return (g_string_free (fs_cpe, FALSE));
}
static char *
get_uri_component (const char *uri_cpe, int index)
{
char *component = NULL;
char *c;
char *component_start, *component_end;
if (!uri_cpe)
return NULL;
c = (char *) uri_cpe;
/* find start of component */
for (int i = 0; *c != '\0' && i < index; c++)
{
if (*c == ':')
i++;
}
if (index == 1 && *c != '\0')
c++;
component_start = c;
/* find end of component */
if (*component_start == '\0')
component_end = component_start;
else
{
for (c = component_start; *c != '\0' && *c != ':'; c++)
;
}
component_end = c;
if (component_start >= component_end || component_end == 0)
component = (char *) g_strdup ("");
else
component = g_strndup (component_start, component_end - component_start);
return component;
}
static char *
decode_uri_component (const char *component)
{
GString *decoded_component;
char *escapes = "!\"#$%&'()*+,/:;<=>?@[\\]^`{|}~";
char *tmp_component;
char code_a[4], code_b[4], code_c[4];
long unsigned int index;
gboolean embedded;
if (!component)
return NULL;
if (strcmp (component, "") == 0 || strcmp (component, " ") == 0)
{
return (g_strdup ("ANY"));
}
if (strcmp (component, "-") == 0)
{
return (g_strdup ("NA"));
}
tmp_component = g_strdup (component);
/* set all characters to lowercase */
char *c = tmp_component;
for (; *c; c++)
*c = tolower (*c);
index = 0;
embedded = FALSE;
decoded_component = g_string_sized_new (2 * strlen (component));
char l;
char *unescaped;
while (index < strlen (tmp_component))
{
l = *(tmp_component + index);
if (l == '.' || l == '-' || l == '~')
{
g_string_append_c (decoded_component, '\\');
g_string_append_c (decoded_component, l);
index++;
embedded = TRUE;
continue;
}
if (l != '%')
{
g_string_append_c (decoded_component, l);
index++;
embedded = TRUE;
continue;
}
get_code (code_a, tmp_component + index);
if (strcmp (code_a, "%01") == 0)
{
if (index >= 3)
get_code (code_b, tmp_component + index - 3);
else
code_b[0] = '0';
if (strlen (tmp_component) >= index + 6)
get_code (code_c, tmp_component + index + 3);
else
code_c[0] = '0';
if ((index == 0 || index == strlen (tmp_component) - 3)
|| (!embedded && strcmp (code_b, "%01"))
|| (embedded && strcmp (code_c, "%01")))
{
g_string_append_c (decoded_component, '?');
index = index + 3;
continue;
}
else
{
g_string_free (decoded_component, TRUE);
g_free (tmp_component);
return NULL;
}
}
if (strcmp (code_a, "%02") == 0)
{
if (index == 0 || index == strlen (tmp_component) - 3)
{
g_string_append_c (decoded_component, '*');
index = index + 3;
continue;
}
else
{
g_string_free (decoded_component, TRUE);
g_free (tmp_component);
return NULL;
}
}
unescaped = g_uri_unescape_string (code_a, NULL);
if (unescaped && strchr (escapes, *unescaped))
{
g_string_append_c (decoded_component, '\\');
g_string_append (decoded_component, unescaped);
g_free (unescaped);
}
else if (unescaped)
{
g_string_append (decoded_component, unescaped);
g_free (unescaped);
}
else
{
g_string_free (decoded_component, TRUE);
g_free (tmp_component);
return NULL;
}
index = index + 3;
embedded = TRUE;
}
g_free (tmp_component);
return (g_string_free (decoded_component, FALSE));
}
static void
unpack_sixth_uri_component (const char *component, cpe_struct_t *cpe)
{
const char *start = component + 1;
const char *end;
char *edition, *sw_edition, *target_sw, *target_hw, *other;
end = strchr (start, '~');
if (start >= end || end == NULL)
edition = strdup ("");
else
edition = g_strndup (start, end - start);
if (end != NULL)
{
start = end + 1;
end = strchr (start, '~');
if (start >= end || end == NULL)
sw_edition = strdup ("");
else
sw_edition = g_strndup (start, end - start);
}
else
sw_edition = strdup ("");
if (end != NULL)
{
start = end + 1;
end = strchr (start, '~');
if (start >= end || end == NULL)
target_sw = strdup ("");
else
target_sw = g_strndup (start, end - start);
}
else
target_sw = strdup ("");
if (end != NULL)
{
start = end + 1;
end = strchr (start, '~');
if (start >= end || end == NULL)
target_hw = strdup ("");
else
target_hw = g_strndup (start, end - start);
}
else
target_hw = strdup ("");
if (end != NULL)
{
start = end + 1;
end = component + strlen (component);
if (start >= end)
other = strdup ("");
else
other = g_strndup (start, end - start);
}
else
other = strdup ("");
cpe->edition = decode_uri_component (edition);
g_free (edition);
cpe->sw_edition = decode_uri_component (sw_edition);
g_free (sw_edition);
cpe->target_sw = decode_uri_component (target_sw);
g_free (target_sw);
cpe->target_hw = decode_uri_component (target_hw);
g_free (target_hw);
cpe->other = decode_uri_component (other);
g_free (other);
}
static char *
get_fs_component (const char *fs_cpe, int index)
{
char *component = NULL;
char *c;
char *component_start, *component_end;
gboolean escaped;
if (!fs_cpe)
return NULL;
if (*fs_cpe == '\0')
return ((char *) g_strdup (""));
c = (char *) fs_cpe;
/* find start of component */
escaped = FALSE;
if (index == 0)
component_start = c;
else
{
for (int i = 0; *c != '\0' && i < index; c++)
{
if (*c == ':' && !escaped)
i++;
else if (*c == '\\' && !escaped)
escaped = TRUE;
else
escaped = FALSE;
}
component_start = c;
}
/* find end of component */
escaped = FALSE;
if (*component_start == '\0')
component_end = component_start;
else
{
for (c = component_start; *c != '\0'; c++)
{
if (*c == ':' && !escaped)
break;
if (*c == '\\' && !escaped)
escaped = TRUE;
else
escaped = FALSE;
}
}
component_end = c;
if (component_start >= component_end || component_end == NULL)
component = (char *) g_strdup ("");
else
component = g_strndup (component_start, component_end - component_start);
return component;
}
static char *
unbind_fs_component (char *component)
{
char *unbound_component;
if (strcmp (component, "*") == 0)
{
g_free (component);
return ((char *) g_strdup ("ANY"));
}
if (strcmp (component, "-") == 0)
{
g_free (component);
return ((char *) g_strdup ("NA"));
}
unbound_component = add_quoting (component);
g_free (component);
return unbound_component;
}
static char *
add_quoting (const char *component)
{
GString *quoted_component;
char *tmp_component;
char *c;
gboolean embedded;
if (!component)
return NULL;
quoted_component = g_string_sized_new (2 * strlen (component));
tmp_component = (char *) g_strdup (component);
embedded = FALSE;
/* set all characters to lowercase */
for (c = tmp_component; *c; c++)
*c = tolower (*c);
c = tmp_component;
while (*c != '\0')
{
if (g_ascii_isalnum (*c) || *c == '_')
{
g_string_append_c (quoted_component, *c);
c++;
embedded = TRUE;
continue;
}
if (*c == '\\')
{
c++;
if (*c != '\0')
{
g_string_append_c (quoted_component, '\\');
g_string_append_c (quoted_component, *c);
embedded = TRUE;
c++;
continue;
}
}
if (*c == '*')
{
if ((c == tmp_component)
|| (c == tmp_component + strlen (tmp_component - 1)))
{
g_string_append_c (quoted_component, *c);
c++;
embedded = TRUE;
continue;
}
else
{
g_free (tmp_component);
return NULL;
}
}
if (*c == '?')
{
if ((c == tmp_component)
|| (c == tmp_component + strlen (tmp_component - 1))
|| (!embedded && (c > tmp_component) && (*(c - 1) == '?'))
|| (embedded && *(c + 1) == '?'))
{
g_string_append_c (quoted_component, *c);
c++;
embedded = FALSE;
continue;
}
else
{
g_free (tmp_component);
return NULL;
}
}
g_string_append_c (quoted_component, '\\');
g_string_append_c (quoted_component, *c);
c++;
embedded = TRUE;
}
g_free (tmp_component);
return (g_string_free (quoted_component, FALSE));
}
static char *
bind_cpe_component_for_uri (const char *component)
{
if (!component)
return (g_strdup (""));
if (strcmp (component, "") == 0)
return (g_strdup (""));
if (strcmp (component, "ANY") == 0)
return (g_strdup (""));
if (strcmp (component, "NA") == 0)
return (g_strdup ("-"));
return (transform_for_uri (component));
}
static char *
transform_for_uri (const char *component)
{
GString *result;
char *tmp_component;
char *c;
if (!component)
return (g_strdup (""));
if (strcmp (component, "") == 0)
return (g_strdup (""));
tmp_component = g_strdup (component);
/* set all characters to lowercase */
for (c = tmp_component; *c; c++)
*c = tolower (*c);
result = g_string_new ("");
c = tmp_component;
while (*c)
{
if ((g_ascii_isalnum (*c) || *c == '_') && *c != '-')
{
g_string_append_c (result, *c);
c++;
continue;
}
if (*c == '\\')
{
c++;
if (*c != '\0')
{
char to_escape[2];
char *escaped;
to_escape[0] = *c;
to_escape[1] = '\0';
escaped = g_uri_escape_string (to_escape, NULL, FALSE);
g_string_append (result, escaped);
g_free (escaped);
c++;
}
continue;
}
if (*c == '?')
g_string_append (result, "%01");
if (*c == '*')
g_string_append (result, "%02");
c++;
}
g_free (tmp_component);
return (g_string_free (result, FALSE));
}
static char *
pack_sixth_uri_component (const cpe_struct_t *cpe)
{
if ((cpe->sw_edition == NULL || strcmp (cpe->sw_edition, "") == 0)
&& (cpe->target_sw == NULL || strcmp (cpe->target_sw, "") == 0)
&& (cpe->target_hw == NULL || strcmp (cpe->target_hw, "") == 0)
&& (cpe->other == NULL || strcmp (cpe->other, "") == 0))
{
if (strcmp (cpe->edition, "ANY") == 0)
return (g_strdup (""));
if (strcmp (cpe->edition, "NA") == 0)
return (g_strdup ("-"));
return (g_strdup (cpe->edition));
}
char *edition = bind_cpe_component_for_uri (cpe->edition);
char *sw_edition = bind_cpe_component_for_uri (cpe->sw_edition);
char *target_sw = bind_cpe_component_for_uri (cpe->target_sw);
char *target_hw = bind_cpe_component_for_uri (cpe->target_hw);
char *other = bind_cpe_component_for_uri (cpe->other);
GString *component;
component = g_string_new ("");
if (!((!sw_edition || strcmp (sw_edition, "") == 0)
&& (!target_sw || strcmp (target_sw, "") == 0)
&& (!target_hw || strcmp (target_hw, "") == 0)
&& (!other || strcmp (other, "") == 0)))
g_string_append_printf (component, "~%s~%s~%s~%s~%s", edition, sw_edition,
target_sw, target_hw, other);
else if (edition)
g_string_append (component, edition);
if (edition)
g_free (edition);
if (sw_edition)
g_free (sw_edition);
if (target_sw)
g_free (target_sw);
if (target_hw)
g_free (target_hw);
if (other)
g_free (other);
return (g_string_free (component, FALSE));
}
static char *
bind_cpe_component_for_fs (const char *component)
{
if (!component)
return (g_strdup ("*"));
if (strcmp (component, "") == 0)
return (g_strdup ("*"));
if (strcmp (component, "ANY") == 0)
return (g_strdup ("*"));
if (strcmp (component, "NA") == 0)
return (g_strdup ("-"));
return (process_quoted_chars (component));
}
static char *
process_quoted_chars (const char *component)
{
if (!component)
return (g_strdup (""));
if (strcmp (component, "") == 0)
return (g_strdup (""));
GString *fs_component;
fs_component = g_string_new ("");
char *c = (char *) component;
char next_c;
while (*c)
{
if (*c != '\\')
{
g_string_append_c (fs_component, *c);
c++;
}
else
{
next_c = *(c + 1);
if (next_c == '.' || next_c == '-' || next_c == '_')
{
g_string_append_c (fs_component, next_c);
c += 2;
}
else if (next_c)
{
g_string_append_c (fs_component, '\\');
g_string_append_c (fs_component, next_c);
c += 2;
}
}
}
return (g_string_free (fs_component, FALSE));
}
void
cpe_struct_init (cpe_struct_t *cpe)
{
cpe->part = NULL;
cpe->vendor = NULL;
cpe->product = NULL;
cpe->version = NULL;
cpe->update = NULL;
cpe->edition = NULL;
cpe->sw_edition = NULL;
cpe->target_sw = NULL;
cpe->target_hw = NULL;
cpe->other = NULL;
cpe->language = NULL;
/* to keep the compiler satisfied */
cpe->part = cpe->part;
}
void
cpe_struct_free (cpe_struct_t *cpe)
{
if (!cpe)
return;
if (cpe->part)
g_free (cpe->part);
if (cpe->vendor)
g_free (cpe->vendor);
if (cpe->product)
g_free (cpe->product);
if (cpe->version)
g_free (cpe->version);
if (cpe->update)
g_free (cpe->update);
if (cpe->edition)
g_free (cpe->edition);
if (cpe->sw_edition)
g_free (cpe->sw_edition);
if (cpe->target_sw)
g_free (cpe->target_sw);
if (cpe->target_hw)
g_free (cpe->target_hw);
if (cpe->other)
g_free (cpe->other);
if (cpe->language)
g_free (cpe->language);
}
static void
trim_pct (char *str)
{
char *c;
if (!str)
return;
c = str + strlen (str) - 1;
while (c >= str)
{
if (*c == ':')
{
*c = '\0';
c--;
}
else
break;
}
}
static void
get_code (char *code, const char *str)
{
code[0] = *str;
code[1] = *(str + 1);
code[2] = *(str + 2);
code[3] = '\0';
}
gboolean
cpe_struct_match (cpe_struct_t *source, cpe_struct_t *target)
{
enum set_relation relation;
relation = compare_component (source->part, target->part);
if (relation != SUPERSET && relation != EQUAL)
return FALSE;
relation = compare_component (source->vendor, target->vendor);
if (relation != SUPERSET && relation != EQUAL)
return FALSE;
relation = compare_component (source->product, target->product);
if (relation != SUPERSET && relation != EQUAL)
return FALSE;
relation = compare_component (source->version, target->version);
if (relation != SUPERSET && relation != EQUAL)
return FALSE;
relation = compare_component (source->update, target->update);
if (relation != SUPERSET && relation != EQUAL)
return FALSE;
relation = compare_component (source->edition, target->edition);
if (relation != SUPERSET && relation != EQUAL)
return FALSE;
relation = compare_component (source->sw_edition, target->sw_edition);
if (relation != SUPERSET && relation != EQUAL)
return FALSE;
relation = compare_component (source->target_sw, target->target_sw);
if (relation != SUPERSET && relation != EQUAL)
return FALSE;
relation = compare_component (source->target_hw, target->target_hw);
if (relation != SUPERSET && relation != EQUAL)
return FALSE;
relation = compare_component (source->other, target->other);
if (relation != SUPERSET && relation != EQUAL)
return FALSE;
relation = compare_component (source->language, target->language);
if (relation != SUPERSET && relation != EQUAL)
return FALSE;
return TRUE;
}
gboolean
cpe_struct_match_tail (cpe_struct_t *source, cpe_struct_t *target)
{
enum set_relation relation;
relation = compare_component (source->update, target->update);
if (relation != SUPERSET && relation != EQUAL)
return FALSE;
relation = compare_component (source->edition, target->edition);
if (relation != SUPERSET && relation != EQUAL)
return FALSE;
relation = compare_component (source->sw_edition, target->sw_edition);
if (relation != SUPERSET && relation != EQUAL)
return FALSE;
relation = compare_component (source->target_sw, target->target_sw);
if (relation != SUPERSET && relation != EQUAL)
return FALSE;
relation = compare_component (source->target_hw, target->target_hw);
if (relation != SUPERSET && relation != EQUAL)
return FALSE;
relation = compare_component (source->other, target->other);
if (relation != SUPERSET && relation != EQUAL)
return FALSE;
relation = compare_component (source->language, target->language);
if (relation != SUPERSET && relation != EQUAL)
return FALSE;
return TRUE;
}
static enum set_relation
compare_component (const char *source, const char *target)
{
enum set_relation result;
char *source_cpy, *target_cpy;
char *c;
if (source)
source_cpy = g_strdup (source);
else
source_cpy = g_strdup ("ANY");
if (target)
target_cpy = g_strdup (target);
else
target_cpy = g_strdup ("ANY");
if (is_string (source_cpy))
{
/* set all characters to lowercase */
for (c = source_cpy; *c; c++)
*c = tolower (*c);
}
if (is_string (target_cpy))
{
/* set all characters to lowercase */
for (c = target_cpy; *c; c++)
*c = tolower (*c);
}
if (is_string (target_cpy) && has_wildcards (target_cpy))
{
g_free (source_cpy);
g_free (target_cpy);
return UNDEFINED;
}
if (strcmp (source_cpy, target_cpy) == 0)
{
g_free (source_cpy);
g_free (target_cpy);
return EQUAL;
}
if (strcmp (source_cpy, "ANY") == 0)
{
g_free (source_cpy);
g_free (target_cpy);
return SUPERSET;
}
if (strcmp (target_cpy, "ANY") == 0)
{
g_free (source_cpy);
g_free (target_cpy);
return SUBSET;
}
if (strcmp (target_cpy, "NA") == 0 || strcmp (source_cpy, "NA") == 0)
{
g_free (source_cpy);
g_free (target_cpy);
return DISJOINT;
}
result = compare_strings (source_cpy, target_cpy);
g_free (source_cpy);
g_free (target_cpy);
return result;
}
static enum set_relation
compare_strings (const char *source, const char *target)
{
int start = 0;
int end = strlen (source);
int begins = 0;
int ends = 0;
char *sub_source;
if (*source == '*')
{
start = 1;
begins = -1;
}
else
{
while (start < (int) strlen (source) && *(source + start) == '?')
{
start++;
begins++;
}
}
if (*(source + end - 1) == '*' && is_even_wildcards (source, end - 1))
{
end--;
ends = -1;
}
else
{
while (end > 0 && *(source + end - 1) == '?'
&& is_even_wildcards (source, end - 1))
{
end--;
ends++;
}
}
sub_source = g_strndup (source + start, end - start);
int index = -1;
int escapes = 0;
int leftover = strlen (target);
while (leftover > 0)
{
index = index_of (target, sub_source, index + 1);
if (index == -1)
break;
escapes = count_escapes (target, 0, index);
if (index > 0 && begins != -1 && begins < (index - escapes))
break;
escapes = count_escapes (target, index + 1, strlen (target));
leftover = strlen (target) - index - escapes - strlen (sub_source);
if (leftover > 0 && (ends != -1 && leftover > ends))
continue;
g_free (sub_source);
return SUPERSET;
}
g_free (sub_source);
return DISJOINT;
}
static int
count_escapes (const char *str, int start, int end)
{
int result = 0;
gboolean active = FALSE;
for (int i = 0; i < end && *(str + i) != '\0'; i++)
{
active = (!active && *(str + i) == '\\');
if (active && i >= start)
result++;
}
return result;
}
static gboolean
is_even_wildcards (const char *str, int index)
{
int result = 0;
while (index > 0 && *(str + index - 1) == '\\')
{
index--;
result++;
}
return ((result % 2) == 0);
}
static gboolean
has_wildcards (const char *str)
{
char *c = (char *) str;
gboolean active = FALSE;
while (*c != '\0')
{
if (!active && (*c == '?' || *c == '*'))
return TRUE;
if (!active && *c == '\\')
active = TRUE;
else
active = FALSE;
c++;
}
return FALSE;
}
static int
index_of (const char *str, const char *sub_str, int offset)
{
char *start;
char *begin_substr;
if (offset > (int) strlen (str))
return -1;
start = (char *) str + offset;
begin_substr = strstr (start, sub_str);
if (begin_substr == NULL)
return -1;
return begin_substr - str;
}
static gboolean
is_string (const char *str)
{
if (!str)
return TRUE;
return (strcmp (str, "ANY") && strcmp (str, "NA"));
}
fs_cpe_to_uri_cpe
char * fs_cpe_to_uri_cpe(const char *fs_cpe)
Convert a formatted string CPE to a URI CPE.
Definition cpeutils.c:160
cpe_struct_match
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
bind_cpe_component_for_fs
static char * bind_cpe_component_for_fs(const char *)
Bind a CPE component for a formatted string CPE.
Definition cpeutils.c:1124
cpe_struct_match_tail
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
uri_cpe_to_fs_cpe
char * uri_cpe_to_fs_cpe(const char *uri_cpe)
Convert a URI CPE to a formatted string CPE.
Definition cpeutils.c:100
compare_strings
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
bind_cpe_component_for_uri
static char * bind_cpe_component_for_uri(const char *)
Bind a CPE component for a URI CPE.
Definition cpeutils.c:989
get_fs_component
static char * get_fs_component(const char *, int)
Get the indexth component of a formatted string CPE.
Definition cpeutils.c:801
is_even_wildcards
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
compare_component
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
fs_cpe_to_uri_product
char * fs_cpe_to_uri_product(const char *fs_cpe)
Convert a formatted string CPE to an URI product.
Definition cpeutils.c:180
get_code
static void get_code(char *, const char *)
Get the percent code from the start of a string.
Definition cpeutils.c:1274
unpack_sixth_uri_component
static void unpack_sixth_uri_component(const char *, cpe_struct_t *)
Unpack the sixth component of a URI CPE.
Definition cpeutils.c:719
cpe_struct_to_fs_cpe
char * cpe_struct_to_fs_cpe(const cpe_struct_t *cpe)
Convert a CPE struct into a formatted string CPE.
Definition cpeutils.c:402
unbind_fs_component
static char * unbind_fs_component(char *)
Unbind a formatted string CPE component.
Definition cpeutils.c:869
get_uri_component
static char * get_uri_component(const char *, int)
Get the indexth component of a URI CPE.
Definition cpeutils.c:536
decode_uri_component
static char * decode_uri_component(const char *)
Decode a component of a URI CPE.
Definition cpeutils.c:586
process_quoted_chars
static char * process_quoted_chars(const char *)
Process the quoted characters of a CPE component for a formatted string CPE.
Definition cpeutils.c:1146
fs_cpe_to_cpe_struct
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
add_quoting
static char * add_quoting(const char *)
Handle the quoting for an unbind formatted string CPE component.
Definition cpeutils.c:898
cpe_struct_to_uri_product
char * cpe_struct_to_uri_product(const cpe_struct_t *cpe)
Convert a CPE struct into a URI product.
Definition cpeutils.c:309
cpe_struct_to_uri_cpe
char * cpe_struct_to_uri_cpe(const cpe_struct_t *cpe)
Convert a CPE struct into a URI CPE.
Definition cpeutils.c:240
cpe_struct_init
void cpe_struct_init(cpe_struct_t *cpe)
Initialize a CPE struct.
Definition cpeutils.c:1190
cpe_struct_to_fs_product
char * cpe_struct_to_fs_product(const cpe_struct_t *cpe)
Convert a CPE struct into a formatted string product.
Definition cpeutils.c:496
get_version_from_uri_cpe
char * get_version_from_uri_cpe(const char *uri_cpe)
Get the version from an uri cpe.
Definition cpeutils.c:350
index_of
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
is_string
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
cpe_struct_free
void cpe_struct_free(cpe_struct_t *cpe)
Free a CPE struct.
Definition cpeutils.c:1214
pack_sixth_uri_component
static char * pack_sixth_uri_component(const cpe_struct_t *)
Pack the sixth component of a URI CPE.
Definition cpeutils.c:1073
uri_cpe_to_uri_product
char * uri_cpe_to_uri_product(const char *uri_cpe)
Convert a URI CPE to a formatted string product.
Definition cpeutils.c:140
transform_for_uri
static char * transform_for_uri(const char *)
Transform a CPE component for a URI CPE.
Definition cpeutils.c:1010
has_wildcards
static gboolean has_wildcards(const char *)
Returns if a given string contains wildcards ("*" or "?").
Definition cpeutils.c:1588
uri_cpe_to_cpe_struct
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
count_escapes
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
trim_pct
static void trim_pct(char *)
Cut of trailing ':' signs.
Definition cpeutils.c:1248
uri_cpe_to_fs_product
char * uri_cpe_to_fs_product(const char *uri_cpe)
Convert a URI CPE to a formatted string product.
Definition cpeutils.c:120
cpeutils.h
Headers for CPE utils.
set_relation
set_relation
Definition cpeutils.h:86
SUBSET
@ SUBSET
Definition cpeutils.h:89
DISJOINT
@ DISJOINT
Definition cpeutils.h:87
EQUAL
@ EQUAL
Definition cpeutils.h:88
UNDEFINED
@ UNDEFINED
Definition cpeutils.h:91
SUPERSET
@ SUPERSET
Definition cpeutils.h:90
cpe_struct_t
XML context.
Definition cpeutils.h:23
cpe_struct_t::sw_edition
char * sw_edition
Definition cpeutils.h:30
cpe_struct_t::target_sw
char * target_sw
Definition cpeutils.h:31
cpe_struct_t::vendor
char * vendor
Definition cpeutils.h:25
cpe_struct_t::version
char * version
Definition cpeutils.h:27
cpe_struct_t::update
char * update
Definition cpeutils.h:28
cpe_struct_t::product
char * product
Definition cpeutils.h:26
cpe_struct_t::part
char * part
Definition cpeutils.h:24
cpe_struct_t::edition
char * edition
Definition cpeutils.h:29
cpe_struct_t::language
char * language
Definition cpeutils.h:34
cpe_struct_t::target_hw
char * target_hw
Definition cpeutils.h:32
cpe_struct_t::other
char * other
Definition cpeutils.h:33