This commit is contained in:
Maxim Slipenko 2023-11-29 13:57:30 +03:00
parent 9aafd0f238
commit f69b73187e
9 changed files with 186 additions and 46 deletions

View File

@ -14,24 +14,63 @@ struct memory {
size_t size; size_t size;
}; };
// Callback function for writing response data struct data {
static size_t write_callback(void *contents, size_t size, size_t nmemb, struct memory *mem) { 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; size_t realsize = size * nmemb;
struct memory *mem = (struct memory *)clientp;
char *ptr = realloc(mem->response, mem->size + realsize + 1); char *ptr = realloc(mem->response, mem->size + realsize + 1);
if(!ptr) { if(ptr == NULL)
// out of memory return 0; /* out of memory! */
printf("not enough memory (realloc returned NULL)\n");
return 0;
}
mem->response = ptr; mem->response = ptr;
memcpy(&(mem->response[mem->size]), contents, realsize); memcpy(&(mem->response[mem->size]), data, realsize);
mem->size += realsize; mem->size += realsize;
mem->response[mem->size] = 0; mem->response[mem->size] = 0;
return realsize; 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 // Function to make an HTTP request using libcurl
int api_http_request( int api_http_request(
yadisk_api_client *client, yadisk_api_client *client,
@ -45,14 +84,19 @@ int api_http_request(
CURLcode res; CURLcode res;
struct memory chunk = {0}; struct memory chunk = {0};
curl_global_init(CURL_GLOBAL_ALL);
curl = curl_easy_init(); curl = curl_easy_init();
if(curl) { if(curl) {
char url[256]; 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); snprintf(url, sizeof(url), "%s%s", YANDEX_DISK_API_HOST, path);
}
curl_easy_setopt(curl, CURLOPT_URL, url); 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); curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk);
// Set the HTTP method // Set the HTTP method
@ -79,7 +123,6 @@ int api_http_request(
fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
free(chunk.response); free(chunk.response);
curl_easy_cleanup(curl); curl_easy_cleanup(curl);
curl_global_cleanup();
return -1; return -1;
} else { } else {
*output = strdup(chunk.response); *output = strdup(chunk.response);
@ -91,6 +134,5 @@ int api_http_request(
curl_easy_cleanup(curl); curl_easy_cleanup(curl);
} }
curl_global_cleanup();
return 0; return 0;
} }

View File

@ -8,15 +8,41 @@
#define YANDEX_DISK_API_HOST "https://cloud-api.yandex.net" #define YANDEX_DISK_API_HOST "https://cloud-api.yandex.net"
typedef struct { typedef struct {
const char *key; const char* key;
const char *value; const char* value;
} query_param; } query_param;
int api_http_request(yadisk_api_client *client, int api_http_request(yadisk_api_client* client,
const char *method, const char* method,
const char *path, const char* path,
query_param *params, query_param* params,
size_t num_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 #endif //YADISK_YADISK_API_INTERNAL_H

View File

@ -9,21 +9,21 @@ yadisk_code yadisk_get_disk(yadisk_api_client* client, yadisk_disk_info* info)
{ {
char* output = NULL; char* output = NULL;
int error = api_http_request(client, "GET", "/v1/disk", NULL, 0, &output); int error = api_http_request(client, "GET", "/v1/disk", NULL, 0, &output);
json_object* root = json_tokener_parse(output);
if (error) { if (error) {
json_object_put(root); return YADISK_FAILED_HTTP_REQUEST;
return YADISK_FAILED_PARSE_JSON;
} }
json_object* total_space = NULL; json_object* root = json_tokener_parse(output);
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_put(root);
free(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);
return YADISK_OK; return YADISK_OK;
} }

View File

@ -9,6 +9,10 @@
typedef struct yadisk_disk_info { typedef struct yadisk_disk_info {
unsigned long total_space; unsigned long total_space;
unsigned long trash_size;
unsigned long used_space;
int is_paid;
const char* reg_time;
} yadisk_disk_info; } yadisk_disk_info;
yadisk_code yadisk_get_disk(yadisk_api_client* client, yadisk_disk_info* info); yadisk_code yadisk_get_disk(yadisk_api_client* client, yadisk_disk_info* info);

View File

@ -5,8 +5,27 @@
#include "yadisk_api_internal.h" #include "yadisk_api_internal.h"
yadisk_code 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; char* output = NULL;
int error = api_http_request(client, "GET", "/v1/disk", NULL, 0, &output); 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;
}; };

View File

@ -1,18 +1,35 @@
// //
// Created by maxim on 27.11.23. // 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" #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 { typedef struct {
unsigned long limit;
unsigned long offset;
unsigned long total;
} yadisk_resource_embedded; } yadisk_resource_embedded;
typedef struct typedef struct {
{ YADISK_RESOURCE_ITEM_PROPERTIES
const char* path;
const char* name;
const char* resource_id;
const char* type;
const yadisk_resource_embedded* _embedded; const yadisk_resource_embedded* _embedded;
} yadisk_resource_info; } yadisk_resource_info;
yadisk_code yadisk_get_disk_resources(yadisk_api_client *client, const char *path); yadisk_code yadisk_get_disk_resources(yadisk_api_client* client, const char* path, yadisk_resource_info* resource);
#endif // YADISK_GET_DISK_RESOURCES_H_INCLUDED

View File

@ -3,3 +3,13 @@
// //
#include "yadisk_shared.h" #include "yadisk_shared.h"
int yadisk_init()
{
return curl_global_init(CURL_GLOBAL_ALL);
}
void yadisk_cleanup()
{
curl_global_cleanup();
}

View File

@ -11,11 +11,15 @@
typedef enum { typedef enum {
YADISK_OK = 0, YADISK_OK = 0,
YADISK_FAILED_PARSE_JSON = 1 YADISK_FAILED_PARSE_JSON = 1,
YADISK_FAILED_HTTP_REQUEST = 2
} yadisk_code; } yadisk_code;
typedef struct { typedef struct {
char* token; char* token;
} yadisk_api_client; } yadisk_api_client;
int yadisk_init();
void yadisk_cleanup();
#endif //YADISK_YADISK_SHARED_H #endif //YADISK_YADISK_SHARED_H

View File

@ -11,15 +11,33 @@ int main() {
printf("Enter OAuth token: "); printf("Enter OAuth token: ");
fgets(token, sizeof(token), stdin); fgets(token, sizeof(token), stdin);
yadisk_init();
yadisk_api_client* client = &(yadisk_api_client){ yadisk_api_client* client = &(yadisk_api_client){
.token = token .token = token
}; };
yadisk_disk_info yadisk_disk_info; yadisk_disk_info yadisk_disk_info;
yadisk_get_disk(client, &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; return 0;
} }