2023-11-27 19:50:27 +03:00
|
|
|
//
|
|
|
|
// 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;
|
2023-11-27 19:50:27 +03:00
|
|
|
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
|
|
|
{
|
2023-11-27 19:50:27 +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! */
|
2023-11-27 19:50:27 +03:00
|
|
|
|
|
|
|
mem->response = ptr;
|
2023-11-29 13:57:30 +03:00
|
|
|
memcpy(&(mem->response[mem->size]), data, realsize);
|
2023-11-27 19:50:27 +03:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2023-11-27 19:50:27 +03:00
|
|
|
// 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;
|
2023-11-27 19:50:27 +03:00
|
|
|
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);
|
|
|
|
}
|
2023-11-27 19:50:27 +03:00
|
|
|
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);
|
2023-11-27 19:50:27 +03:00
|
|
|
|
|
|
|
// 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;
|
2023-11-27 19:50:27 +03:00
|
|
|
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) {
|
2023-11-27 19:50:27 +03:00
|
|
|
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
|
|
|
}
|