diff --git a/src/yadisk_api_internal.c b/src/yadisk_api_internal.c index e598e0a..1144996 100644 --- a/src/yadisk_api_internal.c +++ b/src/yadisk_api_internal.c @@ -14,24 +14,63 @@ struct memory { size_t size; }; -// Callback function for writing response data -static size_t write_callback(void *contents, size_t size, size_t nmemb, struct memory *mem) { +struct data { + char trace_ascii; /* 1 or 0 */ +}; + + +static size_t cb(void *data, size_t size, size_t nmemb, void *clientp) +{ size_t realsize = size * nmemb; + struct memory *mem = (struct memory *)clientp; + char *ptr = realloc(mem->response, mem->size + realsize + 1); - if(!ptr) { - // out of memory - printf("not enough memory (realloc returned NULL)\n"); - return 0; - } + if(ptr == NULL) + return 0; /* out of memory! */ mem->response = ptr; - memcpy(&(mem->response[mem->size]), contents, realsize); + memcpy(&(mem->response[mem->size]), data, realsize); mem->size += realsize; mem->response[mem->size] = 0; return realsize; } +char* build_query_string(query_param *params, size_t num_params) { + CURL *curl = curl_easy_init(); + if (!curl) { + return NULL; + } + + char *query = NULL; + size_t query_len = 0; + + for (size_t i = 0; i < num_params; ++i) { + char *encoded_key = curl_easy_escape(curl, params[i].key, 0); + char *encoded_value = curl_easy_escape(curl, params[i].value, 0); + + // Calculate additional space needed: key=value& (including null terminator) + size_t additional_len = strlen(encoded_key) + strlen(encoded_value) + 2; + if (i < num_params - 1) { + additional_len++; // For '&' + } + + query = realloc(query, query_len + additional_len); + sprintf(query + query_len, "%s=%s", encoded_key, encoded_value); + query_len += additional_len - 1; // Minus null terminator + + if (i < num_params - 1) { + strcat(query, "&"); + } + + curl_free(encoded_key); + curl_free(encoded_value); + } + + curl_easy_cleanup(curl); + return query; +} + // Function to make an HTTP request using libcurl int api_http_request( yadisk_api_client *client, @@ -45,14 +84,19 @@ int api_http_request( CURLcode res; struct memory chunk = {0}; - curl_global_init(CURL_GLOBAL_ALL); curl = curl_easy_init(); if(curl) { - char url[256]; - snprintf(url, sizeof(url), "%s%s", YANDEX_DISK_API_HOST, path); + char url[512]; + if (num_params) { + char *query_string = build_query_string(params, num_params); + snprintf(url, sizeof(url), "%s%s?%s", YANDEX_DISK_API_HOST, path, query_string); + free(query_string); + } else { + snprintf(url, sizeof(url), "%s%s", YANDEX_DISK_API_HOST, path); + } curl_easy_setopt(curl, CURLOPT_URL, url); - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, cb); curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk); // Set the HTTP method @@ -79,7 +123,6 @@ int api_http_request( fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); free(chunk.response); curl_easy_cleanup(curl); - curl_global_cleanup(); return -1; } else { *output = strdup(chunk.response); @@ -91,6 +134,5 @@ int api_http_request( curl_easy_cleanup(curl); } - curl_global_cleanup(); return 0; } diff --git a/src/yadisk_api_internal.h b/src/yadisk_api_internal.h index c1542a1..94fd858 100644 --- a/src/yadisk_api_internal.h +++ b/src/yadisk_api_internal.h @@ -8,15 +8,41 @@ #define YANDEX_DISK_API_HOST "https://cloud-api.yandex.net" typedef struct { - const char *key; - const char *value; + const char* key; + const char* value; } query_param; -int api_http_request(yadisk_api_client *client, - const char *method, - const char *path, - query_param *params, +int api_http_request(yadisk_api_client* client, + const char* method, + const char* path, + query_param* params, size_t num_params, - char **output); + char** output); + + +#define THROW_PARSE_JSON_ERROR { \ + return YADISK_FAILED_PARSE_JSON; \ + } + +#define __DANGER_GET_JSON_OBJECT(root, key) \ + json_object* obj = NULL; \ + if (!json_object_object_get_ex(root, key, &obj)){\ + json_object_put(root); \ + THROW_PARSE_JSON_ERROR \ + } \ + +#define GET_JSON_STRING(root, key, v) { \ + __DANGER_GET_JSON_OBJECT(root, key) \ + *v = json_object_get_string(obj); \ + } + +#define GET_JSON_UINT64(root, key, v) { \ + __DANGER_GET_JSON_OBJECT(root, key) \ + *v = json_object_get_uint64(obj); \ + } +#define GET_JSON_BOOL(root, key, v) { \ + __DANGER_GET_JSON_OBJECT(root, key) \ + *v = json_object_get_boolean(obj); \ + } #endif //YADISK_YADISK_API_INTERNAL_H diff --git a/src/yadisk_get_disk.c b/src/yadisk_get_disk.c index fcd8dab..87463c1 100644 --- a/src/yadisk_get_disk.c +++ b/src/yadisk_get_disk.c @@ -9,21 +9,21 @@ yadisk_code yadisk_get_disk(yadisk_api_client* client, yadisk_disk_info* info) { char* output = NULL; int error = api_http_request(client, "GET", "/v1/disk", NULL, 0, &output); - json_object* root = json_tokener_parse(output); if (error) { - json_object_put(root); - return YADISK_FAILED_PARSE_JSON; + return YADISK_FAILED_HTTP_REQUEST; } - json_object* total_space = NULL; - if (!json_object_object_get_ex(root, "total_space", &total_space)) { - // printf("Key total_space doesn't exists!"); - return YADISK_FAILED_PARSE_JSON; - } - info->total_space = json_object_get_uint64(total_space); - json_object_put(total_space); + json_object* root = json_tokener_parse(output); + free(output); + + GET_JSON_UINT64(root, "total_space", &(info->total_space)); + GET_JSON_UINT64(root, "trash_size", &(info->trash_size)); + GET_JSON_UINT64(root, "used_space", &(info->used_space)); + GET_JSON_STRING(root, "reg_time", &(info->reg_time)); + GET_JSON_BOOL(root, "is_paid", &(info->is_paid)); json_object_put(root); - free(output); + + return YADISK_OK; } diff --git a/src/yadisk_get_disk.h b/src/yadisk_get_disk.h index 350e1a8..ff473d7 100644 --- a/src/yadisk_get_disk.h +++ b/src/yadisk_get_disk.h @@ -9,6 +9,10 @@ typedef struct yadisk_disk_info { unsigned long total_space; + unsigned long trash_size; + unsigned long used_space; + int is_paid; + const char* reg_time; } yadisk_disk_info; yadisk_code yadisk_get_disk(yadisk_api_client* client, yadisk_disk_info* info); diff --git a/src/yadisk_get_disk_resources.c b/src/yadisk_get_disk_resources.c index e0619b4..2c566f8 100644 --- a/src/yadisk_get_disk_resources.c +++ b/src/yadisk_get_disk_resources.c @@ -5,8 +5,27 @@ #include "yadisk_api_internal.h" yadisk_code -yadisk_get_disk_resources(yadisk_api_client* client, const char* path) +yadisk_get_disk_resources( + yadisk_api_client* client, const char* path, yadisk_resource_info* info +) { - char* output; - int error = api_http_request(client, "GET", "/v1/disk", NULL, 0, &output); + char* output = NULL; + query_param params[] = { + {"path", path}, + }; + int error = api_http_request(client, "GET", "/v1/disk/resources", params, 1, &output); + if (error) { + return YADISK_FAILED_HTTP_REQUEST; + } + json_object* root = json_tokener_parse(output); + free(output); + GET_JSON_STRING(root, "path", &(info->path)); + GET_JSON_STRING(root, "name", &(info->name)); + GET_JSON_STRING(root, "resource_id", &(info->resource_id)); + GET_JSON_STRING(root, "type", &(info->type)); + GET_JSON_STRING(root, "created", &(info->created)); + GET_JSON_STRING(root, "modified", &(info->modified)); + + json_object_put(root); + return YADISK_OK; }; diff --git a/src/yadisk_get_disk_resources.h b/src/yadisk_get_disk_resources.h index c70e49d..570a1ec 100644 --- a/src/yadisk_get_disk_resources.h +++ b/src/yadisk_get_disk_resources.h @@ -1,18 +1,35 @@ // // Created by maxim on 27.11.23. // +#ifndef YADISK_GET_DISK_RESOURCES_H_INCLUDED +#define YADISK_GET_DISK_RESOURCES_H_INCLUDED + #include "yadisk_shared.h" +#define YADISK_RESOURCE_ITEM_PROPERTIES \ + const char* path; \ + const char* name; \ + const char* resource_id; \ + const char* type; \ + const char* created; \ + const char* modified; + +struct yadisk_resource_item +{ + YADISK_RESOURCE_ITEM_PROPERTIES +}; + typedef struct { + unsigned long limit; + unsigned long offset; + unsigned long total; } yadisk_resource_embedded; -typedef struct -{ - const char* path; - const char* name; - const char* resource_id; - const char* type; +typedef struct { + YADISK_RESOURCE_ITEM_PROPERTIES const yadisk_resource_embedded* _embedded; } yadisk_resource_info; -yadisk_code yadisk_get_disk_resources(yadisk_api_client *client, const char *path); \ No newline at end of file +yadisk_code yadisk_get_disk_resources(yadisk_api_client* client, const char* path, yadisk_resource_info* resource); + +#endif // YADISK_GET_DISK_RESOURCES_H_INCLUDED diff --git a/src/yadisk_shared.c b/src/yadisk_shared.c index 1f6bb04..8942c07 100644 --- a/src/yadisk_shared.c +++ b/src/yadisk_shared.c @@ -3,3 +3,13 @@ // #include "yadisk_shared.h" + +int yadisk_init() +{ + return curl_global_init(CURL_GLOBAL_ALL); +} + +void yadisk_cleanup() +{ + curl_global_cleanup(); +} \ No newline at end of file diff --git a/src/yadisk_shared.h b/src/yadisk_shared.h index d0f0486..c5826f4 100644 --- a/src/yadisk_shared.h +++ b/src/yadisk_shared.h @@ -11,11 +11,15 @@ typedef enum { YADISK_OK = 0, - YADISK_FAILED_PARSE_JSON = 1 + YADISK_FAILED_PARSE_JSON = 1, + YADISK_FAILED_HTTP_REQUEST = 2 } yadisk_code; typedef struct { char* token; } yadisk_api_client; +int yadisk_init(); +void yadisk_cleanup(); + #endif //YADISK_YADISK_SHARED_H diff --git a/tests/app.c b/tests/app.c index c7e3f7a..be13d49 100644 --- a/tests/app.c +++ b/tests/app.c @@ -11,15 +11,33 @@ int main() { printf("Enter OAuth token: "); fgets(token, sizeof(token), stdin); + yadisk_init(); + yadisk_api_client* client = &(yadisk_api_client){ .token = token }; yadisk_disk_info yadisk_disk_info; - yadisk_get_disk(client, &yadisk_disk_info); - printf("Total disk size: %lu", yadisk_disk_info.total_space); + printf("Total disk size: %lu\n", yadisk_disk_info.total_space); + printf("Trash size: %lu\n", yadisk_disk_info.trash_size); + printf("Used space: %lu\n", yadisk_disk_info.used_space); + printf("Registration time: %s\n", yadisk_disk_info.reg_time); + printf("Is paid: %s\n", yadisk_disk_info.is_paid ? "Yes" : "No"); + + printf("=================\n"); + + yadisk_resource_info resource; + yadisk_get_disk_resources(client, "/", &resource); + printf("Path: %s\n", resource.path); + printf("Name: %s\n", resource.name); + printf("Type: %s\n", resource.type); + printf("Created: %s\n", resource.created); + printf("Modified: %s\n", resource.modified); + printf("ResourceID: %s\n", resource.resource_id); + + yadisk_cleanup(); return 0; -} \ No newline at end of file +}