Plan cloud transfer requests

This commit is contained in:
2026-06-05 07:27:51 +02:00
parent a104f88360
commit a79ef4cda8
8 changed files with 430 additions and 10 deletions

View File

@@ -11,6 +11,7 @@
#include "app_core/app_startup.h"
#include "app_core/app_thread.h"
#include "app_core/canvas_tool_ui.h"
#include "app_core/document_cloud.h"
#include "app_core/document_recording.h"
#include "app_core/document_route.h"
#include "app_core/document_session.h"
@@ -272,16 +273,28 @@ void App::initLog()
int progress_callback_download(void *clientp, curl_off_t dltotal,
curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow)
{
std::function<void(float)> progress = *(std::function<void(float)>*)clientp;
progress((float)dlnow / (float)dltotal);
(void)ultotal;
(void)ulnow;
auto* progress = static_cast<std::function<void(float)>*>(clientp);
const auto plan = pp::app::plan_cloud_transfer_progress(
static_cast<std::int64_t>(dltotal),
static_cast<std::int64_t>(dlnow));
if (progress != nullptr && *progress && plan.notify)
(*progress)(plan.fraction);
return 0;
}
int progress_callback_upload(void *clientp, curl_off_t dltotal,
curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow)
{
std::function<void(float)> progress = *(std::function<void(float)>*)clientp;
progress((float)ulnow / (float)ultotal);
(void)dltotal;
(void)dlnow;
auto* progress = static_cast<std::function<void(float)>*>(clientp);
const auto plan = pp::app::plan_cloud_transfer_progress(
static_cast<std::int64_t>(ultotal),
static_cast<std::int64_t>(ulnow));
if (progress != nullptr && *progress && plan.notify)
(*progress)(plan.fraction);
return 0;
}
#endif //CURL
@@ -289,17 +302,32 @@ int progress_callback_upload(void *clientp, curl_off_t dltotal,
void App::download(std::string url, std::string dest_filepath, std::function<void(float)> progress)
{
#if WITH_CURL
const auto plan = pp::app::plan_cloud_download_transfer(
url,
dest_filepath,
progress != nullptr,
disables_network_tls_verification());
if (plan.action != pp::app::CloudTransferAction::start_transfer) {
LOG("download skipped: invalid transfer request");
return;
}
CURL *curl = curl_easy_init();
if (curl)
{
FILE* fp = fopen(dest_filepath.c_str(), "wb");
if (fp == nullptr) {
LOG("download failed to open destination %s", dest_filepath.c_str());
curl_easy_cleanup(curl);
return;
}
LOG("download %s to %s", url.c_str(), dest_filepath.c_str());
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_data_write);
if (disables_network_tls_verification())
if (plan.disable_tls_verification)
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
if (progress)
if (plan.enable_progress)
{
curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, progress_callback_download);
curl_easy_setopt(curl, CURLOPT_XFERINFODATA, &progress);
@@ -349,6 +377,15 @@ bool App::check_license()
void App::upload(std::string filename, std::string name, std::function<void(float)> progress)
{
#if WITH_CURL
const auto plan = pp::app::plan_cloud_upload_transfer(
filename,
progress != nullptr,
disables_network_tls_verification());
if (plan.action != pp::app::CloudTransferAction::start_transfer) {
LOG("upload skipped: invalid transfer request");
return;
}
CURL *curl;
struct curl_httppost *formpost = NULL;
@@ -372,9 +409,9 @@ void App::upload(std::string filename, std::string name, std::function<void(floa
curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &res);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_data_handler);
if (disables_network_tls_verification())
if (plan.disable_tls_verification)
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
if (progress)
if (plan.enable_progress)
{
curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, progress_callback_upload);
curl_easy_setopt(curl, CURLOPT_XFERINFODATA, &progress);

View File

@@ -3,6 +3,7 @@
#include "foundation/result.h"
#include <cstddef>
#include <cstdint>
#include <limits>
#include <string>
#include <string_view>
@@ -25,6 +26,17 @@ enum class CloudDownloadSelectionAction {
start_download,
};
enum class CloudTransferDirection {
download,
upload,
};
enum class CloudTransferAction {
reject_missing_source,
reject_missing_destination,
start_transfer,
};
struct CloudUploadPlan {
CloudUploadAction action = CloudUploadAction::unavailable_no_canvas;
bool save_before_upload = false;
@@ -42,6 +54,18 @@ struct CloudDownloadRequest {
std::string selected_name;
};
struct CloudTransferPlan {
CloudTransferDirection direction = CloudTransferDirection::download;
CloudTransferAction action = CloudTransferAction::reject_missing_source;
bool enable_progress = false;
bool disable_tls_verification = false;
};
struct CloudTransferProgressPlan {
bool notify = false;
float fraction = 0.0F;
};
class CloudServices {
public:
virtual ~CloudServices() = default;
@@ -98,6 +122,77 @@ public:
};
}
[[nodiscard]] constexpr CloudTransferPlan plan_cloud_download_transfer(
std::string_view url,
std::string_view destination_path,
bool has_progress_callback,
bool disables_tls_verification) noexcept
{
if (url.empty()) {
return {
CloudTransferDirection::download,
CloudTransferAction::reject_missing_source,
false,
false,
};
}
if (destination_path.empty()) {
return {
CloudTransferDirection::download,
CloudTransferAction::reject_missing_destination,
false,
false,
};
}
return {
CloudTransferDirection::download,
CloudTransferAction::start_transfer,
has_progress_callback,
disables_tls_verification,
};
}
[[nodiscard]] constexpr CloudTransferPlan plan_cloud_upload_transfer(
std::string_view filename,
bool has_progress_callback,
bool disables_tls_verification) noexcept
{
if (filename.empty()) {
return {
CloudTransferDirection::upload,
CloudTransferAction::reject_missing_source,
false,
false,
};
}
return {
CloudTransferDirection::upload,
CloudTransferAction::start_transfer,
has_progress_callback,
disables_tls_verification,
};
}
[[nodiscard]] constexpr CloudTransferProgressPlan plan_cloud_transfer_progress(
std::int64_t total,
std::int64_t current) noexcept
{
if (total <= 0) {
return {};
}
const auto clamped_current = current < 0
? std::int64_t { 0 }
: (current > total ? total : current);
return {
true,
static_cast<float>(static_cast<double>(clamped_current) / static_cast<double>(total)),
};
}
[[nodiscard]] inline pp::foundation::Status execute_cloud_upload_plan(
const CloudUploadPlan& plan,
CloudServices& services)