From 893b0d142efe80c4347cb94588c85ac0b46a17da Mon Sep 17 00:00:00 2001 From: Eric Warmenhoven Date: Fri, 4 Aug 2023 03:20:50 -0400 Subject: [PATCH] Cloud Sync (#15548) * cloud sync - algorithm and abstract cloud storage API * WebDAV cloud sync driver, and associated net_http improvements * Cloud sync settings menu --- configuration.c | 6 + configuration.h | 9 + griffin/griffin.c | 9 + intl/msg_hash_lbl.h | 32 + intl/msg_hash_us.h | 56 + libretro-common/include/net/net_http.h | 14 + libretro-common/net/net_http.c | 91 +- libretro-common/net/net_socket_ssl_mbed.c | 21 +- list_special.h | 1 + menu/cbs/menu_cbs_deferred_push.c | 7 +- menu/cbs/menu_cbs_ok.c | 5 + menu/cbs/menu_cbs_sublabel.c | 28 + menu/cbs/menu_cbs_title.c | 5 + menu/drivers/materialui.c | 1 + menu/drivers/ozone.c | 1 + menu/drivers/xmb.c | 1 + menu/menu_cbs.h | 1 + menu/menu_displaylist.c | 24 + menu/menu_displaylist.h | 1 + menu/menu_setting.c | 127 +- msg_hash.h | 8 + network/cloud_sync/webdav.c | 803 +++++++++++++ network/cloud_sync_driver.c | 126 ++ network/cloud_sync_driver.h | 77 ++ pkg/apple/BaseConfig.xcconfig | 1 + .../RetroArch_iOS13.xcodeproj/project.pbxproj | 4 + retroarch.c | 36 + tasks/task_cloudsync.c | 1064 +++++++++++++++++ tasks/task_http.c | 118 +- tasks/tasks_internal.h | 16 + 30 files changed, 2667 insertions(+), 26 deletions(-) create mode 100644 network/cloud_sync/webdav.c create mode 100644 network/cloud_sync_driver.c create mode 100644 network/cloud_sync_driver.h create mode 100644 tasks/task_cloudsync.c diff --git a/configuration.c b/configuration.c index 14ac60819a..b03630c73e 100644 --- a/configuration.c +++ b/configuration.c @@ -1490,6 +1490,7 @@ static struct config_array_setting *populate_settings_array(settings_t *settings SETTING_ARRAY("bluetooth_driver", settings->arrays.bluetooth_driver, false, NULL, true); SETTING_ARRAY("wifi_driver", settings->arrays.wifi_driver, false, NULL, true); SETTING_ARRAY("location_driver", settings->arrays.location_driver,false, NULL, true); + SETTING_ARRAY("cloud_sync_driver", settings->arrays.cloud_sync_driver, false, NULL, true); #ifdef HAVE_MENU SETTING_ARRAY("menu_driver", settings->arrays.menu_driver, false, NULL, true); #endif @@ -1516,6 +1517,9 @@ static struct config_array_setting *populate_settings_array(settings_t *settings SETTING_ARRAY("midi_driver", settings->arrays.midi_driver, false, NULL, true); SETTING_ARRAY("midi_input", settings->arrays.midi_input, true, DEFAULT_MIDI_INPUT, true); SETTING_ARRAY("midi_output", settings->arrays.midi_output, true, DEFAULT_MIDI_OUTPUT, true); + SETTING_ARRAY("webdav_url", settings->arrays.webdav_url, false, NULL, true); + SETTING_ARRAY("webdav_username", settings->arrays.webdav_username, false, NULL, true); + SETTING_ARRAY("webdav_password", settings->arrays.webdav_password, false, NULL, true); SETTING_ARRAY("youtube_stream_key", settings->arrays.youtube_stream_key, true, NULL, true); SETTING_ARRAY("twitch_stream_key", settings->arrays.twitch_stream_key, true, NULL, true); SETTING_ARRAY("facebook_stream_key", settings->arrays.facebook_stream_key, true, NULL, true); @@ -1848,6 +1852,8 @@ static struct config_bool_setting *populate_settings_bool( SETTING_BOOL("core_updater_show_experimental_cores", &settings->bools.network_buildbot_show_experimental_cores, true, DEFAULT_NETWORK_BUILDBOT_SHOW_EXPERIMENTAL_CORES, false); SETTING_BOOL("core_updater_auto_backup", &settings->bools.core_updater_auto_backup, true, DEFAULT_CORE_UPDATER_AUTO_BACKUP, false); SETTING_BOOL("camera_allow", &settings->bools.camera_allow, true, false, false); + SETTING_BOOL("cloud_sync_enable", &settings->bools.cloud_sync_enable, true, false, false); + SETTING_BOOL("cloud_sync_destructive", &settings->bools.cloud_sync_destructive, true, false, false); SETTING_BOOL("discord_allow", &settings->bools.discord_enable, true, false, false); #if defined(VITA) SETTING_BOOL("input_backtouch_enable", &settings->bools.input_backtouch_enable, false, DEFAULT_INPUT_BACKTOUCH_ENABLE, false); diff --git a/configuration.h b/configuration.h index cc7f9def38..4145a8d14a 100644 --- a/configuration.h +++ b/configuration.h @@ -427,6 +427,7 @@ typedef struct settings char wifi_driver[32]; char led_driver[32]; char location_driver[32]; + char cloud_sync_driver[32]; char menu_driver[32]; char cheevos_username[32]; char cheevos_password[256]; @@ -460,6 +461,10 @@ typedef struct settings char translation_service_url[2048]; + char webdav_url[255]; + char webdav_username[255]; + char webdav_password[255]; + char youtube_stream_key[PATH_MAX_LENGTH]; char twitch_stream_key[PATH_MAX_LENGTH]; char facebook_stream_key[PATH_MAX_LENGTH]; @@ -899,6 +904,10 @@ typedef struct settings bool steam_rich_presence_enable; #endif + /* Cloud Sync */ + bool cloud_sync_enable; + bool cloud_sync_destructive; + /* Misc. */ bool discord_enable; bool threaded_data_runloop_enable; diff --git a/griffin/griffin.c b/griffin/griffin.c index 3c194a3e2a..7d5405090d 100644 --- a/griffin/griffin.c +++ b/griffin/griffin.c @@ -1621,3 +1621,12 @@ STEAM INTEGRATION USING MIST #ifdef HAVE_PRESENCE #include "../network/presence.c" #endif + +/*============================================================ +CLOUD SYNC +============================================================ */ +#ifdef HAVE_CLOUDSYNC +#include "../tasks/task_cloudsync.c" +#include "../network/cloud_sync_driver.c" +#include "../network/cloud_sync/webdav.c" +#endif diff --git a/intl/msg_hash_lbl.h b/intl/msg_hash_lbl.h index 9580da2b4a..3cc864e196 100644 --- a/intl/msg_hash_lbl.h +++ b/intl/msg_hash_lbl.h @@ -1409,6 +1409,10 @@ MSG_HASH( MENU_ENUM_LABEL_DEFERRED_SAVING_SETTINGS_LIST, "deferred_saving_settings_list" ) +MSG_HASH( + MENU_ENUM_LABEL_DEFERRED_CLOUD_SYNC_SETTINGS_LIST, + "deferred_cloud_sync_settings_list" + ) MSG_HASH( MENU_ENUM_LABEL_DEFERRED_THUMBNAILS_UPDATER_LIST, "deferred_thumbnails_updater_list" @@ -3483,6 +3487,34 @@ MSG_HASH( MENU_ENUM_LABEL_SAVING_SETTINGS, "saving_settings" ) +MSG_HASH( + MENU_ENUM_LABEL_CLOUD_SYNC_SETTINGS, + "cloud_sync_settings" + ) +MSG_HASH( + MENU_ENUM_LABEL_CLOUD_SYNC_ENABLE, + "cloud_sync_enable" + ) +MSG_HASH( + MENU_ENUM_LABEL_CLOUD_SYNC_DESTRUCTIVE, + "cloud_sync_destructive" + ) +MSG_HASH( + MENU_ENUM_LABEL_CLOUD_SYNC_DRIVER, + "cloud_sync_driver" + ) +MSG_HASH( + MENU_ENUM_LABEL_CLOUD_SYNC_URL, + "cloud_sync_url" + ) +MSG_HASH( + MENU_ENUM_LABEL_CLOUD_SYNC_USERNAME, + "cloud_sync_username" + ) +MSG_HASH( + MENU_ENUM_LABEL_CLOUD_SYNC_PASSWORD, + "cloud_sync_password" + ) MSG_HASH( MENU_ENUM_LABEL_SCAN_DIRECTORY, "scan_directory" diff --git a/intl/msg_hash_us.h b/intl/msg_hash_us.h index c2e0de6390..564920be37 100644 --- a/intl/msg_hash_us.h +++ b/intl/msg_hash_us.h @@ -1204,6 +1204,62 @@ MSG_HASH( MENU_ENUM_SUBLABEL_SAVING_SETTINGS, "Change saving settings." ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_CLOUD_SYNC_SETTINGS, + "Cloud Sync" + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_CLOUD_SYNC_SETTINGS, + "Change cloud sync settings." + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_CLOUD_SYNC_ENABLE, + "Enable Cloud Sync" + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_CLOUD_SYNC_ENABLE, + "Attempt to sync configs, sram, and states to a cloud storage provider." + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_CLOUD_SYNC_DESTRUCTIVE, + "Destructive Cloud Sync" + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_CLOUD_SYNC_DESTRUCTIVE, + "When disabled, files are moved to a backup folder before being overwritten or deleted." + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_CLOUD_SYNC_DRIVER, + "Cloud Sync Backend" + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_CLOUD_SYNC_DRIVER, + "Which cloud storage network protocol to use." + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_CLOUD_SYNC_URL, + "Cloud Storage URL" + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_CLOUD_SYNC_URL, + "The URL for the API entry point to the cloud storage service." + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_CLOUD_SYNC_USERNAME, + "Username" + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_CLOUD_SYNC_USERNAME, + "Your username for your cloud storage account." + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_CLOUD_SYNC_PASSWORD, + "Password" + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_CLOUD_SYNC_PASSWORD, + "Your password for your cloud storage account." + ) MSG_HASH( MENU_ENUM_LABEL_VALUE_LOGGING_SETTINGS, "Logging" diff --git a/libretro-common/include/net/net_http.h b/libretro-common/include/net/net_http.h index 85231452fe..c328d4265f 100644 --- a/libretro-common/include/net/net_http.h +++ b/libretro-common/include/net/net_http.h @@ -51,6 +51,9 @@ void net_http_connection_set_user_agent(struct http_connection_t *conn, const ch void net_http_connection_set_headers(struct http_connection_t *conn, const char *headers); +void net_http_connection_set_content(struct http_connection_t *conn, const char *content_type, + size_t content_length, const void *content); + const char *net_http_connection_url(struct http_connection_t *conn); const char* net_http_connection_method(struct http_connection_t* conn); @@ -93,6 +96,17 @@ int net_http_status(struct http_t *state); **/ bool net_http_error(struct http_t *state); +/** + * net_http_headers: + * + * Leaf function. + * + * @return the response headers. The returned buffer is owned by the + * caller of net_http_new; it is not freed by net_http_delete. + * If the status is not 20x and accept_error is false, it returns NULL. + **/ +struct string_list *net_http_headers(struct http_t *state); + /** * net_http_data: * diff --git a/libretro-common/net/net_http.c b/libretro-common/net/net_http.c index a57c79361d..7205ee543e 100644 --- a/libretro-common/net/net_http.c +++ b/libretro-common/net/net_http.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -63,6 +64,7 @@ struct http_socket_state_t struct http_t { char *data; + struct string_list *headers; struct http_socket_state_t sock_state; /* ptr alignment */ size_t pos; size_t len; @@ -81,10 +83,11 @@ struct http_connection_t char *scan; char *methodcopy; char *contenttypecopy; - char *postdatacopy; + void *postdatacopy; char *useragentcopy; char *headerscopy; struct http_socket_state_t sock_state; /* ptr alignment */ + size_t contentlength; int port; }; @@ -530,7 +533,10 @@ struct http_connection_t *net_http_connection_new(const char *url, conn->methodcopy = strdup(method); if (data) + { conn->postdatacopy = strdup(data); + conn->contentlength = strlen(data); + } if (!(conn->urlcopy = strdup(url))) goto error; @@ -703,6 +709,25 @@ void net_http_connection_set_headers( conn->headerscopy = headers ? strdup(headers) : NULL; } +void net_http_connection_set_content( + struct http_connection_t *conn, const char *content_type, + size_t content_length, const void *content) + +{ + if (conn->contenttypecopy) + free(conn->contenttypecopy); + if (conn->postdatacopy) + free(conn->postdatacopy); + + conn->contenttypecopy = content_type ? strdup(content_type) : NULL; + conn->contentlength = content_length; + if (content_length) + { + conn->postdatacopy = malloc(content_length); + memcpy(conn->postdatacopy, content, content_length); + } +} + const char *net_http_connection_url(struct http_connection_t *conn) { return conn->urlcopy; @@ -767,8 +792,7 @@ struct http_t *net_http_new(struct http_connection_t *conn) if (conn->headerscopy) net_http_send_str(&conn->sock_state, &error, conn->headerscopy, strlen(conn->headerscopy)); - /* This is not being set anywhere yet */ - else if (conn->contenttypecopy) + if (conn->contenttypecopy) { net_http_send_str(&conn->sock_state, &error, "Content-Type: ", STRLEN_CONST("Content-Type: ")); @@ -778,12 +802,12 @@ struct http_t *net_http_new(struct http_connection_t *conn) STRLEN_CONST("\r\n")); } - if (conn->methodcopy && (string_is_equal(conn->methodcopy, "POST"))) + if (conn->methodcopy && (string_is_equal(conn->methodcopy, "POST") || string_is_equal(conn->methodcopy, "PUT"))) { size_t post_len, len; char *len_str = NULL; - if (!conn->postdatacopy) + if (!conn->postdatacopy && !string_is_equal(conn->methodcopy, "PUT")) goto err; if (!conn->headerscopy) @@ -799,7 +823,7 @@ struct http_t *net_http_new(struct http_connection_t *conn) net_http_send_str(&conn->sock_state, &error, "Content-Length: ", STRLEN_CONST("Content-Length: ")); - post_len = strlen(conn->postdatacopy); + post_len = conn->contentlength; #ifdef _WIN32 len = snprintf(NULL, 0, "%" PRIuPTR, post_len); len_str = (char*)malloc(len + 1); @@ -836,9 +860,9 @@ struct http_t *net_http_new(struct http_connection_t *conn) net_http_send_str(&conn->sock_state, &error, "\r\n", STRLEN_CONST("\r\n")); - if (conn->methodcopy && (string_is_equal(conn->methodcopy, "POST"))) + if (conn->postdatacopy && conn->contentlength) net_http_send_str(&conn->sock_state, &error, conn->postdatacopy, - strlen(conn->postdatacopy)); + conn->contentlength); if (!error) { @@ -854,7 +878,12 @@ struct http_t *net_http_new(struct http_connection_t *conn) state->buflen = 512; if ((state->data = (char*)malloc(state->buflen))) - return state; + { + if ((state->headers = string_list_new()) && + string_list_initialize(state->headers)) + return state; + string_list_free(state->headers); + } free(state); } @@ -865,6 +894,8 @@ err: free(conn->methodcopy); if (conn->contenttypecopy) free(conn->contenttypecopy); + if (conn->postdatacopy) + free(conn->postdatacopy); conn->methodcopy = NULL; conn->contenttypecopy = NULL; conn->postdatacopy = NULL; @@ -981,12 +1012,24 @@ bool net_http_update(struct http_t *state, size_t* progress, size_t* total) if (string_is_equal_case_insensitive(state->data, "Transfer-Encoding: chunked")) state->bodytype = T_CHUNK; - /* TODO: save headers somewhere */ if (state->data[0]=='\0') { - state->part = P_BODY; - if (state->bodytype == T_CHUNK) - state->part = P_BODY_CHUNKLEN; + if (state->status == 100) + { + state->part = P_HEADER_TOP; + } + else + { + state->part = P_BODY; + if (state->bodytype == T_CHUNK) + state->part = P_BODY_CHUNKLEN; + } + } + else + { + union string_list_elem_attr attr; + attr.i = 0; + string_list_append(state->headers, state->data, attr); } } @@ -1007,7 +1050,7 @@ bool net_http_update(struct http_t *state, size_t* progress, size_t* total) { if (state->error) newlen = -1; - else + else if (state->len) { #ifdef HAVE_SSL if (state->sock_state.ssl && state->sock_state.ssl_ctx) @@ -1158,6 +1201,26 @@ int net_http_status(struct http_t *state) return state->status; } +/** + * net_http_headers: + * + * Leaf function. + * + * @return the response headers. The returned buffer is owned by the + * caller of net_http_new; it is not freed by net_http_delete(). + * If the status is not 20x and accept_error is false, it returns NULL. + **/ +struct string_list *net_http_headers(struct http_t *state) +{ + if (!state) + return NULL; + + if (state->error) + return NULL; + + return state->headers; +} + /** * net_http_data: * diff --git a/libretro-common/net/net_socket_ssl_mbed.c b/libretro-common/net/net_socket_ssl_mbed.c index 48bed209ad..a0a524f355 100644 --- a/libretro-common/net/net_socket_ssl_mbed.c +++ b/libretro-common/net/net_socket_ssl_mbed.c @@ -234,11 +234,24 @@ int ssl_socket_send_all_blocking(void *state_data, mbedtls_net_set_block(&state->net_ctx); - while ((ret = mbedtls_ssl_write(&state->ctx, data, size)) <= 0) + while (size) { - if ( ret != MBEDTLS_ERR_SSL_WANT_READ && - ret != MBEDTLS_ERR_SSL_WANT_WRITE) - return false; + ret = mbedtls_ssl_write(&state->ctx, data, size); + + if (!ret) + continue; + + if (ret < 0) + { + if ( ret != MBEDTLS_ERR_SSL_WANT_READ && + ret != MBEDTLS_ERR_SSL_WANT_WRITE) + return false; + } + else + { + data += ret; + size -= ret; + } } return true; diff --git a/list_special.h b/list_special.h index cbfe9571ed..3c7604111d 100644 --- a/list_special.h +++ b/list_special.h @@ -57,6 +57,7 @@ enum string_list_type STRING_LIST_INPUT_JOYPAD_DRIVERS, STRING_LIST_INPUT_HID_DRIVERS, STRING_LIST_RECORD_DRIVERS, + STRING_LIST_CLOUD_SYNC_DRIVERS, #ifdef HAVE_LAKKA STRING_LIST_TIMEZONES, #endif diff --git a/menu/cbs/menu_cbs_deferred_push.c b/menu/cbs/menu_cbs_deferred_push.c index 19123da733..ac8284c744 100644 --- a/menu/cbs/menu_cbs_deferred_push.c +++ b/menu/cbs/menu_cbs_deferred_push.c @@ -176,6 +176,7 @@ GENERIC_DEFERRED_PUSH(deferred_push_video_hdr_settings_list, DISPLAYLIST_ GENERIC_DEFERRED_PUSH(deferred_push_crt_switchres_settings_list, DISPLAYLIST_CRT_SWITCHRES_SETTINGS_LIST) GENERIC_DEFERRED_PUSH(deferred_push_configuration_settings_list, DISPLAYLIST_CONFIGURATION_SETTINGS_LIST) GENERIC_DEFERRED_PUSH(deferred_push_saving_settings_list, DISPLAYLIST_SAVING_SETTINGS_LIST) +GENERIC_DEFERRED_PUSH(deferred_push_cloud_sync_settings_list, DISPLAYLIST_CLOUD_SYNC_SETTINGS_LIST) GENERIC_DEFERRED_PUSH(deferred_push_mixer_stream_settings_list, DISPLAYLIST_MIXER_STREAM_SETTINGS_LIST) GENERIC_DEFERRED_PUSH(deferred_push_logging_settings_list, DISPLAYLIST_LOGGING_SETTINGS_LIST) GENERIC_DEFERRED_PUSH(deferred_push_frame_throttle_settings_list, DISPLAYLIST_FRAME_THROTTLE_SETTINGS_LIST) @@ -702,6 +703,7 @@ static int menu_cbs_init_bind_deferred_push_compare_label( {MENU_ENUM_LABEL_DEFERRED_CORE_INFORMATION_LIST, deferred_push_core_information_list}, {MENU_ENUM_LABEL_DEFERRED_CONFIGURATION_SETTINGS_LIST, deferred_push_configuration_settings_list}, {MENU_ENUM_LABEL_DEFERRED_SAVING_SETTINGS_LIST, deferred_push_saving_settings_list}, + {MENU_ENUM_LABEL_DEFERRED_CLOUD_SYNC_SETTINGS_LIST, deferred_push_cloud_sync_settings_list}, {MENU_ENUM_LABEL_DEFERRED_MIXER_STREAM_SETTINGS_LIST, deferred_push_mixer_stream_settings_list}, {MENU_ENUM_LABEL_DEFERRED_LOGGING_SETTINGS_LIST, deferred_push_logging_settings_list}, {MENU_ENUM_LABEL_DEFERRED_FRAME_THROTTLE_SETTINGS_LIST, deferred_push_frame_throttle_settings_list}, @@ -1262,8 +1264,11 @@ static int menu_cbs_init_bind_deferred_push_compare_label( case MENU_ENUM_LABEL_DEFERRED_SAVING_SETTINGS_LIST: BIND_ACTION_DEFERRED_PUSH(cbs, deferred_push_saving_settings_list); break; + case MENU_ENUM_LABEL_DEFERRED_CLOUD_SYNC_SETTINGS_LIST: + BIND_ACTION_DEFERRED_PUSH(cbs, deferred_push_cloud_sync_settings_list); + break; case MENU_ENUM_LABEL_DEFERRED_LOGGING_SETTINGS_LIST: - BIND_ACTION_DEFERRED_PUSH(cbs, deferred_push_saving_settings_list); + BIND_ACTION_DEFERRED_PUSH(cbs, deferred_push_logging_settings_list); break; case MENU_ENUM_LABEL_DEFERRED_FRAME_THROTTLE_SETTINGS_LIST: BIND_ACTION_DEFERRED_PUSH(cbs, deferred_push_frame_throttle_settings_list); diff --git a/menu/cbs/menu_cbs_ok.c b/menu/cbs/menu_cbs_ok.c index b9bcd484eb..afa838ba9b 100644 --- a/menu/cbs/menu_cbs_ok.c +++ b/menu/cbs/menu_cbs_ok.c @@ -366,6 +366,8 @@ static enum msg_hash_enums action_ok_dl_to_enum(unsigned lbl) return MENU_ENUM_LABEL_DEFERRED_CONFIGURATION_SETTINGS_LIST; case ACTION_OK_DL_SAVING_SETTINGS_LIST: return MENU_ENUM_LABEL_DEFERRED_SAVING_SETTINGS_LIST; + case ACTION_OK_DL_CLOUD_SYNC_SETTINGS_LIST: + return MENU_ENUM_LABEL_DEFERRED_CLOUD_SYNC_SETTINGS_LIST; case ACTION_OK_DL_LOGGING_SETTINGS_LIST: return MENU_ENUM_LABEL_DEFERRED_LOGGING_SETTINGS_LIST; case ACTION_OK_DL_FRAME_THROTTLE_SETTINGS_LIST: @@ -1672,6 +1674,7 @@ int generic_action_ok_displaylist_push( case ACTION_OK_DL_CRT_SWITCHRES_SETTINGS_LIST: case ACTION_OK_DL_CONFIGURATION_SETTINGS_LIST: case ACTION_OK_DL_SAVING_SETTINGS_LIST: + case ACTION_OK_DL_CLOUD_SYNC_SETTINGS_LIST: case ACTION_OK_DL_LOGGING_SETTINGS_LIST: case ACTION_OK_DL_FRAME_THROTTLE_SETTINGS_LIST: case ACTION_OK_DL_FRAME_TIME_COUNTER_SETTINGS_LIST: @@ -5924,6 +5927,7 @@ STATIC_DEFAULT_ACTION_OK_FUNC(action_ok_parent_directory_push, ACTION_OK_DL_PARE STATIC_DEFAULT_ACTION_OK_FUNC(action_ok_directory_push, ACTION_OK_DL_DIRECTORY_PUSH) STATIC_DEFAULT_ACTION_OK_FUNC(action_ok_configurations_list, ACTION_OK_DL_CONFIGURATIONS_LIST) STATIC_DEFAULT_ACTION_OK_FUNC(action_ok_saving_list, ACTION_OK_DL_SAVING_SETTINGS_LIST) +STATIC_DEFAULT_ACTION_OK_FUNC(action_ok_cloud_sync_list, ACTION_OK_DL_CLOUD_SYNC_SETTINGS_LIST) STATIC_DEFAULT_ACTION_OK_FUNC(action_ok_network_list, ACTION_OK_DL_NETWORK_SETTINGS_LIST) STATIC_DEFAULT_ACTION_OK_FUNC(action_ok_network_hosting_list, ACTION_OK_DL_NETWORK_HOSTING_SETTINGS_LIST) STATIC_DEFAULT_ACTION_OK_FUNC(action_ok_netplay_kick_list, ACTION_OK_DL_NETPLAY_KICK_LIST) @@ -8568,6 +8572,7 @@ static int menu_cbs_init_bind_ok_compare_label(menu_file_list_cbs_t *cbs, {MENU_ENUM_LABEL_SUBSYSTEM_LOAD, action_ok_subsystem_add_load}, {MENU_ENUM_LABEL_CONFIGURATIONS, action_ok_configurations_list}, {MENU_ENUM_LABEL_SAVING_SETTINGS, action_ok_saving_list}, + {MENU_ENUM_LABEL_CLOUD_SYNC_SETTINGS, action_ok_cloud_sync_list}, {MENU_ENUM_LABEL_LOGGING_SETTINGS, action_ok_logging_list}, {MENU_ENUM_LABEL_FRAME_THROTTLE_SETTINGS, action_ok_frame_throttle_list}, {MENU_ENUM_LABEL_FRAME_TIME_COUNTER_SETTINGS, action_ok_frame_time_counter_list}, diff --git a/menu/cbs/menu_cbs_sublabel.c b/menu/cbs/menu_cbs_sublabel.c index 4dec14c716..9ac77176fc 100644 --- a/menu/cbs/menu_cbs_sublabel.c +++ b/menu/cbs/menu_cbs_sublabel.c @@ -252,6 +252,13 @@ DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_crt_switchres_hires_menu, MENU DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_driver_settings_list, MENU_ENUM_SUBLABEL_DRIVER_SETTINGS) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_retro_achievements_settings_list, MENU_ENUM_SUBLABEL_RETRO_ACHIEVEMENTS_SETTINGS) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_saving_settings_list, MENU_ENUM_SUBLABEL_SAVING_SETTINGS) +DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_cloud_sync_settings_list, MENU_ENUM_SUBLABEL_CLOUD_SYNC_SETTINGS) +DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_cloud_sync_enable, MENU_ENUM_SUBLABEL_CLOUD_SYNC_ENABLE) +DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_cloud_sync_destructive, MENU_ENUM_SUBLABEL_CLOUD_SYNC_DESTRUCTIVE) +DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_cloud_sync_driver, MENU_ENUM_SUBLABEL_CLOUD_SYNC_DRIVER) +DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_cloud_sync_url, MENU_ENUM_SUBLABEL_CLOUD_SYNC_URL) +DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_cloud_sync_username, MENU_ENUM_SUBLABEL_CLOUD_SYNC_USERNAME) +DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_cloud_sync_password, MENU_ENUM_SUBLABEL_CLOUD_SYNC_PASSWORD) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_logging_settings_list, MENU_ENUM_SUBLABEL_LOGGING_SETTINGS) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_user_interface_settings_list, MENU_ENUM_SUBLABEL_USER_INTERFACE_SETTINGS) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_ai_service_settings_list, MENU_ENUM_SUBLABEL_AI_SERVICE_SETTINGS) @@ -4784,6 +4791,27 @@ int menu_cbs_init_bind_sublabel(menu_file_list_cbs_t *cbs, case MENU_ENUM_LABEL_SAVING_SETTINGS: BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_saving_settings_list); break; + case MENU_ENUM_LABEL_CLOUD_SYNC_SETTINGS: + BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_cloud_sync_settings_list); + break; + case MENU_ENUM_LABEL_CLOUD_SYNC_ENABLE: + BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_cloud_sync_enable); + break; + case MENU_ENUM_LABEL_CLOUD_SYNC_DESTRUCTIVE: + BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_cloud_sync_destructive); + break; + case MENU_ENUM_LABEL_CLOUD_SYNC_DRIVER: + BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_cloud_sync_driver); + break; + case MENU_ENUM_LABEL_CLOUD_SYNC_URL: + BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_cloud_sync_url); + break; + case MENU_ENUM_LABEL_CLOUD_SYNC_USERNAME: + BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_cloud_sync_username); + break; + case MENU_ENUM_LABEL_CLOUD_SYNC_PASSWORD: + BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_cloud_sync_password); + break; case MENU_ENUM_LABEL_LOGGING_SETTINGS: BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_logging_settings_list); break; diff --git a/menu/cbs/menu_cbs_title.c b/menu/cbs/menu_cbs_title.c index b7f6479681..d20a937a2c 100644 --- a/menu/cbs/menu_cbs_title.c +++ b/menu/cbs/menu_cbs_title.c @@ -629,6 +629,7 @@ DEFAULT_TITLE_MACRO(action_get_dump_disc_list, MENU_ENUM_LABEL_ DEFAULT_TITLE_MACRO(action_get_eject_disc, MENU_ENUM_LABEL_VALUE_EJECT_DISC) #endif DEFAULT_TITLE_MACRO(action_get_saving_settings_list, MENU_ENUM_LABEL_VALUE_SAVING_SETTINGS) +DEFAULT_TITLE_MACRO(action_get_cloud_sync_settings_list, MENU_ENUM_LABEL_VALUE_CLOUD_SYNC_SETTINGS) DEFAULT_TITLE_MACRO(action_get_logging_settings_list, MENU_ENUM_LABEL_VALUE_LOGGING_SETTINGS) DEFAULT_TITLE_MACRO(action_get_frame_throttle_settings_list, MENU_ENUM_LABEL_VALUE_FRAME_THROTTLE_SETTINGS) DEFAULT_TITLE_MACRO(action_get_frame_time_counter_settings_list, MENU_ENUM_LABEL_VALUE_FRAME_TIME_COUNTER_SETTINGS) @@ -989,6 +990,7 @@ static int menu_cbs_init_bind_title_compare_label(menu_file_list_cbs_t *cbs, {MENU_ENUM_LABEL_DEFERRED_LOAD_DISC_LIST, action_get_load_disc_list}, {MENU_ENUM_LABEL_DEFERRED_CONFIGURATION_SETTINGS_LIST, action_get_configuration_settings_list }, {MENU_ENUM_LABEL_DEFERRED_SAVING_SETTINGS_LIST, action_get_saving_settings_list}, + {MENU_ENUM_LABEL_DEFERRED_CLOUD_SYNC_SETTINGS_LIST, action_get_cloud_sync_settings_list}, {MENU_ENUM_LABEL_DEFERRED_LOGGING_SETTINGS_LIST, action_get_logging_settings_list}, {MENU_ENUM_LABEL_DEFERRED_FRAME_TIME_COUNTER_SETTINGS_LIST, action_get_frame_time_counter_settings_list }, {MENU_ENUM_LABEL_DEFERRED_FRAME_THROTTLE_SETTINGS_LIST, action_get_frame_throttle_settings_list}, @@ -1597,6 +1599,9 @@ static int menu_cbs_init_bind_title_compare_label(menu_file_list_cbs_t *cbs, case MENU_ENUM_LABEL_DEFERRED_SAVING_SETTINGS_LIST: BIND_ACTION_GET_TITLE(cbs, action_get_saving_settings_list); break; + case MENU_ENUM_LABEL_DEFERRED_CLOUD_SYNC_SETTINGS_LIST: + BIND_ACTION_GET_TITLE(cbs, action_get_cloud_sync_settings_list); + break; case MENU_ENUM_LABEL_DEFERRED_FRAME_THROTTLE_SETTINGS_LIST: BIND_ACTION_GET_TITLE(cbs, action_get_frame_throttle_settings_list); break; diff --git a/menu/drivers/materialui.c b/menu/drivers/materialui.c index edd4431329..969d21d8b9 100644 --- a/menu/drivers/materialui.c +++ b/menu/drivers/materialui.c @@ -10860,6 +10860,7 @@ static void materialui_list_insert( || string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_SIDELOAD_CORE_LIST)) || string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_CRT_SWITCHRES_SETTINGS)) || string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_SAVING_SETTINGS)) + || string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_CLOUD_SYNC_SETTINGS)) || string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_LOGGING_SETTINGS)) || string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_FRAME_THROTTLE_SETTINGS)) || string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_RECORDING_SETTINGS)) diff --git a/menu/drivers/ozone.c b/menu/drivers/ozone.c index 486d9e6e02..aaaa66e157 100644 --- a/menu/drivers/ozone.c +++ b/menu/drivers/ozone.c @@ -2125,6 +2125,7 @@ static uintptr_t ozone_entries_icon_get_texture( case MENU_ENUM_LABEL_FRAME_TIME_COUNTER_SETTINGS: case MENU_ENUM_LABEL_PLAYLIST_MANAGER_CLEAN_PLAYLIST: case MENU_ENUM_LABEL_PLAYLIST_MANAGER_REFRESH_PLAYLIST: + case MENU_ENUM_LABEL_CLOUD_SYNC_SETTINGS: return ozone->icons_textures[OZONE_ENTRIES_ICONS_TEXTURE_RELOAD]; case MENU_ENUM_LABEL_VRR_RUNLOOP_ENABLE: /* Only show icon in Throttle settings */ diff --git a/menu/drivers/xmb.c b/menu/drivers/xmb.c index 383199e507..49b55e05a6 100644 --- a/menu/drivers/xmb.c +++ b/menu/drivers/xmb.c @@ -2956,6 +2956,7 @@ static uintptr_t xmb_icon_get_id(xmb_handle_t *xmb, case MENU_ENUM_LABEL_FRAME_TIME_COUNTER_SETTINGS: case MENU_ENUM_LABEL_PLAYLIST_MANAGER_CLEAN_PLAYLIST: case MENU_ENUM_LABEL_PLAYLIST_MANAGER_REFRESH_PLAYLIST: + case MENU_ENUM_LABEL_CLOUD_SYNC_SETTINGS: return xmb->textures.list[XMB_TEXTURE_RELOAD]; case MENU_ENUM_LABEL_VRR_RUNLOOP_ENABLE: /* Only show icon in Throttle settings */ diff --git a/menu/menu_cbs.h b/menu/menu_cbs.h index 80e67bddc9..5cd18306a5 100644 --- a/menu/menu_cbs.h +++ b/menu/menu_cbs.h @@ -120,6 +120,7 @@ enum ACTION_OK_DL_LATENCY_SETTINGS_LIST, ACTION_OK_DL_CONFIGURATION_SETTINGS_LIST, ACTION_OK_DL_SAVING_SETTINGS_LIST, + ACTION_OK_DL_CLOUD_SYNC_SETTINGS_LIST, ACTION_OK_DL_LOGGING_SETTINGS_LIST, ACTION_OK_DL_FRAME_THROTTLE_SETTINGS_LIST, ACTION_OK_DL_FRAME_TIME_COUNTER_SETTINGS_LIST, diff --git a/menu/menu_displaylist.c b/menu/menu_displaylist.c index 2308df4226..60a5e30288 100644 --- a/menu/menu_displaylist.c +++ b/menu/menu_displaylist.c @@ -10142,6 +10142,9 @@ unsigned menu_displaylist_build_list( {MENU_ENUM_LABEL_SCREENSHOTS_IN_CONTENT_DIR_ENABLE, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_CONTENT_RUNTIME_LOG, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_CONTENT_RUNTIME_LOG_AGGREGATE, PARSE_ONLY_BOOL, true}, +#if HAVE_CLOUDSYNC + {MENU_ENUM_LABEL_CLOUD_SYNC_SETTINGS, PARSE_ACTION, true}, +#endif }; for (i = 0; i < ARRAY_SIZE(build_list); i++) @@ -10169,6 +10172,26 @@ unsigned menu_displaylist_build_list( } } break; + case DISPLAYLIST_CLOUD_SYNC_SETTINGS_LIST: + { + menu_displaylist_build_info_t build_list[] = { + {MENU_ENUM_LABEL_CLOUD_SYNC_ENABLE, PARSE_ONLY_BOOL }, + {MENU_ENUM_LABEL_CLOUD_SYNC_DESTRUCTIVE, PARSE_ONLY_BOOL }, + {MENU_ENUM_LABEL_CLOUD_SYNC_DRIVER, PARSE_ONLY_STRING_OPTIONS }, + {MENU_ENUM_LABEL_CLOUD_SYNC_URL, PARSE_ONLY_STRING }, + {MENU_ENUM_LABEL_CLOUD_SYNC_USERNAME, PARSE_ONLY_STRING }, + {MENU_ENUM_LABEL_CLOUD_SYNC_PASSWORD, PARSE_ONLY_STRING }, + }; + + for (i = 0; i < ARRAY_SIZE(build_list); i++) + { + if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, + build_list[i].enum_idx, build_list[i].parse_type, + false) == 0) + count++; + } + } + break; #ifdef HAVE_MIST case DISPLAYLIST_STEAM_SETTINGS_LIST: { @@ -13637,6 +13660,7 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, break; #endif case DISPLAYLIST_SAVING_SETTINGS_LIST: + case DISPLAYLIST_CLOUD_SYNC_SETTINGS_LIST: case DISPLAYLIST_DRIVER_SETTINGS_LIST: case DISPLAYLIST_LOGGING_SETTINGS_LIST: case DISPLAYLIST_FRAME_THROTTLE_SETTINGS_LIST: diff --git a/menu/menu_displaylist.h b/menu/menu_displaylist.h index 27881f9c25..3c67655cc8 100644 --- a/menu/menu_displaylist.h +++ b/menu/menu_displaylist.h @@ -181,6 +181,7 @@ enum menu_displaylist_ctl_state DISPLAYLIST_VIDEO_SETTINGS_LIST, DISPLAYLIST_CONFIGURATION_SETTINGS_LIST, DISPLAYLIST_SAVING_SETTINGS_LIST, + DISPLAYLIST_CLOUD_SYNC_SETTINGS_LIST, DISPLAYLIST_LOGGING_SETTINGS_LIST, DISPLAYLIST_FRAME_THROTTLE_SETTINGS_LIST, DISPLAYLIST_FRAME_TIME_COUNTER_SETTINGS_LIST, diff --git a/menu/menu_setting.c b/menu/menu_setting.c index 5eaa5dc1b0..b510de0fff 100644 --- a/menu/menu_setting.c +++ b/menu/menu_setting.c @@ -93,6 +93,7 @@ #endif #include "../midi_driver.h" #include "../location_driver.h" +#include "../network/cloud_sync_driver.h" #include "../record/record_driver.h" #include "../tasks/tasks_internal.h" #include "../config.def.h" @@ -275,6 +276,7 @@ enum settings_list_type SETTINGS_LIST_CONFIGURATION, SETTINGS_LIST_LOGGING, SETTINGS_LIST_SAVING, + SETTINGS_LIST_CLOUD_SYNC, SETTINGS_LIST_REWIND, SETTINGS_LIST_CHEAT_DETAILS, SETTINGS_LIST_CHEAT_SEARCH, @@ -2936,8 +2938,8 @@ static void setting_get_string_representation_max_users(rarch_setting_t *setting snprintf(s, len, "%d", *setting->value.target.unsigned_integer); } -#ifdef HAVE_CHEEVOS -static void setting_get_string_representation_cheevos_password( +#if defined(HAVE_CHEEVOS) || defined(HAVE_CLOUDSYNC) +static void setting_get_string_representation_password( rarch_setting_t *setting, char *s, size_t len) { @@ -11099,10 +11101,128 @@ static bool setting_append_list( general_read_handler, SD_FLAG_NONE); + CONFIG_ACTION( + list, list_info, + MENU_ENUM_LABEL_CLOUD_SYNC_SETTINGS, + MENU_ENUM_LABEL_VALUE_CLOUD_SYNC_SETTINGS, + &group_info, + &subgroup_info, + parent_group); + END_SUB_GROUP(list, list_info, parent_group); END_GROUP(list, list_info, parent_group); } + break; + case SETTINGS_LIST_CLOUD_SYNC: +#ifdef HAVE_CLOUDSYNC + START_GROUP(list, list_info, &group_info, + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CLOUD_SYNC_SETTINGS), + parent_group); + parent_group = msg_hash_to_str(MENU_ENUM_LABEL_CLOUD_SYNC_SETTINGS); + START_SUB_GROUP(list, list_info, "State", &group_info, &subgroup_info, parent_group); + + CONFIG_BOOL( + list, list_info, + &settings->bools.cloud_sync_enable, + MENU_ENUM_LABEL_CLOUD_SYNC_ENABLE, + MENU_ENUM_LABEL_VALUE_CLOUD_SYNC_ENABLE, + false, + MENU_ENUM_LABEL_VALUE_OFF, + MENU_ENUM_LABEL_VALUE_ON, + &group_info, + &subgroup_info, + parent_group, + general_write_handler, + general_read_handler, + SD_FLAG_NONE); + + CONFIG_BOOL( + list, list_info, + &settings->bools.cloud_sync_destructive, + MENU_ENUM_LABEL_CLOUD_SYNC_DESTRUCTIVE, + MENU_ENUM_LABEL_VALUE_CLOUD_SYNC_DESTRUCTIVE, + false, + MENU_ENUM_LABEL_VALUE_OFF, + MENU_ENUM_LABEL_VALUE_ON, + &group_info, + &subgroup_info, + parent_group, + general_write_handler, + general_read_handler, + SD_FLAG_NONE); + + CONFIG_STRING_OPTIONS( + list, list_info, + settings->arrays.cloud_sync_driver, + sizeof(settings->arrays.cloud_sync_driver), + MENU_ENUM_LABEL_CLOUD_SYNC_DRIVER, + MENU_ENUM_LABEL_VALUE_CLOUD_SYNC_DRIVER, + "null", + config_get_cloud_sync_driver_options(), + &group_info, + &subgroup_info, + parent_group, + general_read_handler, + general_write_handler); + SETTINGS_DATA_LIST_CURRENT_ADD_FLAGS(list, list_info, SD_FLAG_IS_DRIVER); + (*list)[list_info->index - 1].action_ok = setting_action_ok_uint; + (*list)[list_info->index - 1].action_left = setting_string_action_left_driver; + (*list)[list_info->index - 1].action_right = setting_string_action_right_driver; + + CONFIG_STRING( + list, list_info, + settings->arrays.webdav_url, + sizeof(settings->arrays.webdav_url), + MENU_ENUM_LABEL_CLOUD_SYNC_URL, + MENU_ENUM_LABEL_VALUE_CLOUD_SYNC_URL, + "", + &group_info, + &subgroup_info, + parent_group, + general_write_handler, + general_read_handler); + SETTINGS_DATA_LIST_CURRENT_ADD_FLAGS(list, list_info, SD_FLAG_ALLOW_INPUT); + (*list)[list_info->index - 1].ui_type = ST_UI_TYPE_STRING_LINE_EDIT; + (*list)[list_info->index - 1].action_start = setting_generic_action_start_default; + + CONFIG_STRING( + list, list_info, + settings->arrays.webdav_username, + sizeof(settings->arrays.webdav_username), + MENU_ENUM_LABEL_CLOUD_SYNC_USERNAME, + MENU_ENUM_LABEL_VALUE_CLOUD_SYNC_USERNAME, + "", + &group_info, + &subgroup_info, + parent_group, + general_write_handler, + general_read_handler); + SETTINGS_DATA_LIST_CURRENT_ADD_FLAGS(list, list_info, SD_FLAG_ALLOW_INPUT); + (*list)[list_info->index - 1].ui_type = ST_UI_TYPE_STRING_LINE_EDIT; + (*list)[list_info->index - 1].action_start = setting_generic_action_start_default; + + CONFIG_STRING( + list, list_info, + settings->arrays.webdav_password, + sizeof(settings->arrays.webdav_password), + MENU_ENUM_LABEL_CLOUD_SYNC_PASSWORD, + MENU_ENUM_LABEL_VALUE_CLOUD_SYNC_PASSWORD, + "", + &group_info, + &subgroup_info, + parent_group, + general_write_handler, + general_read_handler); + (*list)[list_info->index - 1].get_string_representation = + &setting_get_string_representation_password; + SETTINGS_DATA_LIST_CURRENT_ADD_FLAGS(list, list_info, SD_FLAG_ALLOW_INPUT); + (*list)[list_info->index - 1].ui_type = ST_UI_TYPE_PASSWORD_LINE_EDIT; + (*list)[list_info->index - 1].action_start = setting_generic_action_start_default; + + END_SUB_GROUP(list, list_info, parent_group); + END_GROUP(list, list_info, parent_group); +#endif break; case SETTINGS_LIST_FRAME_TIME_COUNTER: START_GROUP(list, list_info, &group_info, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_FRAME_TIME_COUNTER_SETTINGS), parent_group); @@ -21994,7 +22114,7 @@ static bool setting_append_list( general_write_handler, general_read_handler); (*list)[list_info->index - 1].get_string_representation = - &setting_get_string_representation_cheevos_password; + &setting_get_string_representation_password; SETTINGS_DATA_LIST_CURRENT_ADD_FLAGS(list, list_info, SD_FLAG_ALLOW_INPUT); (*list)[list_info->index - 1].ui_type = ST_UI_TYPE_PASSWORD_LINE_EDIT; (*list)[list_info->index - 1].action_start = setting_generic_action_start_default; @@ -22917,6 +23037,7 @@ static rarch_setting_t *menu_setting_new_internal(rarch_setting_info_t *list_inf SETTINGS_LIST_CONFIGURATION, SETTINGS_LIST_LOGGING, SETTINGS_LIST_SAVING, + SETTINGS_LIST_CLOUD_SYNC, SETTINGS_LIST_REWIND, SETTINGS_LIST_CHEAT_DETAILS, SETTINGS_LIST_CHEAT_SEARCH, diff --git a/msg_hash.h b/msg_hash.h index a9e57ab3d0..72b7a4c1d2 100644 --- a/msg_hash.h +++ b/msg_hash.h @@ -1920,6 +1920,7 @@ enum msg_hash_enums MENU_ENUM_LABEL_DEFERRED_CRT_SWITCHRES_SETTINGS_LIST, MENU_ENUM_LABEL_DEFERRED_CONFIGURATION_SETTINGS_LIST, MENU_ENUM_LABEL_DEFERRED_SAVING_SETTINGS_LIST, + MENU_ENUM_LABEL_DEFERRED_CLOUD_SYNC_SETTINGS_LIST, MENU_ENUM_LABEL_DEFERRED_FRAME_THROTTLE_SETTINGS_LIST, MENU_ENUM_LABEL_DEFERRED_REWIND_SETTINGS_LIST, MENU_ENUM_LABEL_DEFERRED_FRAME_TIME_COUNTER_SETTINGS_LIST, @@ -3062,6 +3063,13 @@ enum msg_hash_enums MENU_LABEL(CONFIGURATION_SETTINGS), MENU_LABEL(LOGGING_SETTINGS), MENU_LABEL(SAVING_SETTINGS), + MENU_LABEL(CLOUD_SYNC_SETTINGS), + MENU_LABEL(CLOUD_SYNC_ENABLE), + MENU_LABEL(CLOUD_SYNC_DESTRUCTIVE), + MENU_LABEL(CLOUD_SYNC_DRIVER), + MENU_LABEL(CLOUD_SYNC_URL), + MENU_LABEL(CLOUD_SYNC_USERNAME), + MENU_LABEL(CLOUD_SYNC_PASSWORD), MENU_LABEL(RECORDING_SETTINGS), MENU_LABEL(OVERLAY_SETTINGS), MENU_LABEL(REWIND_SETTINGS), diff --git a/network/cloud_sync/webdav.c b/network/cloud_sync/webdav.c new file mode 100644 index 0000000000..f1495935f8 --- /dev/null +++ b/network/cloud_sync/webdav.c @@ -0,0 +1,803 @@ +/* RetroArch - A frontend for libretro. + * + * RetroArch is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with RetroArch. + * If not, see . + */ + +#include +#include +#include +#include +#include