<commit_before>/* This file is part of the YAZ toolkit.
 * Copyright (C) 1995-2010 Index Data
 * See the file LICENSE for details.
 */
/**
 * \file srwutil.c
 * \brief Implements SRW/SRU utilities.
 */

#include <stdlib.h>
#include <assert.h>
#include <yaz/srw.h>
#include <yaz/matchstr.h>
#include <yaz/yaz-iconv.h>
#include <yaz/log.h>
#include <yaz/facet.h>
#include <yaz/wrbuf.h>

#include "sru-p.h"

#if YAZ_HAVE_XML2
#include <libxml/parser.h>
#include <libxml/tree.h>

#define SOLR_MAX_PARAMETERS  100

const char *xml_node_attribute_value_get(xmlNodePtr ptr, const char *node_name, const char *attribute_name) {

    struct _xmlAttr *attr;
    // check if the node name matches
    if (strcmp((const char*) ptr->name, node_name))
        return 0;
    // check if the attribute name and return the value
    for (attr = ptr->properties; attr; attr = attr->next)
        if (attr->children && attr->children->type == XML_TEXT_NODE) {
            if (!strcmp((const char *) attr->name, attribute_name))
                return (const char *) attr->children->content;
        }
    return 0;
}


static int match_xml_node_attribute(xmlNodePtr ptr, const char *node_name, const char *attribute_name, const char *value)
{
    const char *attribute_value;
    // check if the node name matches
    if (strcmp((const char*) ptr->name, node_name))
        return 0;
    attribute_value = xml_node_attribute_value_get(ptr, node_name, attribute_name);
    if (attribute_value && !strcmp(attribute_value, value))
        return 1;
    return 0;
}

static void yaz_solr_decode_result_docs(ODR o, xmlNodePtr ptr, Odr_int start, Z_SRW_searchRetrieveResponse *sr) {
    xmlNodePtr node;
    int offset = 0;
    int i = 0;

    sr->num_records = 0;
    for (node = ptr->children; node; node = node->next)
        if (node->type == XML_ELEMENT_NODE)
            sr->num_records++;

    sr->records = odr_malloc(o, sizeof(*sr->records) * sr->num_records);

    for (node = ptr->children; node; node = node->next)
    {
        if (node->type == XML_ELEMENT_NODE)
        {
            Z_SRW_record *record = sr->records + i;
            xmlBufferPtr buf = xmlBufferCreate();
            xmlNode *tmp = xmlCopyNode(node, 1);

            xmlNodeDump(buf, tmp->doc, tmp, 0, 0);

            xmlFreeNode(tmp);

            record->recordSchema = 0;
            record->recordPacking = Z_SRW_recordPacking_XML;
            record->recordData_len = buf->use;
            record->recordData_buf = odr_malloc(o, buf->use + 1);
            memcpy(record->recordData_buf, buf->content, buf->use);
            record->recordData_buf[buf->use] = '\0';
            // TODO Solve the real problem in zoom-sru, that doesnt work with 0-based indexes.
            // Work-around: Making the recordPosition 1-based.
            record->recordPosition = odr_intdup(o, start + offset + 1);

            xmlBufferFree(buf);

            offset++;
            i++;
        }
    }
}

static int  yaz_solr_decode_result(ODR o, xmlNodePtr ptr, Z_SRW_searchRetrieveResponse *sr) {
    Odr_int start = 0;
    struct _xmlAttr *attr;
    for (attr = ptr->properties; attr; attr = attr->next)
        if (attr->children && attr->children->type == XML_TEXT_NODE) {
            if (!strcmp((const char *) attr->name, "numFound")) {
                sr->numberOfRecords = odr_intdup(o, odr_atoi(
                        (const char *) attr->children->content));
            } 
            else if (!strcmp((const char *) attr->name, "start")) {
                start = odr_atoi((const char *) attr->children->content);
            }
        }
    if (sr->numberOfRecords && *sr->numberOfRecords > 0)
        yaz_solr_decode_result_docs(o, ptr, start, sr);
    if (sr->numberOfRecords)
        return 0;
    return -1;
}

static Z_AttributeList *yaz_solr_use_atttribute_create(ODR o, const char *name) {
    Z_AttributeList *attributes= (Z_AttributeList *) odr_malloc(o, sizeof(*attributes));
    Z_AttributeElement ** elements;
    attributes->num_attributes = 1;
    /* TODO check on name instead
    if (!attributes->num_attributes) {
        attributes->attributes = (Z_AttributeElement**)odr_nullval();
        return attributes;
    }
    */
    elements = (Z_AttributeElement**) odr_malloc (o, attributes->num_attributes * sizeof(*elements));
    elements[0] = (Z_AttributeElement*)odr_malloc(o,sizeof(**elements));
    elements[0]->attributeType = odr_malloc(o, sizeof(*elements[0]->attributeType));
    *elements[0]->attributeType = 1;
    elements[0]->attributeSet = odr_nullval();
    elements[0]->which = Z_AttributeValue_complex;
    elements[0]->value.complex = (Z_ComplexAttribute *) odr_malloc(o, sizeof(Z_ComplexAttribute));
    elements[0]->value.complex->num_list = 1;
    elements[0]->value.complex->list = (Z_StringOrNumeric **) odr_malloc(o, 1 * sizeof(Z_StringOrNumeric *));
    elements[0]->value.complex->list[0] = (Z_StringOrNumeric *) odr_malloc(o, sizeof(Z_StringOrNumeric));
    elements[0]->value.complex->list[0]->which = Z_StringOrNumeric_string;
    elements[0]->value.complex->list[0]->u.string = (Z_InternationalString *) name;
    elements[0]->value.complex->semanticAction = 0;
    elements[0]->value.complex->num_semanticAction = 0;
    attributes->attributes = elements;
    return attributes;
}


static const char *get_facet_term_count(xmlNodePtr node, int *freq) {

    const char *term = xml_node_attribute_value_get(node, "int", "name");
    xmlNodePtr child;<commit_msg>Fix: allocating string on odr memory<commit_after>/* This file is part of the YAZ toolkit.
 * Copyright (C) 1995-2010 Index Data
 * See the file LICENSE for details.
 */
/**
 * \file srwutil.c
 * \brief Implements SRW/SRU utilities.
 */

#include <stdlib.h>
#include <assert.h>
#include <yaz/srw.h>
#include <yaz/matchstr.h>
#include <yaz/yaz-iconv.h>
#include <yaz/log.h>
#include <yaz/facet.h>
#include <yaz/wrbuf.h>

#include "sru-p.h"

#if YAZ_HAVE_XML2
#include <libxml/parser.h>
#include <libxml/tree.h>

#define SOLR_MAX_PARAMETERS  100

const char *xml_node_attribute_value_get(xmlNodePtr ptr, const char *node_name, const char *attribute_name) {

    struct _xmlAttr *attr;
    // check if the node name matches
    if (strcmp((const char*) ptr->name, node_name))
        return 0;
    // check if the attribute name and return the value
    for (attr = ptr->properties; attr; attr = attr->next)
        if (attr->children && attr->children->type == XML_TEXT_NODE) {
            if (!strcmp((const char *) attr->name, attribute_name))
                return (const char *) attr->children->content;
        }
    return 0;
}


static int match_xml_node_attribute(xmlNodePtr ptr, const char *node_name, const char *attribute_name, const char *value)
{
    const char *attribute_value;
    // check if the node name matches
    if (strcmp((const char*) ptr->name, node_name))
        return 0;
    attribute_value = xml_node_attribute_value_get(ptr, node_name, attribute_name);
    if (attribute_value && !strcmp(attribute_value, value))
        return 1;
    return 0;
}

static void yaz_solr_decode_result_docs(ODR o, xmlNodePtr ptr, Odr_int start, Z_SRW_searchRetrieveResponse *sr) {
    xmlNodePtr node;
    int offset = 0;
    int i = 0;

    sr->num_records = 0;
    for (node = ptr->children; node; node = node->next)
        if (node->type == XML_ELEMENT_NODE)
            sr->num_records++;

    sr->records = odr_malloc(o, sizeof(*sr->records) * sr->num_records);

    for (node = ptr->children; node; node = node->next)
    {
        if (node->type == XML_ELEMENT_NODE)
        {
            Z_SRW_record *record = sr->records + i;
            xmlBufferPtr buf = xmlBufferCreate();
            xmlNode *tmp = xmlCopyNode(node, 1);

            xmlNodeDump(buf, tmp->doc, tmp, 0, 0);

            xmlFreeNode(tmp);

            record->recordSchema = 0;
            record->recordPacking = Z_SRW_recordPacking_XML;
            record->recordData_len = buf->use;
            record->recordData_buf = odr_malloc(o, buf->use + 1);
            memcpy(record->recordData_buf, buf->content, buf->use);
            record->recordData_buf[buf->use] = '\0';
            // TODO Solve the real problem in zoom-sru, that doesnt work with 0-based indexes.
            // Work-around: Making the recordPosition 1-based.
            record->recordPosition = odr_intdup(o, start + offset + 1);

            xmlBufferFree(buf);

            offset++;
            i++;
        }
    }
}

static int  yaz_solr_decode_result(ODR o, xmlNodePtr ptr, Z_SRW_searchRetrieveResponse *sr) {
    Odr_int start = 0;
    struct _xmlAttr *attr;
    for (attr = ptr->properties; attr; attr = attr->next)
        if (attr->children && attr->children->type == XML_TEXT_NODE) {
            if (!strcmp((const char *) attr->name, "numFound")) {
                sr->numberOfRecords = odr_intdup(o, odr_atoi(
                        (const char *) attr->children->content));
            } 
            else if (!strcmp((const char *) attr->name, "start")) {
                start = odr_atoi((const char *) attr->children->content);
            }
        }
    if (sr->numberOfRecords && *sr->numberOfRecords > 0)
        yaz_solr_decode_result_docs(o, ptr, start, sr);
    if (sr->numberOfRecords)
        return 0;
    return -1;
}

static Z_AttributeList *yaz_solr_use_atttribute_create(ODR o, const char *name) {
    Z_AttributeList *attributes= (Z_AttributeList *) odr_malloc(o, sizeof(*attributes));
    Z_AttributeElement ** elements;
    attributes->num_attributes = 1;
    /* TODO check on name instead
    if (!attributes->num_attributes) {
        attributes->attributes = (Z_AttributeElement**)odr_nullval();
        return attributes;
    }
    */
    elements = (Z_AttributeElement**) odr_malloc (o, attributes->num_attributes * sizeof(*elements));
    elements[0] = (Z_AttributeElement*)odr_malloc(o,sizeof(**elements));
    elements[0]->attributeType = odr_malloc(o, sizeof(*elements[0]->attributeType));
    *elements[0]->attributeType = 1;
    elements[0]->attributeSet = odr_nullval();
    elements[0]->which = Z_AttributeValue_complex;
    elements[0]->value.complex = (Z_ComplexAttribute *) odr_malloc(o, sizeof(Z_ComplexAttribute));
    elements[0]->value.complex->num_list = 1;
    elements[0]->value.complex->list = (Z_StringOrNumeric **) odr_malloc(o, 1 * sizeof(Z_StringOrNumeric *));
    elements[0]->value.complex->list[0] = (Z_StringOrNumeric *) odr_malloc(o, sizeof(Z_StringOrNumeric));
    elements[0]->value.complex->list[0]->which = Z_StringOrNumeric_string;
    elements[0]->value.complex->list[0]->u.string = (Z_InternationalString *) odr_strdup(o, name);
    elements[0]->value.complex->semanticAction = 0;
    elements[0]->value.complex->num_semanticAction = 0;
    attributes->attributes = elements;
    return attributes;
}


static const char *get_facet_term_count(xmlNodePtr node, int *freq) {

    const char *term = xml_node_attribute_value_get(node, "int", "name");
    xmlNodePtr child;
{'fraction_non_alphanumeric': 0.13387978142076504, 'fraction_numerical': 0.010200364298724954, 'mean_word_length': 3.0475488389237007, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 179, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 44}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4383805', 'n_tokens_mistral': 3617, 'n_tokens_neox': 3491, 'n_words': 799}