114 lines
2.6 KiB
C
114 lines
2.6 KiB
C
|
|
#include <curl/curl.h>
|
||
|
|
#include <stdio.h>
|
||
|
|
#include <stdlib.h>
|
||
|
|
#include <string.h>
|
||
|
|
|
||
|
|
#include "fetch.h"
|
||
|
|
|
||
|
|
static char curl_errbuf[CURL_ERROR_SIZE] = {'\0'};
|
||
|
|
|
||
|
|
struct fetch *fetch_init(void) {
|
||
|
|
CURLcode res;
|
||
|
|
CURL *handle;
|
||
|
|
struct fetch *fh = NULL;
|
||
|
|
|
||
|
|
/*
|
||
|
|
* TODO: Not sure if calling this possibly more than once can cause
|
||
|
|
* an issue or not.
|
||
|
|
*/
|
||
|
|
if ((res = curl_global_init(CURL_GLOBAL_DEFAULT)) != CURLE_OK) {
|
||
|
|
fprintf(stderr, "Could not initialize curl: %s\n", curl_easy_strerror(res));
|
||
|
|
exit(EXIT_FAILURE);
|
||
|
|
}
|
||
|
|
|
||
|
|
handle = curl_easy_init();
|
||
|
|
|
||
|
|
if ((res = curl_easy_setopt(handle, CURLOPT_ERRORBUFFER, curl_errbuf)) !=
|
||
|
|
CURLE_OK) {
|
||
|
|
fprintf(stderr, "Error setting up error buffer: %s\n",
|
||
|
|
curl_easy_strerror(res));
|
||
|
|
curl_easy_cleanup(handle);
|
||
|
|
exit(EXIT_FAILURE);
|
||
|
|
}
|
||
|
|
|
||
|
|
if ((fh = malloc(sizeof *fh)) == NULL) {
|
||
|
|
fputs("Out of memory.\n", stderr);
|
||
|
|
exit(EXIT_FAILURE);
|
||
|
|
}
|
||
|
|
|
||
|
|
fh->handle = handle;
|
||
|
|
|
||
|
|
return fh;
|
||
|
|
}
|
||
|
|
|
||
|
|
void fetch_cleanup(struct fetch *restrict f) {
|
||
|
|
/* Don't even dignify this with a response */
|
||
|
|
if (f == NULL)
|
||
|
|
return;
|
||
|
|
|
||
|
|
curl_easy_cleanup(f->handle);
|
||
|
|
free(f);
|
||
|
|
}
|
||
|
|
|
||
|
|
size_t fetch_cb(void *ptr, size_t size, size_t nmemb, void *data) {
|
||
|
|
struct response *resp = (struct response *)data;
|
||
|
|
size_t real_size = size * nmemb;
|
||
|
|
|
||
|
|
if ((resp->data = realloc(resp->data, resp->size + real_size + 1)) == NULL) {
|
||
|
|
fputs("Out of memory.\n", stderr);
|
||
|
|
exit(EXIT_FAILURE);
|
||
|
|
}
|
||
|
|
|
||
|
|
printf("Wrote %zd bytes\n", real_size);
|
||
|
|
|
||
|
|
memcpy(resp->data + resp->size, ptr, real_size);
|
||
|
|
resp->size += real_size;
|
||
|
|
resp->data[resp->size] = '\0';
|
||
|
|
|
||
|
|
return real_size;
|
||
|
|
}
|
||
|
|
|
||
|
|
struct response *fetch(struct fetch *restrict f, CURLU *restrict url) {
|
||
|
|
struct response *resp = NULL;
|
||
|
|
|
||
|
|
if (curl_easy_setopt(f->handle, CURLOPT_WRITEFUNCTION, fetch_cb) != CURLE_OK)
|
||
|
|
goto call_fetch_fail;
|
||
|
|
|
||
|
|
if (curl_easy_setopt(f->handle, CURLOPT_CURLU, url) != CURLE_OK)
|
||
|
|
goto call_fetch_fail;
|
||
|
|
|
||
|
|
if ((resp = malloc(sizeof *resp)) == NULL) {
|
||
|
|
fputs("Out of memory.", stderr);
|
||
|
|
exit(EXIT_FAILURE);
|
||
|
|
}
|
||
|
|
|
||
|
|
memset(resp, 0, sizeof *resp);
|
||
|
|
|
||
|
|
if (curl_easy_setopt(f->handle, CURLOPT_WRITEDATA, (void *)resp) != CURLE_OK)
|
||
|
|
goto call_fetch_fail;
|
||
|
|
|
||
|
|
if (curl_easy_perform(f->handle) != CURLE_OK)
|
||
|
|
goto call_fetch_fail;
|
||
|
|
|
||
|
|
if (curl_easy_getinfo(f->handle, CURLINFO_CONTENT_TYPE,
|
||
|
|
&resp->content_type) != CURLE_OK)
|
||
|
|
goto call_fetch_fail;
|
||
|
|
|
||
|
|
printf("CONTENT TYPE: %s\n", resp->content_type);
|
||
|
|
|
||
|
|
return resp;
|
||
|
|
|
||
|
|
call_fetch_fail:
|
||
|
|
if (resp != NULL)
|
||
|
|
free(resp);
|
||
|
|
fputs(curl_errbuf, stderr);
|
||
|
|
return NULL;
|
||
|
|
}
|
||
|
|
|
||
|
|
void response_cleanup(struct response *resp) {
|
||
|
|
if (resp != NULL) {
|
||
|
|
free(resp->data);
|
||
|
|
free(resp);
|
||
|
|
}
|
||
|
|
}
|