#include #include #include #include #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); } }