neocities.h

a C library for interacting with Neocities' API
git clone https://github.com/tanguyandreani/neocities.h
Log | Files | Refs | README | LICENSE

commit 693330e26543401d43023840d4dd0eeaea33a701
parent 6c74683a4eb785714839512716ad63331dfcc5e3
Author: Tanguy Andreani <dev@tanguy.space>
Date:   Thu, 21 Feb 2019 21:18:30 +0100

Break: better design + error handling

Diffstat:
Mexample.c | 23+++++++++--------------
Mneocities.h | 134++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------
2 files changed, 108 insertions(+), 49 deletions(-)

diff --git a/example.c b/example.c @@ -3,29 +3,24 @@ #include <string.h> #include <curl/curl.h> -#include <json-c/json.h> +#include <json.h> #include "neocities.h" int main(void) { - json_object *obj = NULL; + json_object * jobj; + int err; - curl_global_init(CURL_GLOBAL_SSL); + if (curl_global_init(CURL_GLOBAL_SSL) != 0) + return NEOCITIES_ERR_CURL_GLOBAL_INIT; + if ((err = neocities_api(APIKEY, INFO, "lainzine", &jobj)) != NEOCITIES_OK) + return err; -// obj = neocities_api(APIKEY, INFO, "lainzine"); - obj = neocities_api(APIKEY, INFO, ""); printf("%s\n", - json_object_to_json_string_ext(obj, JSON_C_TO_STRING_PRETTY)); - json_object_put(obj); - - - obj = neocities_api(APIKEY, UPLOAD, "neocities.h"); - printf("%s\n", - json_object_to_json_string_ext(obj, JSON_C_TO_STRING_PRETTY)); - json_object_put(obj); - + json_object_to_json_string_ext(jobj, JSON_C_TO_STRING_PRETTY)); + // fflush(stdout); curl_global_cleanup(); diff --git a/neocities.h b/neocities.h @@ -14,24 +14,51 @@ #define INFO BASEURL "info" #define KEY BASEURL "key" +enum neocities_error { + NEOCITIES_OK, + NEOCITIES_ERR_CURL_GLOBAL_INIT, + NEOCITIES_ERR_JSON_TOKENER_NEW, + NEOCITIES_ERR_CURL_EASY_INIT, + NEOCITIES_ERR_CURL_MIME_INIT, + NEOCITIES_ERR_CURL_MIME_ADDPART, + NEOCITIES_ERR_CURL_MIME_NAME, + NEOCITIES_ERR_CURL_MIME_FILEDATA, + NEOCITIES_ERR_CURL_MIME_DATA, + NEOCITIES_ERR_CURL_SLIST_APPEND, + NEOCITIES_ERR_CURL_EASY_SETOPT, + NEOCITIES_ERR_UNSUPPORTED_DELETE, + NEOCITIES_ERR_BAD_ACTION, + NEOCITIES_ERR_NEOCITIES_INIT, + NEOCITIES_ERR_CURL_EASY_PERFORM, + NEOCITIES_ERR_JSON_TOKENER_PARSE +}; + typedef struct Neocities_ { char *buf; int size; int pos; } Neocities; -void neocities_init(Neocities * neocities, size_t size) +int neocities_init(Neocities * neocities, size_t size) { neocities->buf = malloc(sizeof(char) * size); + + if (neocities->buf == NULL) + return 1; + neocities->size = size; neocities->pos = 0; - return; + return 0; } void neocities_destroy(Neocities * neocities) { free(neocities->buf); + neocities->buf = NULL; + + neocities->size = 0; + neocities->pos = 0; return; } @@ -58,6 +85,8 @@ size_t write_data(void *buffer, size_t size, size_t nmemb, neocities->size += nmemb; neocities->buf = realloc(neocities->buf, sizeof(char) * neocities->size); + if (neocities->buf == NULL) + return neocities->size; } neocities->buf[neocities->pos] = *(char *) (buffer + i); @@ -69,56 +98,76 @@ size_t write_data(void *buffer, size_t size, size_t nmemb, return i; } -json_object *neocities_api(const char *apikey, const char *action, - const char *params) +enum neocities_error neocities_api(const char *apikey, const char *action, + const char *params, json_object ** obj) { Neocities neocities; - struct curl_slist *headers; + struct curl_slist *headers = NULL; CURL *curl; curl_mime *form = NULL; curl_mimepart *field = NULL; - json_object *empty_error = - json_object_new_string("neocities_api() failed somewhere."); - json_tokener *tok = json_tokener_new(); - json_object *obj = NULL; char url_with_get_params[500]; - headers = NULL; + if (tok == NULL) + return NEOCITIES_ERR_JSON_TOKENER_NEW; curl = curl_easy_init(); - if (!curl) { - fprintf(stderr, "couldn't initialize an easy handle.\n"); - return empty_error; - } + if (curl == NULL) + return NEOCITIES_ERR_CURL_EASY_INIT; if (strcmp(action, UPLOAD) == 0) { form = curl_mime_init(curl); + if (form == NULL) + return NEOCITIES_ERR_CURL_MIME_INIT; + field = curl_mime_addpart(form); - curl_mime_name(field, "sendfile"); - curl_mime_filedata(field, params); + + if (field == NULL) + return NEOCITIES_ERR_CURL_MIME_ADDPART; + + if (curl_mime_name(field, "sendfile") != CURLE_OK) + return NEOCITIES_ERR_CURL_MIME_NAME; + + if (curl_mime_filedata(field, params) != CURLE_OK) + return NEOCITIES_ERR_CURL_MIME_FILEDATA; field = curl_mime_addpart(form); - curl_mime_name(field, "filename"); - curl_mime_data(field, params, CURL_ZERO_TERMINATED); + + if (field == NULL) + return NEOCITIES_ERR_CURL_MIME_ADDPART; + + if (curl_mime_name(field, "filename") != CURLE_OK) + return NEOCITIES_ERR_CURL_MIME_NAME; + + if (curl_mime_data(field, params, CURL_ZERO_TERMINATED) != + CURLE_OK) + return NEOCITIES_ERR_CURL_MIME_DATA; + + field = NULL; headers = curl_slist_append(headers, "Expect:"); - curl_easy_setopt(curl, CURLOPT_MIMEPOST, form); - curl_easy_setopt(curl, CURLOPT_URL, action); + if (headers == NULL) + return NEOCITIES_ERR_CURL_SLIST_APPEND; + + if (curl_easy_setopt(curl, CURLOPT_MIMEPOST, form) != CURLE_OK) + return NEOCITIES_ERR_CURL_EASY_SETOPT; + + if (curl_easy_setopt(curl, CURLOPT_URL, action) != CURLE_OK) + return NEOCITIES_ERR_CURL_EASY_SETOPT; } else if (strcmp(action, DELETE) == 0) { - fprintf(stderr, "DELETE is currently unsupported.\n"); - return empty_error; + return NEOCITIES_ERR_UNSUPPORTED_DELETE; } else if (strcmp(action, INFO) == 0 || strcmp(action, LIST) == 0 || strcmp(action, KEY) == 0) { @@ -131,41 +180,56 @@ json_object *neocities_api(const char *apikey, const char *action, strcat(url_with_get_params, "?path="); strcat(url_with_get_params, params); - curl_easy_setopt(curl, CURLOPT_URL, url_with_get_params); + + if (curl_easy_setopt(curl, CURLOPT_URL, url_with_get_params) != + CURLE_OK) + return NEOCITIES_ERR_CURL_EASY_SETOPT; } else { - fprintf(stderr, "bad action.\n"); - return empty_error; + return NEOCITIES_ERR_BAD_ACTION; } char auth_bearer[22 + 32 + 1] = "Authorization: Bearer "; strcat(auth_bearer, apikey); - neocities_init(&neocities, 700); + if (neocities_init(&neocities, 700) != 0) + return NEOCITIES_ERR_NEOCITIES_INIT; headers = curl_slist_append(headers, auth_bearer); - curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data); - curl_easy_setopt(curl, CURLOPT_WRITEDATA, ((Neocities *) & neocities)); + if (headers == NULL) + return NEOCITIES_ERR_CURL_SLIST_APPEND; - if (curl_easy_perform(curl) != CURLE_OK) { - fprintf(stderr, "curl failed.\n"); - return empty_error; - } + if (curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers) != CURLE_OK) + return NEOCITIES_ERR_CURL_EASY_SETOPT; + + if (curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data) != + CURLE_OK) + return NEOCITIES_ERR_CURL_EASY_SETOPT; + + if (curl_easy_setopt + (curl, CURLOPT_WRITEDATA, ((Neocities *) & neocities))) + return NEOCITIES_ERR_CURL_EASY_SETOPT; + + if (curl_easy_perform(curl) != CURLE_OK) + return NEOCITIES_ERR_CURL_EASY_PERFORM; curl_slist_free_all(headers); curl_mime_free(form); curl_easy_cleanup(curl); - obj = + *obj = json_tokener_parse_ex(tok, (char *) neocities.buf, neocities.pos); + neocities_dump(&neocities); neocities_destroy(&neocities); - return obj; + if (*obj == NULL) + return NEOCITIES_ERR_JSON_TOKENER_PARSE; + + return NEOCITIES_OK; } #endif