libyadisk/src/yadisk_api_internal.c

141 lines
3.9 KiB
C
Raw Normal View History

//
// Created by maxim on 27.11.23.
//
#include <string.h>
#include <stdlib.h>
#include <curl/curl.h>
#include <json.h>
#include "yadisk_shared.h"
#include "yadisk_api_internal.h"
struct memory {
2023-11-29 14:00:52 +03:00
char* response;
size_t size;
};
2023-11-29 13:57:30 +03:00
struct data {
char trace_ascii; /* 1 or 0 */
};
2023-11-29 14:00:52 +03:00
static size_t cb(void* data, size_t size, size_t nmemb, void* clientp)
2023-11-29 13:57:30 +03:00
{
size_t realsize = size * nmemb;
2023-11-29 14:00:52 +03:00
struct memory* mem = (struct memory*)clientp;
2023-11-29 13:57:30 +03:00
2023-11-29 14:00:52 +03:00
char* ptr = realloc(mem->response, mem->size + realsize + 1);
if (ptr == NULL)
2023-11-29 13:57:30 +03:00
return 0; /* out of memory! */
mem->response = ptr;
2023-11-29 13:57:30 +03:00
memcpy(&(mem->response[mem->size]), data, realsize);
mem->size += realsize;
mem->response[mem->size] = 0;
return realsize;
}
2023-11-29 14:00:52 +03:00
char* build_query_string(query_param* params, size_t num_params)
{
CURL* curl = curl_easy_init();
2023-11-29 13:57:30 +03:00
if (!curl) {
return NULL;
}
2023-11-29 14:00:52 +03:00
char* query = NULL;
2023-11-29 13:57:30 +03:00
size_t query_len = 0;
for (size_t i = 0; i < num_params; ++i) {
2023-11-29 14:00:52 +03:00
char* encoded_key = curl_easy_escape(curl, params[i].key, 0);
char* encoded_value = curl_easy_escape(curl, params[i].value, 0);
2023-11-29 13:57:30 +03:00
// 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(
2023-11-29 14:00:52 +03:00
yadisk_api_client* client,
const char* method,
const char* path,
query_param* params,
size_t num_params,
char** output
)
{
CURL* curl;
CURLcode res;
struct memory chunk = {0};
curl = curl_easy_init();
2023-11-29 14:00:52 +03:00
if (curl) {
2023-11-29 13:57:30 +03:00
char url[512];
if (num_params) {
2023-11-29 14:00:52 +03:00
char* query_string = build_query_string(params, num_params);
2023-11-29 13:57:30 +03:00
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);
2023-11-29 13:57:30 +03:00
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, cb);
2023-11-29 14:00:52 +03:00
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void*)&chunk);
// Set the HTTP method
if (strcmp(method, "GET") == 0) {
curl_easy_setopt(curl, CURLOPT_HTTPGET, 1L);
} else if (strcmp(method, "POST") == 0) {
curl_easy_setopt(curl, CURLOPT_POST, 1L);
} else if (strcmp(method, "DELETE") == 0) {
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "DELETE");
} else if (strcmp(method, "PATCH") == 0) {
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PATCH");
}
// Set the authorization header
char auth_header[256];
snprintf(auth_header, sizeof(auth_header), "Authorization: OAuth %s", client->token);
2023-11-29 14:00:52 +03:00
struct curl_slist* headers = NULL;
headers = curl_slist_append(headers, auth_header);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
// Perform the request
res = curl_easy_perform(curl);
2023-11-29 14:00:52 +03:00
if (res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
free(chunk.response);
curl_easy_cleanup(curl);
return -1;
} else {
*output = strdup(chunk.response);
}
// Clean up
curl_slist_free_all(headers);
free(chunk.response);
curl_easy_cleanup(curl);
}
return 0;
2023-11-28 22:13:58 +03:00
}