kalu / curl.c

/**
 * kalu - Copyright (C) 2012 Olivier Brunel
 *
 * curl.c
 * Copyright (C) 2012 Olivier Brunel <i.am.jack.mail@gmail.com>
 * 
 * This file is part of kalu.
 *
 * kalu is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 *
 * kalu is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * kalu. If not, see http://www.gnu.org/licenses/
 */

#include <config.h>

/* C */
#include <string.h>

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

/* kalu */
#include "kalu.h"
#include "curl.h"

/* struct to hold data downloaded via curl */
typedef struct _string_t {
    char   *content;
    size_t  len;
    size_t  alloc;
} string_t;

static size_t
curl_write (void *content, size_t size, size_t nmemb, string_t *data)
{
    size_t total = size * nmemb;
    
    /* alloc memory if needed */
    if (data->len + total >= data->alloc)
    {
        data->content = realloc (data->content, data->alloc + total + 1024);
        data->alloc += total + 1024;
    }
    
    /* copy data */
    memcpy (&(data->content[data->len]), content, total);
    data->len += total;
    
    return total;
}

char *
curl_download (const char *url, GError **error)
{
    CURL *curl;
    string_t data;
    char errmsg[CURL_ERROR_SIZE];
    
    debug ("downloading %s", url);
    memset (&data, 0, sizeof (string_t));
    
    curl = curl_easy_init();
    if (!curl)
    {
        g_set_error (error, KALU_ERROR, 1, "Unable to init cURL\n");
        return NULL;
    }
    
    curl_easy_setopt (curl, CURLOPT_USERAGENT, PACKAGE_NAME "/" PACKAGE_VERSION);
    curl_easy_setopt (curl, CURLOPT_URL, url);
    curl_easy_setopt (curl, CURLOPT_NOPROGRESS, 1);
    curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, (curl_write_callback) curl_write);
    curl_easy_setopt (curl, CURLOPT_WRITEDATA, (void *) &data);
    curl_easy_setopt (curl, CURLOPT_ERRORBUFFER, errmsg);
    
    if (curl_easy_perform (curl) != 0)
    {
        curl_easy_cleanup (curl);
        if (data.content != NULL)
        {
            free (data.content);
        }
        g_set_error (error, KALU_ERROR, 1, errmsg);
        return NULL;
    }
    curl_easy_cleanup (curl);
    debug ("downloaded %d bytes", data.len);
    
    /* content is not NULL-terminated yet */
    data.content[data.len] = '\0';
    
    return data.content;
}
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.