add game dump uploading, fix download progress using u32 instead of s64, add progress and title for usb game dump.

- added support for custom upload locations, set in /config/sphaira/locations.ini
- add support for various auth options for download/upload (port, pub/priv key, user/pass, bearer).
This commit is contained in:
ITotalJustice
2025-05-18 20:30:04 +01:00
parent bd7eadc6a0
commit 71df5317be
7 changed files with 641 additions and 34 deletions

View File

@@ -29,7 +29,8 @@ struct ApiResult;
using Path = fs::FsPath;
using OnComplete = std::function<void(ApiResult& result)>;
using OnProgress = std::function<bool(u32 dltotal, u32 dlnow, u32 ultotal, u32 ulnow)>;
using OnProgress = std::function<bool(s64 dltotal, s64 dlnow, s64 ultotal, s64 ulnow)>;
using OnUploadCallback = std::function<size_t(void *ptr, size_t size)>;
using StopToken = std::stop_token;
struct Url {
@@ -62,6 +63,48 @@ struct Flags {
u32 m_flags{Flag_None};
};
struct Port {
Port() = default;
Port(u16 port) : m_port{port} {}
u16 m_port{};
};
struct UserPass {
UserPass() = default;
UserPass(const std::string& user) : m_user{user} {}
UserPass(const std::string& user, const std::string& pass) : m_user{user}, m_pass{pass} {}
std::string m_user;
std::string m_pass;
};
struct UploadInfo {
UploadInfo() = default;
UploadInfo(const std::string& name, s64 size, OnUploadCallback cb) : m_name{name}, m_size{size}, m_callback{cb} {}
UploadInfo(const std::string& name, const std::vector<u8>& data) : m_name{name}, m_data{data} {}
std::string m_name{};
std::vector<u8> m_data{};
s64 m_size{};
OnUploadCallback m_callback{};
};
struct Bearer {
Bearer() = default;
Bearer(const std::string& str) : m_str{str} {}
std::string m_str;
};
struct PubKey {
PubKey() = default;
PubKey(const std::string& str) : m_str{str} {}
std::string m_str;
};
struct PrivKey {
PrivKey() = default;
PrivKey(const std::string& str) : m_str{str} {}
std::string m_str;
};
struct ApiResult {
bool success;
long code;
@@ -82,10 +125,14 @@ void Exit();
// sync functions
auto ToMemory(const Api& e) -> ApiResult;
auto ToFile(const Api& e) -> ApiResult;
auto FromMemory(const Api& e) -> ApiResult;
auto FromFile(const Api& e) -> ApiResult;
// async functions
auto ToMemoryAsync(const Api& e) -> bool;
auto ToFileAsync(const Api& e) -> bool;
auto FromMemoryAsync(const Api& e) -> bool;
auto FromFileAsync(const Api& e) -> bool;
// uses curl to convert string to their %XX
auto EscapeString(const std::string& str) -> std::string;
@@ -107,6 +154,15 @@ struct Api {
}
}
template <typename... Ts>
auto From(Ts&&... ts) {
if constexpr(std::disjunction_v<std::is_same<Path, Ts>...>) {
return FromFile(std::forward<Ts>(ts)...);
} else {
return FromMemory(std::forward<Ts>(ts)...);
}
}
template <typename... Ts>
auto ToAsync(Ts&&... ts) {
if constexpr(std::disjunction_v<std::is_same<Path, Ts>...>) {
@@ -116,6 +172,15 @@ struct Api {
}
}
template <typename... Ts>
auto FromAsync(Ts&&... ts) {
if constexpr(std::disjunction_v<std::is_same<Path, Ts>...>) {
return FromFileAsync(std::forward<Ts>(ts)...);
} else {
return FromMemoryAsync(std::forward<Ts>(ts)...);
}
}
template <typename... Ts>
auto ToMemory(Ts&&... ts) {
static_assert(std::disjunction_v<std::is_same<Url, Ts>...>, "Url must be specified");
@@ -125,6 +190,16 @@ struct Api {
return curl::ToMemory(*this);
}
template <typename... Ts>
auto FromMemory(Ts&&... ts) {
static_assert(std::disjunction_v<std::is_same<Url, Ts>...>, "Url must be specified");
static_assert(std::disjunction_v<std::is_same<UploadInfo, Ts>...>, "UploadInfo must be specified");
static_assert(!std::disjunction_v<std::is_same<Path, Ts>...>, "Path must not valid for memory");
static_assert(!std::disjunction_v<std::is_same<OnComplete, Ts>...>, "OnComplete must not be specified");
Api::set_option(std::forward<Ts>(ts)...);
return curl::FromMemory(*this);
}
template <typename... Ts>
auto ToFile(Ts&&... ts) {
static_assert(std::disjunction_v<std::is_same<Url, Ts>...>, "Url must be specified");
@@ -134,6 +209,15 @@ struct Api {
return curl::ToFile(*this);
}
template <typename... Ts>
auto FromFile(Ts&&... ts) {
static_assert(std::disjunction_v<std::is_same<Url, Ts>...>, "Url must be specified");
static_assert(std::disjunction_v<std::is_same<Path, Ts>...>, "Path must be specified");
static_assert(!std::disjunction_v<std::is_same<OnComplete, Ts>...>, "OnComplete must not be specified");
Api::set_option(std::forward<Ts>(ts)...);
return curl::FromFile(*this);
}
template <typename... Ts>
auto ToMemoryAsync(Ts&&... ts) {
static_assert(std::disjunction_v<std::is_same<Url, Ts>...>, "Url must be specified");
@@ -144,6 +228,17 @@ struct Api {
return curl::ToMemoryAsync(*this);
}
template <typename... Ts>
auto FromMemoryAsync(Ts&&... ts) {
static_assert(std::disjunction_v<std::is_same<Url, Ts>...>, "Url must be specified");
static_assert(std::disjunction_v<std::is_same<UploadInfo, Ts>...>, "UploadInfo must be specified");
static_assert(std::disjunction_v<std::is_same<OnComplete, Ts>...>, "OnComplete must be specified");
static_assert(!std::disjunction_v<std::is_same<Path, Ts>...>, "Path must not valid for memory");
static_assert(std::disjunction_v<std::is_same<StopToken, Ts>...>, "StopToken must be specified");
Api::set_option(std::forward<Ts>(ts)...);
return curl::FromMemoryAsync(*this);
}
template <typename... Ts>
auto ToFileAsync(Ts&&... ts) {
static_assert(std::disjunction_v<std::is_same<Url, Ts>...>, "Url must be specified");
@@ -154,6 +249,23 @@ struct Api {
return curl::ToFileAsync(*this);
}
template <typename... Ts>
auto FromFileAsync(Ts&&... ts) {
static_assert(std::disjunction_v<std::is_same<Url, Ts>...>, "Url must be specified");
static_assert(std::disjunction_v<std::is_same<Path, Ts>...>, "Path must be specified");
static_assert(std::disjunction_v<std::is_same<OnComplete, Ts>...>, "OnComplete must be specified");
static_assert(std::disjunction_v<std::is_same<StopToken, Ts>...>, "StopToken must be specified");
Api::set_option(std::forward<Ts>(ts)...);
return curl::FromFileAsync(*this);
}
void SetUpload(bool enable) {
m_is_upload = enable;
}
auto IsUpload() const {
return m_is_upload;
}
auto& GetUrl() const {
return m_url.m_str;
}
@@ -169,6 +281,24 @@ struct Api {
auto& GetPath() const {
return m_path;
}
auto& GetPort() const {
return m_port;
}
auto& GetUserPass() const {
return m_userpass;
}
auto& GetBearer() const {
return m_bearer;
}
auto& GetPubKey() const {
return m_pub_key;
}
auto& GetPrivKey() const {
return m_priv_key;
}
auto& GetUploadInfo() const {
return m_info;
}
auto& GetOnComplete() const {
return m_on_complete;
}
@@ -198,6 +328,24 @@ private:
void SetOption(Path&& v) {
m_path = v;
}
void SetOption(Port&& v) {
m_port = v;
}
void SetOption(UserPass&& v) {
m_userpass = v;
}
void SetOption(Bearer&& v) {
m_bearer = v;
}
void SetOption(PubKey&& v) {
m_pub_key = v;
}
void SetOption(PrivKey&& v) {
m_priv_key = v;
}
void SetOption(UploadInfo&& v) {
m_info = v;
}
void SetOption(OnComplete&& v) {
m_on_complete = v;
}
@@ -228,11 +376,18 @@ private:
Header m_header{};
Flags m_flags{};
Path m_path{};
OnComplete m_on_complete{nullptr};
OnProgress m_on_progress{nullptr};
Port m_port{};
UserPass m_userpass{};
Bearer m_bearer{};
PubKey m_pub_key{};
PrivKey m_priv_key{};
UploadInfo m_info{};
OnComplete m_on_complete{};
OnProgress m_on_progress{};
Priority m_prio{Priority::High};
std::stop_source m_stop_source{};
StopToken m_stoken{m_stop_source.get_token()};
bool m_is_upload{};
};
} // namespace sphaira::curl