diff --git a/cheevos-new/cheevos.c b/cheevos-new/cheevos.c index 68dc0d6e26..829221c758 100644 --- a/cheevos-new/cheevos.c +++ b/cheevos-new/cheevos.c @@ -61,7 +61,9 @@ #include "../msg_hash.h" #include "../retroarch.h" #include "../core.h" +#include "../version.h" +#include "../frontend/frontend_driver.h" #include "../network/net_http_special.h" #include "../tasks/tasks_internal.h" @@ -169,6 +171,7 @@ bool rcheevos_hardcore_paused = false; bool rcheevos_state_loaded_flag = false; int rcheevos_cheats_are_enabled = 0; int rcheevos_cheats_were_enabled = 0; +char rcheevos_user_agent_prefix[128] = ""; #ifdef HAVE_THREADS #define CHEEVOS_LOCK(l) do { slock_lock(l); } while (0) @@ -193,6 +196,80 @@ void rcheevos_log(const char *fmt, ...) #endif +static void rcheevos_get_user_agent(char* buffer) +{ + struct retro_system_info *system = runloop_get_libretro_system_info(); + const char* scan; + char* ptr; + + if (!rcheevos_user_agent_prefix[0]) + { + const frontend_ctx_driver_t *frontend = frontend_get_ptr(); + int major, minor; + char tmp[64]; + + ptr = rcheevos_user_agent_prefix + sprintf(rcheevos_user_agent_prefix, "RetroArch/" PACKAGE_VERSION); + + if (frontend && frontend->get_os) + { + frontend->get_os(tmp, sizeof(tmp), &major, &minor); + ptr += sprintf(ptr, " (%s %d.%d)", tmp, major, minor); + } + } + + ptr = buffer + sprintf(buffer, "%s", rcheevos_user_agent_prefix); + + if (system && !string_is_empty(system->library_name)) + { + const char* path = path_get(RARCH_PATH_CORE); + if (!string_is_empty(path)) + { + sprintf(ptr, " %s", path_basename(path)); + path_remove_extension(ptr); + ptr += strlen(ptr); + } + else + { + *ptr++ = ' '; + + scan = system->library_name; + while (*scan) + { + if (*scan == ' ') + { + *ptr++ = '_'; + ++scan; + } + else + { + *ptr++ = *scan++; + } + } + } + + if (system->library_version) + { + *ptr++ = '/'; + + scan = system->library_version; + while (*scan) + { + if (*scan == ' ') + { + *ptr++ = '_'; + ++scan; + } + else + { + *ptr++ = *scan++; + } + } + } + } + + *ptr = '\0'; +} + static void rcheevos_log_url(const char* format, const char* url) { #ifdef CHEEVOS_LOG_URLS @@ -431,7 +508,7 @@ static void rcheevos_award_task_softcore(retro_task_t *task, void* task_data, vo { settings_t *settings = config_get_ptr(); const rcheevos_cheevo_t* cheevo = (const rcheevos_cheevo_t*)user_data; - char buffer[256]; + char buffer[256], user_agent[256]; int ret; buffer[0] = 0; @@ -453,8 +530,10 @@ static void rcheevos_award_task_softcore(retro_task_t *task, void* task_data, vo return; } + rcheevos_get_user_agent(user_agent); + rcheevos_log_url(RCHEEVOS_TAG "rc_url_award_cheevo: %s\n", buffer); - task_push_http_transfer(buffer, true, NULL, rcheevos_award_task_softcore, user_data); + task_push_http_transfer_with_user_agent(buffer, true, NULL, user_agent, rcheevos_award_task_softcore, user_data); } static void rcheevos_award_task_hardcore(retro_task_t *task, void* task_data, void* user_data, @@ -462,7 +541,7 @@ static void rcheevos_award_task_hardcore(retro_task_t *task, void* task_data, vo { settings_t *settings = config_get_ptr(); const rcheevos_cheevo_t* cheevo = (const rcheevos_cheevo_t*)user_data; - char buffer[256]; + char buffer[256], user_agent[256]; int ret; buffer[0] = 0; @@ -484,8 +563,10 @@ static void rcheevos_award_task_hardcore(retro_task_t *task, void* task_data, vo return; } + rcheevos_get_user_agent(user_agent); + rcheevos_log_url(RCHEEVOS_TAG "rc_url_award_cheevo: %s\n", buffer); - task_push_http_transfer(buffer, true, NULL, rcheevos_award_task_hardcore, user_data); + task_push_http_transfer_with_user_agent(buffer, true, NULL, user_agent, rcheevos_award_task_hardcore, user_data); } static void rcheevos_award(rcheevos_cheevo_t* cheevo, int mode) @@ -613,6 +694,7 @@ static void rcheevos_lboard_submit_task(retro_task_t *task, void* task_data, voi uint8_t hash[16]; char signature[64]; char buffer[256]; + char user_agent[256]; int ret; if (!error) @@ -643,8 +725,10 @@ static void rcheevos_lboard_submit_task(retro_task_t *task, void* task_data, voi return; } + rcheevos_get_user_agent(user_agent); + rcheevos_log_url(RCHEEVOS_TAG "rc_url_submit_lboard: %s\n", buffer); - task_push_http_transfer(buffer, true, NULL, rcheevos_lboard_submit_task, user_data); + task_push_http_transfer_with_user_agent(buffer, true, NULL, user_agent, rcheevos_lboard_submit_task, user_data); } static void rcheevos_lboard_submit(rcheevos_lboard_t* lboard) @@ -2185,6 +2269,8 @@ found: *************************************************************************/ CORO_SUB(RCHEEVOS_HTTP_GET) + rcheevos_get_user_agent(buffer); + for (coro->k = 0; coro->k < 5; coro->k++) { if (coro->k != 0) @@ -2210,6 +2296,8 @@ found: continue; } + net_http_connection_set_user_agent(coro->conn, buffer); + coro->http = net_http_new(coro->conn); /* Error connecting to the endpoint. */ diff --git a/libretro-common/include/net/net_http.h b/libretro-common/include/net/net_http.h index f98462764d..b19abec106 100644 --- a/libretro-common/include/net/net_http.h +++ b/libretro-common/include/net/net_http.h @@ -42,6 +42,8 @@ bool net_http_connection_done(struct http_connection_t *conn); void net_http_connection_free(struct http_connection_t *conn); +void net_http_connection_set_user_agent(struct http_connection_t* conn, const char* user_agent); + const char *net_http_connection_url(struct http_connection_t *conn); struct http_t *net_http_new(struct http_connection_t *conn); diff --git a/libretro-common/net/net_http.c b/libretro-common/net/net_http.c index 939113a112..1ccd617a25 100644 --- a/libretro-common/net/net_http.c +++ b/libretro-common/net/net_http.c @@ -84,6 +84,7 @@ struct http_connection_t char *methodcopy; char *contenttypecopy; char *postdatacopy; + char* useragentcopy; int port; struct http_socket_state_t sock_state; }; @@ -424,14 +425,26 @@ void net_http_connection_free(struct http_connection_t *conn) if (conn->postdatacopy) free(conn->postdatacopy); + if (conn->useragentcopy) + free(conn->useragentcopy); + conn->urlcopy = NULL; conn->methodcopy = NULL; conn->contenttypecopy = NULL; conn->postdatacopy = NULL; + conn->useragentcopy = NULL; free(conn); } +void net_http_connection_set_user_agent(struct http_connection_t* conn, const char* user_agent) +{ + if (conn->useragentcopy) + free(conn->useragentcopy); + + conn->useragentcopy = user_agent ? strdup(user_agent) : NULL; +} + const char *net_http_connection_url(struct http_connection_t *conn) { return conn->urlcopy; @@ -523,7 +536,13 @@ struct http_t *net_http_new(struct http_connection_t *conn) free(len_str); } - net_http_send_str(&conn->sock_state, &error, "User-Agent: libretro\r\n"); + net_http_send_str(&conn->sock_state, &error, "User-Agent: "); + if (conn->useragentcopy) + net_http_send_str(&conn->sock_state, &error, conn->useragentcopy); + else + net_http_send_str(&conn->sock_state, &error, "libretro"); + net_http_send_str(&conn->sock_state, &error, "\r\n"); + net_http_send_str(&conn->sock_state, &error, "Connection: close\r\n"); net_http_send_str(&conn->sock_state, &error, "\r\n"); diff --git a/tasks/task_http.c b/tasks/task_http.c index f2f98cbb84..2379ab9513 100644 --- a/tasks/task_http.c +++ b/tasks/task_http.c @@ -262,7 +262,12 @@ static void* task_push_http_transfer_generic( /* Concurrent download of the same file is not allowed */ if (task_queue_find(&find_data)) + { + if (conn) + net_http_connection_free(conn); + return NULL; + } if (!conn) return NULL; @@ -334,6 +339,26 @@ void* task_push_http_transfer(const char *url, bool mute, url, mute, type, cb, user_data); } +void* task_push_http_transfer_with_user_agent(const char *url, bool mute, + const char *type, const char* user_agent, + retro_task_callback_t cb, void *user_data) +{ + struct http_connection_t* conn; + + if (string_is_empty(url)) + return NULL; + + conn = net_http_connection_new(url, "GET", NULL); + if (!conn) + return NULL; + + if (user_agent != NULL) + net_http_connection_set_user_agent(conn, user_agent); + + /* assert: task_push_http_transfer_generic will free conn on failure */ + return task_push_http_transfer_generic(conn, url, mute, type, cb, user_data); +} + void* task_push_http_post_transfer(const char *url, const char *post_data, bool mute, const char *type, retro_task_callback_t cb, void *user_data) diff --git a/tasks/tasks_internal.h b/tasks/tasks_internal.h index 33615418ac..7669ee96d9 100644 --- a/tasks/tasks_internal.h +++ b/tasks/tasks_internal.h @@ -52,6 +52,9 @@ typedef struct void *task_push_http_transfer(const char *url, bool mute, const char *type, retro_task_callback_t cb, void *userdata); +void *task_push_http_transfer_with_user_agent(const char *url, bool mute, const char *type, + const char* user_agent, retro_task_callback_t cb, void *userdata); + void *task_push_http_post_transfer(const char *url, const char *post_data, bool mute, const char *type, retro_task_callback_t cb, void *userdata);