/**
 * @file curl.c
 * @brief Curl helper functions
 */

/* $Progeny$
 *
 * Copyright 2002 Hewlett-Packard Company
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */

#include "config.h"

#ifdef HAVE_LIBCURL

#include <sys/types.h>

#include <assert.h>
#include <stdio.h>
#include <string.h>

#include <expat.h>
#include <curl/curl.h>

#include <discover/discover.h>

#include <discover/curl.h>
#include <discover/utils.h>

static CURL *curl_handle = NULL;
static char *user_agent = NULL;

#define DISCOVER_CURL_NAME "curl"

char *
_discover_curl_get_user_agent(void)
{
    size_t len;
    char *curlversion = curl_version();

    if (!user_agent) {
        len = strlen(PACKAGE_NAME);
        len += 1;               /* '/' */
        len += strlen(PACKAGE_VERSION);
        len += 2;               /* ' ' '(' */
        len += strlen(DISCOVER_TARGET);
        len += 1;               /* ')' */
        len += 1;               /* ' ' */
        len += strlen(DISCOVER_CURL_NAME);
        len += 1;               /* '/' */
        len += strlen(curlversion);
        len += 1;               /* '\0' */

        user_agent = _discover_xmalloc(len);

        snprintf(user_agent, len, "%s/%s (%s) %s/%s",
                 PACKAGE_NAME, PACKAGE_VERSION,
                 DISCOVER_TARGET,
                 DISCOVER_CURL_NAME, curlversion);
    }

    return user_agent;
}

CURL *
_discover_curl_get_handle(void)
{
    if (!curl_handle) {
        curl_handle = curl_easy_init();
        user_agent = _discover_curl_get_user_agent();
        curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, user_agent);
    }

    return curl_handle;
}

void
_discover_curl_cleanup(void)
{
    curl_easy_cleanup(curl_handle);
    curl_handle = NULL;
}

size_t
_discover_curl_xmlparse_callback(void *ptr, size_t size, size_t nmemb,
                                 void *stream)
{
    char *data = ptr;
    XML_Parser parser = stream;
    size_t len;

    assert(data != NULL);
    assert(parser != NULL);

    len = size * nmemb;

    if (!XML_Parse(parser, data, len, 0)) {
        return 0;
    }

    return len;
}

int
_discover_load_url(const char *url, XML_Parser parser)
{
    CURL *curl;
    CURLcode curl_status;

    assert(url != NULL);

    curl = _discover_curl_get_handle();
    curl_easy_setopt(curl, CURLOPT_URL, url);
    curl_easy_setopt(curl, CURLOPT_FILE, parser);
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION,
                     _discover_curl_xmlparse_callback);

    curl_status = curl_easy_perform(curl);
    _discover_curl_cleanup();

    return (curl_status == 0);
}

#endif
