std::string XMLextractor::get_node_content(const std::string& nodeName, 
        xmlNode *node)
{
    // Check Base Case
    if(node == NULL)
        return("null");
    
    xmlNode *cur_node = node;
    std::string content = "null";
    
    // Check if this is the node we need
    if(cur_node->type == XML_ELEMENT_NODE &&
            !nodeName.compare((char*)cur_node->name) ) 
    {
        content = (char*)cur_node->children->content;
        return(content);
    }

    content = get_node_content(nodeName,cur_node->children);
    
    if(content == "null")
        return( get_node_content(nodeName, cur_node->next));
    
    return(content);
    
}
/* !DO NOT ALTER FUNCTION SIGNATURE! */
int callback_n_netopeer_n_modules_n_module_n_enabled(void** UNUSED(data), XMLDIFF_OP op, xmlNodePtr old_node, xmlNodePtr new_node, struct nc_err** UNUSED(error)) {
	xmlNodePtr tmp, node;
	char* module_name = NULL, *module_enabled = NULL;
	struct np_module* module = netopeer_options.modules;

	node = (op & XMLDIFF_REM ? old_node : new_node);
	if (node == NULL) {
		return EXIT_FAILURE;
	}

	for (tmp = node->parent->children; tmp != NULL; tmp = tmp->next) {
		if (xmlStrEqual(tmp->name, BAD_CAST "name")) {
			module_name = get_node_content(tmp);
			break;
		}
	}
	module_enabled = get_node_content(node);

	if (module_name == NULL || module_enabled == NULL) {
		nc_verb_error("%s: missing module \"name\" or \"enabled\" node", __func__);
		return EXIT_FAILURE;
	}

	if ((op & (XMLDIFF_REM | XMLDIFF_ADD)) && strcmp(module_enabled, "false") == 0) {
		/* module is/was not enabled, nothing to enable/disable */
		return EXIT_SUCCESS;
	}

	while (module) {
		if (strcmp(module->name, module_name) == 0) {
			break;
		}
		module = module->next;
	}

	if ((op & XMLDIFF_REM) || ((op & XMLDIFF_MOD) && strcmp(module_enabled, "false") == 0)) {
		if (module == NULL) {
			nc_verb_error("%s: internal error: module to disable not found", __func__);
			return EXIT_FAILURE;
		}

		if (module_disable(module, 1)) {
			return EXIT_FAILURE;
		}
	} else if ((op & XMLDIFF_ADD) || ((op & XMLDIFF_MOD) && strcmp(module_enabled, "true") == 0)) {
		if (module != NULL) {
			nc_verb_error("%s: internal error: module to enable already exists", __func__);
			return EXIT_FAILURE;
		}

		module = calloc(1, sizeof(struct np_module));
		module->name = strdup(module_name);
		if (module_enable(module, 1)) {
			return EXIT_FAILURE;
		}
	}

	return EXIT_SUCCESS;
}
/* !DO NOT ALTER FUNCTION SIGNATURE! */
int callback_n_netopeer_n_tls_n_server_key(void** UNUSED(data), XMLDIFF_OP op, xmlNodePtr UNUSED(old_node), xmlNodePtr new_node, struct nc_err** error) {
	char* key = NULL, *type = NULL;
	xmlNodePtr child;

	if (op & (XMLDIFF_MOD | XMLDIFF_ADD)) {
		for (child = new_node->children; child != NULL; child = child->next) {
			if (xmlStrEqual(child->name, BAD_CAST "key-data")) {
				key = get_node_content(child);
			}

			if (xmlStrEqual(child->name, BAD_CAST "key-type")) {
				type = get_node_content(child);
			}
		}

		if (key == NULL || type == NULL) {
			*error = nc_err_new(NC_ERR_MISSING_ELEM);
			nc_err_set(*error, NC_ERR_PARAM_MSG, "key-data and/or key-type element missing.");
			return EXIT_FAILURE;
		}

		if (strcmp(type, "RSA") != 0 && strcmp(type, "DSA") != 0) {
			*error = nc_err_new(NC_ERR_BAD_ELEM);
			nc_err_set(*error, NC_ERR_PARAM_INFO_BADELEM, "/netopeer/tls/server-key/key-type");
			return EXIT_FAILURE;
		}
	}

	/* TLS_CTX LOCK */
	pthread_mutex_lock(&netopeer_options.tls_opts->tls_ctx_lock);

	free(netopeer_options.tls_opts->server_key);
	netopeer_options.tls_opts->server_key = NULL;
	if (op & (XMLDIFF_MOD | XMLDIFF_ADD)) {
		netopeer_options.tls_opts->server_key = strdup(key);
		if (strcmp(type, "RSA") == 0) {
			netopeer_options.tls_opts->server_key_type = 1;
		} else {
			netopeer_options.tls_opts->server_key_type = 0;
		}
	}
	netopeer_options.tls_opts->tls_ctx_change_flag = 1;

	/* TLS_CTX UNLOCK */
	pthread_mutex_unlock(&netopeer_options.tls_opts->tls_ctx_lock);

	return EXIT_SUCCESS;
}
/* !DO NOT ALTER FUNCTION SIGNATURE! */
int callback_n_netopeer_n_max_sessions(void** UNUSED(data), XMLDIFF_OP op, xmlNodePtr UNUSED(old_node), xmlNodePtr new_node, struct nc_err** error) {
	char* content = NULL, *ptr, *msg;
	uint16_t num;

	if (op & XMLDIFF_REM) {
		netopeer_options.max_sessions = 8;
		return EXIT_SUCCESS;
	}

	content = get_node_content(new_node);
	if (content == NULL) {
		*error = nc_err_new(NC_ERR_OP_FAILED);
		nc_verb_error("%s: node content missing", __func__);
		return EXIT_FAILURE;
	}

	num = strtol(content, &ptr, 10);
	if (*ptr != '\0') {
		asprintf(&msg, "Could not convert '%s' to a number.", content);
		*error = nc_err_new(NC_ERR_BAD_ELEM);
		nc_err_set(*error, NC_ERR_PARAM_MSG, msg);
		nc_err_set(*error, NC_ERR_PARAM_INFO_BADELEM, "/netopeer/max-sessions");
		free(msg);
		return EXIT_FAILURE;
	}

	netopeer_options.max_sessions = num;
	return EXIT_SUCCESS;
}
/* !DO NOT ALTER FUNCTION SIGNATURE! */
int callback_n_netopeer_n_tls_n_server_cert(void** UNUSED(data), XMLDIFF_OP op, xmlNodePtr UNUSED(old_node), xmlNodePtr new_node, struct nc_err** error) {
	char* content = NULL;

	if (op & (XMLDIFF_MOD | XMLDIFF_ADD)) {
		content = get_node_content(new_node);
		if (content == NULL) {
			*error = nc_err_new(NC_ERR_OP_FAILED);
			nc_verb_error("%s: node content missing", __func__);
			return EXIT_FAILURE;
		}
	}

	/* TLS_CTX LOCK */
	pthread_mutex_lock(&netopeer_options.tls_opts->tls_ctx_lock);

	free(netopeer_options.tls_opts->server_cert);
	netopeer_options.tls_opts->server_cert = NULL;
	if (op & (XMLDIFF_MOD | XMLDIFF_ADD)) {
		netopeer_options.tls_opts->server_cert = strdup(content);
	}
	netopeer_options.tls_opts->tls_ctx_change_flag = 1;

	/* TLS_CTX UNLOCK */
	pthread_mutex_unlock(&netopeer_options.tls_opts->tls_ctx_lock);

	return EXIT_SUCCESS;
}
/* !DO NOT ALTER FUNCTION SIGNATURE! */
int callback_n_netopeer_n_ssh_n_auth_timeout(void** UNUSED(data), XMLDIFF_OP op, xmlNodePtr UNUSED(old_node), xmlNodePtr new_node, struct nc_err** error) {
	char* content = NULL, *ptr, *msg;
	uint16_t num;

	if (op & XMLDIFF_REM) {
		netopeer_options.ssh_opts->auth_timeout = 10;
		return EXIT_SUCCESS;
	}

	content = get_node_content(new_node);
	if (content == NULL) {
		*error = nc_err_new(NC_ERR_OP_FAILED);
		nc_verb_error("%s: node content missing", __func__);
		return EXIT_FAILURE;
	}

	num = strtol(content, &ptr, 10);
	if (*ptr != '\0') {
		*error = nc_err_new(NC_ERR_OP_FAILED);
		if (asprintf(&msg, "Could not convert '%s' to a number.", content) == 0) {
			nc_err_set(*error, NC_ERR_PARAM_MSG, msg);
			free(msg);
		}
		return EXIT_FAILURE;
	}

	netopeer_options.ssh_opts->auth_timeout = num;
	return EXIT_SUCCESS;
}
/* !DO NOT ALTER FUNCTION SIGNATURE! */
int callback_n_netopeer_n_hello_timeout(void** UNUSED(data), XMLDIFF_OP op, xmlNodePtr UNUSED(old_node), xmlNodePtr new_node, struct nc_err** error) {
	char* content = NULL, *ptr, *msg;
	uint32_t num;

	if (op & XMLDIFF_REM) {
		/* set default value */
		nc_hello_timeout(600 * 1000);
		return EXIT_SUCCESS;
	}

	content = get_node_content(new_node);
	if (content == NULL) {
		*error = nc_err_new(NC_ERR_OP_FAILED);
		nc_verb_error("%s: node content missing", __func__);
		return EXIT_FAILURE;
	}

	num = strtol(content, &ptr, 10);
	if (*ptr != '\0') {
		*error = nc_err_new(NC_ERR_BAD_ELEM);
		if (asprintf(&msg, "Could not convert '%s' to a number.", content) == 0) {
			nc_err_set(*error, NC_ERR_PARAM_MSG, msg);
			nc_err_set(*error, NC_ERR_PARAM_INFO_BADELEM, "/netopeer/hello-timeout");
			free(msg);
		}
		return EXIT_FAILURE;
	}

	nc_hello_timeout(num * 1000);
	return EXIT_SUCCESS;
}
/* !DO NOT ALTER FUNCTION SIGNATURE! */
int callback_n_netopeer_n_tls_n_crl_dir(void** UNUSED(data), XMLDIFF_OP op, xmlNodePtr UNUSED(old_node), xmlNodePtr new_node, struct nc_err** error) {
	char* content = NULL;

	if (op & (XMLDIFF_MOD | XMLDIFF_ADD)) {
		content = get_node_content(new_node);
		if (content == NULL) {
			*error = nc_err_new(NC_ERR_OP_FAILED);
			nc_verb_error("%s: node content missing", __func__);
			return EXIT_FAILURE;
		}
	}

	/* CRL_DIR LOCK */
	pthread_mutex_lock(&netopeer_options.tls_opts->crl_dir_lock);

	free(netopeer_options.tls_opts->crl_dir);
	netopeer_options.tls_opts->crl_dir = NULL;
	if (op & (XMLDIFF_MOD | XMLDIFF_ADD)) {
		netopeer_options.tls_opts->crl_dir = strdup(content);
	}

	/* CRL_DIR UNLOCK */
	pthread_mutex_unlock(&netopeer_options.tls_opts->crl_dir_lock);

	return EXIT_SUCCESS;
}
/* !DO NOT ALTER FUNCTION SIGNATURE! */
int callback_n_netopeer_n_tls_n_trusted_ca_certs_n_trusted_ca_cert(void** UNUSED(data), XMLDIFF_OP op, xmlNodePtr old_node, xmlNodePtr new_node, struct nc_err** error) {
	char* content = NULL;

	if (op & (XMLDIFF_REM | XMLDIFF_MOD)) {
		content = get_node_content(old_node);
		if (content == NULL) {
			*error = nc_err_new(NC_ERR_OP_FAILED);
			nc_verb_error("%s: node content missing", __func__);
			return EXIT_FAILURE;
		}

		/* TLS_CTX LOCK */
		pthread_mutex_lock(&netopeer_options.tls_opts->tls_ctx_lock);

		if (del_trusted_cert(&netopeer_options.tls_opts->trusted_certs, content, 0) != 0) {
			nc_verb_error("%s: inconsistent state (%s:%d)", __func__, __FILE__, __LINE__);
		} else {
			netopeer_options.tls_opts->tls_ctx_change_flag = 1;
		}

		/* TLS_CTX UNLOCK */
		pthread_mutex_unlock(&netopeer_options.tls_opts->tls_ctx_lock);
	}

	if (op & (XMLDIFF_MOD | XMLDIFF_ADD)) {
		content = get_node_content(new_node);
		if (content == NULL) {
			*error = nc_err_new(NC_ERR_OP_FAILED);
			nc_verb_error("%s: node content missing", __func__);
			return EXIT_FAILURE;
		}

		/* TLS_CTX LOCK */
		pthread_mutex_lock(&netopeer_options.tls_opts->tls_ctx_lock);

		add_trusted_cert(&netopeer_options.tls_opts->trusted_certs, content, 0);
		netopeer_options.tls_opts->tls_ctx_change_flag = 1;

		/* TLS_CTX UNLOCK */
		pthread_mutex_unlock(&netopeer_options.tls_opts->tls_ctx_lock);
	}

	return EXIT_SUCCESS;
}
static void parse_cap_domain_info(struct cap_domain_info *cg_domaininfo,
                                  xmlNode *domain_child_node)
{
        CU_DEBUG("Capabilities guest domain info element node: %s",
                 domain_child_node->name);

        if (XSTREQ(domain_child_node->name, "emulator")) {
                cg_domaininfo->emulator =
                        get_node_content(domain_child_node);
        } else if (XSTREQ(domain_child_node->name, "loader")) {
                cg_domaininfo->loader =
                        get_node_content(domain_child_node);
        } else if (XSTREQ(domain_child_node->name, "machine")) {
                extend_cap_machines(cg_domaininfo,
                                    get_node_content(domain_child_node),
                                    get_attr_value(domain_child_node,
                                                   "canonical"));
        }
}
static int parse_cap_host_cpu(struct cap_host *cap_host, xmlNode *cpu)
{
        xmlNode *child;

        for (child = cpu->children; child != NULL; child = child->next) {
                if (XSTREQ(child->name, "arch")) {
                        cap_host->cpu_arch = get_node_content(child);
                        if (cap_host->cpu_arch != NULL)
                                return 1; /* success - host arch node found */
                        else {
                                CU_DEBUG("Host architecture is not defined");
                                break;
                        }
                }
        }
        return 0; /* error - no arch node or empty arch node */
}
static void parse_cap_arch(struct cap_arch *cg_archinfo,
                           xmlNode *arch)
{
        CU_DEBUG("Capabilities arch node: %s", arch->name);

        xmlNode *child;

        cg_archinfo->name = get_attr_value(arch, "name");

        for (child = arch->children; child != NULL; child = child->next) {
                if (XSTREQ(child->name, "wordsize")) {
                        char *wordsize_str;
                        unsigned int wordsize;
                        wordsize_str = get_node_content(child);
                        /* Default to 0 wordsize if garbage */
                        if (wordsize_str == NULL ||
                            sscanf(wordsize_str, "%i", &wordsize) != 1)
                                wordsize = 0;
                        free(wordsize_str);
                        cg_archinfo->wordsize = wordsize;
                } else if (XSTREQ(child->name, "domain")) {
                        struct cap_domain *tmp_list = NULL;
                        tmp_list = realloc(cg_archinfo->domains,
                                           (cg_archinfo->num_domains + 1) *
                                           sizeof(struct cap_domain));
                        if (tmp_list == NULL) {
                                /* Nothing you can do. Just go on. */
                                CU_DEBUG("Could not alloc space for "
                                         "guest domain");
                                continue;
                        }
                        memset(&tmp_list[cg_archinfo->num_domains],
                               0, sizeof(struct cap_domain));
                        cg_archinfo->domains = tmp_list;
                        parse_cap_domain(&cg_archinfo->
                                         domains[cg_archinfo->num_domains],
                                         child);
                        cg_archinfo->num_domains++;
                } else {
                        /* Check for the default domain child nodes */
                        parse_cap_domain_info(&cg_archinfo->default_domain_info,
                                              child);
                }
        }
}
/* !DO NOT ALTER FUNCTION SIGNATURE! */
int callback_n_netopeer_n_ssh_n_password_auth_enabled(void** UNUSED(data), XMLDIFF_OP op, xmlNodePtr UNUSED(old_node), xmlNodePtr new_node, struct nc_err** error) {
	char* content = NULL;

	if (op & XMLDIFF_REM) {
		netopeer_options.ssh_opts->password_auth_enabled = 1;
		return EXIT_SUCCESS;
	}

	content = get_node_content(new_node);
	if (content == NULL) {
		*error = nc_err_new(NC_ERR_OP_FAILED);
		nc_verb_error("%s: node content missing", __func__);
		return EXIT_FAILURE;
	}

	if (strcmp(content, "false") == 0) {
		netopeer_options.ssh_opts->password_auth_enabled = 0;
	} else {
		netopeer_options.ssh_opts->password_auth_enabled = 1;
	}
	return EXIT_SUCCESS;
}
/* !DO NOT ALTER FUNCTION SIGNATURE! */
int callback_n_netopeer_n_ssh_n_server_keys_n_dsa_key(void** UNUSED(data), XMLDIFF_OP op, xmlNodePtr UNUSED(old_node), xmlNodePtr new_node, struct nc_err** error) {
	char* content = NULL;

	if (op & XMLDIFF_REM) {
		free(netopeer_options.ssh_opts->dsa_key);
		netopeer_options.ssh_opts->dsa_key = NULL;
		netopeer_options.ssh_opts->server_key_change_flag = 1;
		return EXIT_SUCCESS;
	}

	content = get_node_content(new_node);
	if (content == NULL) {
		*error = nc_err_new(NC_ERR_OP_FAILED);
		nc_verb_error("%s: node content missing", __func__);
		return EXIT_FAILURE;
	}

	free(netopeer_options.ssh_opts->dsa_key);
	netopeer_options.ssh_opts->dsa_key = strdup(content);
	netopeer_options.ssh_opts->server_key_change_flag = 1;
	return EXIT_SUCCESS;
}
/* !DO NOT ALTER FUNCTION SIGNATURE! */
int callback_n_netopeer_n_ssh_n_client_auth_keys_n_client_auth_key(void** UNUSED(data), XMLDIFF_OP op, xmlNodePtr old_node, xmlNodePtr new_node, struct nc_err** error) {
	xmlNodePtr node;
	char* path = NULL, *username = NULL;
	struct np_auth_key* key;

	if (op & XMLDIFF_REM) {
		node = old_node;
	} else {
		node = new_node;
	}

	for (node = node->children; node != NULL; node = node->next) {
		if (xmlStrEqual(node->name, BAD_CAST "path")) {
			path = get_node_content(node);
		}
		if (xmlStrEqual(node->name, BAD_CAST "username")) {
			username = get_node_content(node);
		}
	}

	if (path == NULL || username == NULL) {
		*error = nc_err_new(NC_ERR_OP_FAILED);
		nc_verb_error("%s: path and/or username missing", __func__);
		return EXIT_FAILURE;
	}

	if (op & (XMLDIFF_REM | XMLDIFF_MOD)) {
		for (key = netopeer_options.ssh_opts->client_auth_keys; key != NULL; key = key->next) {
			if (strcmp(key->path, path) == 0) {
				break;
			}
		}

		if (key == NULL) {
			*error = nc_err_new(NC_ERR_OP_FAILED);
			nc_verb_error("%s: internal error: changed key not found", __func__);
			return EXIT_FAILURE;
		}

		/* CLIENT KEYS LOCK */
		pthread_mutex_lock(&netopeer_options.ssh_opts->client_keys_lock);

		/* remove the key */
		if (op & XMLDIFF_REM) {
			if (key->prev == NULL) {
				netopeer_options.ssh_opts->client_auth_keys = key->next;
				free(key->path);
				free(key->username);
				free(key);
				if (netopeer_options.ssh_opts->client_auth_keys != NULL) {
					netopeer_options.ssh_opts->client_auth_keys->prev = NULL;
				}
			} else {
				key->prev->next = key->next;
				if (key->next != NULL) {
					key->next->prev = key->prev;
				}
				free(key->path);
				free(key->username);
				free(key);
			}

		/* modify the key */
		} else {
			free(key->username);
			key->username = strdup(username);
		}

		/* CLIENT KEYS UNLOCK */
		pthread_mutex_unlock(&netopeer_options.ssh_opts->client_keys_lock);

	} else if (op & XMLDIFF_ADD) {

		/* CLIENT KEYS LOCK */
		pthread_mutex_lock(&netopeer_options.ssh_opts->client_keys_lock);

		/* add the key */
		if (netopeer_options.ssh_opts->client_auth_keys == NULL) {
			netopeer_options.ssh_opts->client_auth_keys = calloc(1, sizeof(struct np_auth_key));
			netopeer_options.ssh_opts->client_auth_keys->path = strdup(path);
			netopeer_options.ssh_opts->client_auth_keys->username = strdup(username);
		} else {
			for (key = netopeer_options.ssh_opts->client_auth_keys; key->next != NULL; key = key->next) {
				key->next = calloc(1, sizeof(struct np_auth_key));
				key->path = strdup(path);
				key->username = strdup(username);
				key->next->prev = key;
			}
		}

		/* CLIENT KEYS UNLOCK */
		pthread_mutex_unlock(&netopeer_options.ssh_opts->client_keys_lock);
	}


	return EXIT_SUCCESS;
}
std::string XMLextractor::get_node_content(const std::string& nodeName)
{
    return(get_node_content(nodeName,m_root_element)); 
}
/* !DO NOT ALTER FUNCTION SIGNATURE! */
int callback_n_netopeer_n_tls_n_cert_maps_n_cert_to_name(void** UNUSED(data), XMLDIFF_OP op, xmlNodePtr old_node, xmlNodePtr new_node, struct nc_err** error) {
	char* id = NULL, *fingerprint = NULL, *map_type = NULL, *name = NULL, *ptr, *msg;
	xmlNodePtr child;

callback_restart:
	for (child = (op & (XMLDIFF_MOD | XMLDIFF_REM) ? old_node->children : new_node->children); child != NULL; child = child->next) {
		if (xmlStrEqual(child->name, BAD_CAST "id")) {
			id = get_node_content(child);
		}
		if (xmlStrEqual(child->name, BAD_CAST "fingerprint")) {
			fingerprint = get_node_content(child);
		}
		if (xmlStrEqual(child->name, BAD_CAST "map-type")) {
			map_type = get_node_content(child);
			if (strchr(map_type, ':') != NULL) {
				map_type = strchr(map_type, ':')+1;
			}
		}
		if (xmlStrEqual(child->name, BAD_CAST "name")) {
			name = get_node_content(child);
		}
	}

	if (id == NULL || fingerprint == NULL || map_type == NULL) {
		*error = nc_err_new(NC_ERR_MISSING_ELEM);
		nc_err_set(*error, NC_ERR_PARAM_MSG, "id and/or fingerprint and/or map-type element missing.");
		return EXIT_FAILURE;
	}
	strtol(id, &ptr, 10);
	if (*ptr != '\0') {
		asprintf(&msg, "Could not convert '%s' to a number.", id);
		*error = nc_err_new(NC_ERR_BAD_ELEM);
		nc_err_set(*error, NC_ERR_PARAM_INFO_BADELEM, "/netopeer/tls/cert-maps/cert-to-name/id");
		nc_err_set(*error, NC_ERR_PARAM_MSG, msg);
		free(msg);
		return EXIT_FAILURE;
	}
	if (strcmp(map_type, "specified") == 0 && name == NULL) {
		*error = nc_err_new(NC_ERR_MISSING_ELEM);
		nc_err_set(*error, NC_ERR_PARAM_MSG, "name element missing.");
		return EXIT_FAILURE;
	}

	/* CTN_MAP LOCK */
	pthread_mutex_lock(&netopeer_options.tls_opts->ctn_map_lock);

	if (op & (XMLDIFF_REM | XMLDIFF_MOD)) {
		if (del_ctn_item(&netopeer_options.tls_opts->ctn_map, atoi(id), fingerprint, ctn_type_parse(map_type), name) != 0) {
			nc_verb_error("%s: inconsistent state (%s:%d)", __func__, __FILE__, __LINE__);
		}

		if (op & XMLDIFF_MOD) {
			/* CTN_MAP UNLOCK */
			pthread_mutex_unlock(&netopeer_options.tls_opts->ctn_map_lock);
			op = XMLDIFF_ADD;
			goto callback_restart;
		}
	}
	if (op & XMLDIFF_ADD) {
		add_ctn_item(&netopeer_options.tls_opts->ctn_map, atoi(id), fingerprint, ctn_type_parse(map_type), name);
	}

	/* CTN_MAP UNLOCK */
	pthread_mutex_unlock(&netopeer_options.tls_opts->ctn_map_lock);

	return EXIT_SUCCESS;
}