<commit_before>/*  =========================================================================
    zeb_curl_client - Set of utilities to send HTTP request and verify the responses

    Copyright (c) the Contributors as noted in the AUTHORS file.
    This file is part of ZEBRA.

    This Source Code Form is subject to the terms of the Mozilla Public
    License, v. 2.0. If a copy of the MPL was not distributed with this
    file, You can obtain one at http://mozilla.org/MPL/2.0/.
    =========================================================================
*/

/*
@header
    zeb_curl_client - Set of utilities to send HTTP request and verify the responses
@discuss
@end
*/

#include <curl/curl.h>
#include "zebra_classes.h"

//  Structure of our class

typedef struct _zeb_curl_client_t {
    CURLM *multi_handle;
    int still_running;
    char *data;
} zeb_curl_client_t;

size_t static
write_callback_func(void *buffer, size_t size, size_t nmemb, void *userp)
{
    char **response = (char **) userp;
    *response = strndup ((char *) buffer, (size_t) (size * nmemb));
    return nmemb;
}

//  --------------------------------------------------------------------------
//  Create a new zeb_curl_client.

zeb_curl_client_t *
zeb_curl_client_new ()
{
    zeb_curl_client_t *self = (zeb_curl_client_t *) zmalloc (sizeof (zeb_curl_client_t));
    assert (self);

    //  Initialize properties
    curl_global_init(CURL_GLOBAL_ALL);
    self->multi_handle = curl_multi_init ();

    return self;
}

//  --------------------------------------------------------------------------
//  Destroy the zeb_curl_client.

void
zeb_curl_client_destroy (zeb_curl_client_t **self_p)
{
    assert (self_p);
    if (*self_p) {
        zeb_curl_client_t *self = *self_p;

        //  Free class properties
        curl_multi_cleanup (self->multi_handle);

        //  Free object itself
        free (self);
        zstr_free (&self->data);
        *self_p = NULL;
    }
}


//  --------------------------------------------------------------------------
//  Sends a HTTP GET request to the given URL

void
zeb_curl_client_send_get (zeb_curl_client_t *self, char *url)
{
    CURL *curl = curl_easy_init ();
    assert (curl);
    curl_easy_setopt (curl, CURLOPT_URL, url);
    curl_easy_setopt (curl, CURLOPT_FOLLOWLOCATION, 1L);
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback_func);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &self->data);
    curl_easy_setopt (curl, CURLOPT_HEADER, true);
    struct curl_slist *header = NULL;
    header = curl_slist_append (header, "User-Agent: Curl-Test-Client");
    curl_easy_setopt (curl, CURLOPT_HTTPHEADER, header);<commit_msg>Problem: zeb_curl struct is free'd before data is free'd<commit_after>/*  =========================================================================
    zeb_curl_client - Set of utilities to send HTTP request and verify the responses

    Copyright (c) the Contributors as noted in the AUTHORS file.
    This file is part of ZEBRA.

    This Source Code Form is subject to the terms of the Mozilla Public
    License, v. 2.0. If a copy of the MPL was not distributed with this
    file, You can obtain one at http://mozilla.org/MPL/2.0/.
    =========================================================================
*/

/*
@header
    zeb_curl_client - Set of utilities to send HTTP request and verify the responses
@discuss
@end
*/

#include <curl/curl.h>
#include "zebra_classes.h"

//  Structure of our class

typedef struct _zeb_curl_client_t {
    CURLM *multi_handle;
    int still_running;
    char *data;
} zeb_curl_client_t;

size_t static
write_callback_func(void *buffer, size_t size, size_t nmemb, void *userp)
{
    char **response = (char **) userp;
    *response = strndup ((char *) buffer, (size_t) (size * nmemb));
    return nmemb;
}

//  --------------------------------------------------------------------------
//  Create a new zeb_curl_client.

zeb_curl_client_t *
zeb_curl_client_new ()
{
    zeb_curl_client_t *self = (zeb_curl_client_t *) zmalloc (sizeof (zeb_curl_client_t));
    assert (self);

    //  Initialize properties
    curl_global_init(CURL_GLOBAL_ALL);
    self->multi_handle = curl_multi_init ();

    return self;
}

//  --------------------------------------------------------------------------
//  Destroy the zeb_curl_client.

void
zeb_curl_client_destroy (zeb_curl_client_t **self_p)
{
    assert (self_p);
    if (*self_p) {
        zeb_curl_client_t *self = *self_p;

        //  Free class properties
        curl_multi_cleanup (self->multi_handle);

        //  Free object itself
        zstr_free (&self->data);
        free (self);
        *self_p = NULL;
    }
}


//  --------------------------------------------------------------------------
//  Sends a HTTP GET request to the given URL

void
zeb_curl_client_send_get (zeb_curl_client_t *self, char *url)
{
    CURL *curl = curl_easy_init ();
    assert (curl);
    curl_easy_setopt (curl, CURLOPT_URL, url);
    curl_easy_setopt (curl, CURLOPT_FOLLOWLOCATION, 1L);
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback_func);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &self->data);
    curl_easy_setopt (curl, CURLOPT_HEADER, true);
    struct curl_slist *header = NULL;
    header = curl_slist_append (header, "User-Agent: Curl-Test-Client");
    curl_easy_setopt (curl, CURLOPT_HTTPHEADER, header);
{'fraction_non_alphanumeric': 0.22178988326848248, 'fraction_numerical': 0.0018528812303131369, 'mean_word_length': 2.5489809335963183, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, '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': '7352999', 'n_tokens_mistral': 1795, 'n_tokens_neox': 1644, 'n_words': 445}