Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a small rough XML interface based on libxml2 #297

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion gmp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,9 @@ endif (NOT PKG_CONFIG_FOUND)
## Dependency checks

pkg_check_modules (GLIB REQUIRED glib-2.0>=2.42)
pkg_check_modules (LIBXML2 REQUIRED libxml-2.0>=2.0)

include_directories (${GLIB_INCLUDE_DIRS})
include_directories (${GLIB_INCLUDE_DIRS} ${LIBXML2_INCLUDE_DIRS})

set (FILES gmp.c)

Expand Down
3 changes: 2 additions & 1 deletion osp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,9 @@ endif (NOT PKG_CONFIG_FOUND)
## Dependency checks

pkg_check_modules (GLIB REQUIRED glib-2.0>=2.42)
pkg_check_modules (LIBXML2 REQUIRED libxml-2.0>=2.0)

include_directories (${GLIB_INCLUDE_DIRS})
include_directories (${GLIB_INCLUDE_DIRS} ${LIBXML2_INCLUDE_DIRS})

set (FILES osp.c)

Expand Down
30 changes: 28 additions & 2 deletions util/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ if (NOT PKG_CONFIG_FOUND)
message(FATAL_ERROR "pkg-config executable not found. Aborting.")
endif (NOT PKG_CONFIG_FOUND)

set (CMAKE_VERBOSE_MAKEFILE ON)

## Dependency checks

# for all modules we need glib
Expand All @@ -47,6 +49,9 @@ pkg_check_modules (LIBSSH REQUIRED libssh>=0.6.0)
# for kb we need libhiredis
pkg_check_modules (REDIS REQUIRED hiredis>=0.10.1)

# for fast XML we need libxml2
pkg_check_modules (LIBXML2 REQUIRED libxml-2.0>=2.0)

# Set NVTICACHE name with the version
set (NVTICACHE_STR "nvticache${PROJECT_VERSION}")
add_definitions (-DNVTICACHE_STR="${NVTICACHE_STR}")
Expand Down Expand Up @@ -131,7 +136,7 @@ if (BUILD_WITH_LDAP)
endif (NOT LIBLDAP)
endif (BUILD_WITH_LDAP)

include_directories (${GLIB_INCLUDE_DIRS} ${GPGME_INCLUDE_DIRS} ${GCRYPT_INCLUDE_DIRS})
include_directories (${GLIB_INCLUDE_DIRS} ${GPGME_INCLUDE_DIRS} ${GCRYPT_INCLUDE_DIRS} ${LIBXML2_INCLUDE_DIRS})

set (FILES authutils.c compressutils.c fileutils.c gpgmeutils.c kb.c ldaputils.c
nvticache.c radiusutils.c serverutils.c sshutils.c uuidutils.c
Expand Down Expand Up @@ -160,9 +165,30 @@ if (BUILD_SHARED)
${GIO_LDFLAGS} ${GPGME_LDFLAGS} ${ZLIB_LDFLAGS}
${RADIUS_LDFLAGS} ${LIBSSH_LDFLAGS} ${GNUTLS_LDFLAGS}
${GCRYPT_LDFLAGS} ${LDAP_LDFLAGS} ${REDIS_LDFLAGS}
${UUID_LDFLAGS} ${LINKER_HARDENING_FLAGS})
${LIBXML2_LDFLAGS} ${UUID_LDFLAGS}
${LINKER_HARDENING_FLAGS})
endif (BUILD_SHARED)


## Tests

add_executable (xmlutils-test
EXCLUDE_FROM_ALL
xmlutils_tests.c)

add_test (xmlutils-test xmlutils-test)

target_link_libraries (xmlutils-test cgreen
${GLIB_LDFLAGS} ${GIO_LDFLAGS} ${GPGME_LDFLAGS} ${ZLIB_LDFLAGS}
${RADIUS_LDFLAGS} ${LIBSSH_LDFLAGS} ${GNUTLS_LDFLAGS}
${GCRYPT_LDFLAGS} ${LDAP_LDFLAGS} ${REDIS_LDFLAGS}
${LIBXML2_LDFLAGS} ${UUID_LDFLAGS}
${LINKER_HARDENING_FLAGS})

add_custom_target (tests-xmlutils
DEPENDS xmlutils-test)


## Install
configure_file (libgvm_util.pc.in ${CMAKE_BINARY_DIR}/libgvm_util.pc @ONLY)

Expand Down
245 changes: 245 additions & 0 deletions util/xmlutils.c
Original file line number Diff line number Diff line change
Expand Up @@ -1087,6 +1087,251 @@ read_entity_c (gvm_connection_t *connection, entity_t *entity)
return try_read_entity_c (connection, 0, entity);
}

/**
* @brief Get the name an entity.
*
* @param[in] entity Entity.
*
* @return Entity name, which is freed by free_entity2.
*/
void
xml_doc_free (xml_doc_t doc)
{
xmlFreeDoc (doc);
}

/**
* @brief Read an XML entity tree from a string.
*
* @param[in] string Input string.
* @param[out] entity Pointer to an entity tree.
*
* @return 0 success, -1 read error, -2 parse error, -3 XML ended prematurely.
*/
int
parse_entity2 (const char *string, xml_doc_t *xml_doc, entity2_t *entity)
{
LIBXML_TEST_VERSION

/* XML_PARSE_NOCDATA makes this skip CDATA to match our glib parser, but
* it makes this extremely slow, so instead I stripped the CDATA out of the
* XML in my feed (for now, so that I can compare the resulting scap dbs). */
*xml_doc = xmlReadMemory (string, strlen (string), "noname.xml", NULL, /* XML_PARSE_NOCDATA */ 0);
if (*xml_doc == NULL)
return -2;
//xmlFreeDoc(doc);

*entity = xmlDocGetRootElement (*xml_doc);
return 0;
}

/**
* @brief Get the name an entity.
*
* @param[in] entity Entity.
*
* @return Entity name, which is freed by free_entity2.
*/
const char *
entity2_name (entity2_t entity)
{
if (entity
&& (entity->type == XML_ELEMENT_NODE))
return (const char *) entity->name;

// FIX because we have text nodes now too
// FIX maybe should skip over in entity2_children and next_entities2
return "";
}

/**
* @brief Get children of an entity.
*
* @param[in] entity Entity.
*
* @return Children if found, else NULL.
*/
entities2_t
entity2_children (entity2_t entity)
{
if (!entity)
return NULL;
return entity->children;
}

static entity2_t
find_child (entity2_t entity, const char *name)
{
for (xmlNode *node = entity->children; node; node = node->next)
if (xmlStrcmp (node->name, (const xmlChar *) name) == 0)
return node;
return NULL;
}

/**
* @brief Get a child of an entity.
*
* @param[in] entity Entity.
* @param[in] name Name of the child.
*
* @return Entity if found, else NULL.
*/
entity2_t
entity2_child (entity2_t entity, const char *name)
{
const char *stripped_name;

if (!entity)
return NULL;

stripped_name = strchr (name, ':');
if (stripped_name)
{
entity2_t child;

/* There was a namespace in the name.
*
* First try without the namespace, because libxml2 doesn't consider the
* namespace in the name when the namespace is defined. */

stripped_name++;

if (*stripped_name == '\0')
/* Don't search for child with empty stripped name, because we'll
* find text nodes. But search with just the namespace for glib
* compatibility. */
return find_child (entity, name);

child = find_child (entity, stripped_name);
if (child)
return child;

/* Didn't find anything. */
}

/* There was no namespace, or we didn't find anything without the namespace.
*
* Try with the full name. */

return find_child (entity, name);
}

/**
* @brief Get text of an entity.
*
* If entity is not NULL then the return is guaranteed to be a string.
* So if the caller has NULL checked entity then there is no need for
* the caller to NULL check the return.
*
* @param[in] doc XML doc.
* @param[in] entity Entity.
*
* @return NULL if entity is NULL, else the text.
*/
char *
entity2_text (xml_doc_t doc, entity2_t entity)
{
char *string;

if (!entity)
return NULL;

string = (char *) xmlNodeListGetString (doc, entity->xmlChildrenNode, 1);
if (string)
return string;
string = xmlMalloc (1);
string[0] = '\0';
return string;
}

void
entity2_text_free (char *text)
{
xmlFree (text);
}
/**
* @brief Get a child of an entity.
*
* @param[in] entity Entity.
* @param[in] name Name of the child.
*
* @return Entity if found, else NULL.
*/
char *
entity2_attribute (entity2_t entity, const char *name)
{
if (!entity)
return NULL;

const char *stripped_name;

stripped_name = strchr (name, ':');
if (stripped_name)
{
char *attribute;

/* There was a namespace in the name.
*
* First try without the namespace, because libxml2 doesn't consider the
* namespace in the name when the namespace is defined. */

stripped_name++;

if (*stripped_name == '\0')
/* Don't search for child with empty stripped name, because we'll
* find text nodes. But search with just the namespace for glib
* compatibility. */
return (char *) xmlGetProp (entity, (const xmlChar *) name);

attribute = (char *) xmlGetProp (entity, (const xmlChar *) stripped_name);
if (attribute)
return attribute;

/* Didn't find anything. */
}

/* There was no namespace, or we didn't find anything without the namespace.
*
* Try with the full name. */

return (char *) xmlGetProp (entity, (const xmlChar *) name);
}

void
xml_string_free (xml_string_t string)
{
if (string)
xmlFree (string);
}

/**
* @brief Get the name an entity.
*
* @param[in] entity Entity.
*
* @return Entity name, which is freed by free_entity2.
*/
entities2_t
first_entity2 (entities2_t entities)
{
return entities;
}

/**
* @brief Get the name an entity.
*
* @param[in] entity Entity.
*
* @return Entity name, which is freed by free_entity2.
*/
entities2_t
next_entities2 (entities2_t entities)
{
if (entities)
return entities->next;
return NULL;
}

/**
* @brief Read an XML entity tree from a string.
*
Expand Down
51 changes: 51 additions & 0 deletions util/xmlutils.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@

#include <glib.h>
#include <gnutls/gnutls.h>
// FIX should be in .c only
#include <libxml/parser.h>
#include <libxml/tree.h>
#include <stdio.h>

/**
Expand All @@ -54,6 +57,54 @@ xml_handle_end_element (context_data_t *, const gchar *);
void
xml_handle_text (context_data_t *, const gchar *, gsize);

/**
* @brief XML doc.
*/
typedef xmlDoc *xml_doc_t;

typedef xmlNode *entities2_t;
/* equivalent now, kept for compat. */
typedef xmlNode *entity2_t;

typedef xmlChar *xml_string_t;
typedef const xmlChar *const_xml_string_t;

void
xml_doc_free (xml_doc_t);

int
parse_entity2 (const char *, xml_doc_t *, entity2_t *);

void
xml_string_free (xml_string_t);

entities2_t
xml_doc_root (xml_doc_t);

const char *
entity2_name (entities2_t);

char *
entity2_attribute (entity2_t, const char *);

char *
entity2_text (xml_doc_t, entities2_t);

void
entity2_text_free (char *);

entity2_t
entity2_child (entity2_t, const char *);

entities2_t
entity2_children (entities2_t);

entities2_t
first_entity2 (entities2_t);

entities2_t
next_entities2 (entities2_t);

/**
* @brief Entities.
*/
Expand Down
Loading