mirror of
https://github.com/WinampDesktop/winamp.git
synced 2025-04-27 02:45:41 -04:00
374 lines
9.8 KiB
C
374 lines
9.8 KiB
C
#include "rc_url.h"
|
|
|
|
#include "../rcheevos/rc_compat.h"
|
|
#include "../rhash/md5.h"
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
static int rc_url_encode(char* encoded, size_t len, const char* str) {
|
|
for (;;) {
|
|
switch (*str) {
|
|
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': case 'j':
|
|
case 'k': case 'l': case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': case 's': case 't':
|
|
case 'u': case 'v': case 'w': case 'x': case 'y': case 'z':
|
|
case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': case 'J':
|
|
case 'K': case 'L': case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T':
|
|
case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z':
|
|
case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
|
|
case '-': case '_': case '.': case '~':
|
|
if (len < 2)
|
|
return -1;
|
|
|
|
*encoded++ = *str++;
|
|
--len;
|
|
break;
|
|
|
|
case ' ':
|
|
if (len < 2)
|
|
return -1;
|
|
|
|
*encoded++ = '+';
|
|
++str;
|
|
--len;
|
|
break;
|
|
|
|
default:
|
|
if (len < 4)
|
|
return -1;
|
|
|
|
snprintf(encoded, len, "%%%02x", (unsigned char)*str);
|
|
encoded += 3;
|
|
++str;
|
|
len -= 3;
|
|
break;
|
|
|
|
case '\0':
|
|
*encoded = 0;
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
int rc_url_award_cheevo(char* buffer, size_t size, const char* user_name, const char* login_token,
|
|
unsigned cheevo_id, int hardcore, const char* game_hash) {
|
|
char urle_user_name[64];
|
|
char urle_login_token[64];
|
|
int written;
|
|
|
|
if (rc_url_encode(urle_user_name, sizeof(urle_user_name), user_name) != 0) {
|
|
return -1;
|
|
}
|
|
|
|
if (rc_url_encode(urle_login_token, sizeof(urle_login_token), login_token) != 0) {
|
|
return -1;
|
|
}
|
|
|
|
written = snprintf(
|
|
buffer,
|
|
size,
|
|
"https://retroachievements.org/dorequest.php?r=awardachievement&u=%s&t=%s&a=%u&h=%d",
|
|
urle_user_name,
|
|
urle_login_token,
|
|
cheevo_id,
|
|
hardcore ? 1 : 0
|
|
);
|
|
|
|
if (game_hash && strlen(game_hash) == 32 && (size - (size_t)written) >= 35) {
|
|
written += snprintf(buffer + written, size - (size_t)written, "&m=%s", game_hash);
|
|
}
|
|
|
|
return (size_t)written >= size ? -1 : 0;
|
|
}
|
|
|
|
int rc_url_submit_lboard(char* buffer, size_t size, const char* user_name, const char* login_token, unsigned lboard_id, int value) {
|
|
char urle_user_name[64];
|
|
char urle_login_token[64];
|
|
char signature[64];
|
|
unsigned char hash[16];
|
|
md5_state_t state;
|
|
int written;
|
|
|
|
if (rc_url_encode(urle_user_name, sizeof(urle_user_name), user_name) != 0) {
|
|
return -1;
|
|
}
|
|
|
|
if (rc_url_encode(urle_login_token, sizeof(urle_login_token), login_token) != 0) {
|
|
return -1;
|
|
}
|
|
|
|
/* Evaluate the signature. */
|
|
snprintf(signature, sizeof(signature), "%u%s%u", lboard_id, user_name, lboard_id);
|
|
md5_init(&state);
|
|
md5_append(&state, (unsigned char*)signature, (int)strlen(signature));
|
|
md5_finish(&state, hash);
|
|
|
|
written = snprintf(
|
|
buffer,
|
|
size,
|
|
"https://retroachievements.org/dorequest.php?r=submitlbentry&u=%s&t=%s&i=%u&s=%d&v=%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
|
|
urle_user_name,
|
|
urle_login_token,
|
|
lboard_id,
|
|
value,
|
|
hash[ 0], hash[ 1], hash[ 2], hash[ 3], hash[ 4], hash[ 5], hash[ 6], hash[ 7],
|
|
hash[ 8], hash[ 9], hash[10], hash[11],hash[12], hash[13], hash[14], hash[15]
|
|
);
|
|
|
|
return (size_t)written >= size ? -1 : 0;
|
|
}
|
|
|
|
int rc_url_get_gameid(char* buffer, size_t size, const char* hash) {
|
|
int written = snprintf(
|
|
buffer,
|
|
size,
|
|
"https://retroachievements.org/dorequest.php?r=gameid&m=%s",
|
|
hash
|
|
);
|
|
|
|
return (size_t)written >= size ? -1 : 0;
|
|
}
|
|
|
|
int rc_url_get_patch(char* buffer, size_t size, const char* user_name, const char* login_token, unsigned gameid) {
|
|
char urle_user_name[64];
|
|
char urle_login_token[64];
|
|
int written;
|
|
|
|
if (rc_url_encode(urle_user_name, sizeof(urle_user_name), user_name) != 0) {
|
|
return -1;
|
|
}
|
|
|
|
if (rc_url_encode(urle_login_token, sizeof(urle_login_token), login_token) != 0) {
|
|
return -1;
|
|
}
|
|
|
|
written = snprintf(
|
|
buffer,
|
|
size,
|
|
"https://retroachievements.org/dorequest.php?r=patch&u=%s&t=%s&g=%u",
|
|
urle_user_name,
|
|
urle_login_token,
|
|
gameid
|
|
);
|
|
|
|
return (size_t)written >= size ? -1 : 0;
|
|
}
|
|
|
|
int rc_url_get_badge_image(char* buffer, size_t size, const char* badge_name) {
|
|
int written = snprintf(
|
|
buffer,
|
|
size,
|
|
"http://i.retroachievements.org/Badge/%s",
|
|
badge_name
|
|
);
|
|
|
|
return (size_t)written >= size ? -1 : 0;
|
|
}
|
|
|
|
int rc_url_login_with_password(char* buffer, size_t size, const char* user_name, const char* password) {
|
|
char urle_user_name[256];
|
|
char urle_password[256];
|
|
int written;
|
|
|
|
if (rc_url_encode(urle_user_name, sizeof(urle_user_name), user_name) != 0) {
|
|
return -1;
|
|
}
|
|
|
|
if (rc_url_encode(urle_password, sizeof(urle_password), password) != 0) {
|
|
return -1;
|
|
}
|
|
|
|
written = snprintf(
|
|
buffer,
|
|
size,
|
|
"https://retroachievements.org/dorequest.php?r=login&u=%s&p=%s",
|
|
urle_user_name,
|
|
urle_password
|
|
);
|
|
|
|
return (size_t)written >= size ? -1 : 0;
|
|
}
|
|
|
|
int rc_url_login_with_token(char* buffer, size_t size, const char* user_name, const char* login_token) {
|
|
char urle_user_name[64];
|
|
char urle_login_token[64];
|
|
int written;
|
|
|
|
if (rc_url_encode(urle_user_name, sizeof(urle_user_name), user_name) != 0) {
|
|
return -1;
|
|
}
|
|
|
|
if (rc_url_encode(urle_login_token, sizeof(urle_login_token), login_token) != 0) {
|
|
return -1;
|
|
}
|
|
|
|
written = snprintf(
|
|
buffer,
|
|
size,
|
|
"https://retroachievements.org/dorequest.php?r=login&u=%s&t=%s",
|
|
urle_user_name,
|
|
urle_login_token
|
|
);
|
|
|
|
return (size_t)written >= size ? -1 : 0;
|
|
}
|
|
|
|
int rc_url_get_unlock_list(char* buffer, size_t size, const char* user_name, const char* login_token, unsigned gameid, int hardcore) {
|
|
char urle_user_name[64];
|
|
char urle_login_token[64];
|
|
int written;
|
|
|
|
if (rc_url_encode(urle_user_name, sizeof(urle_user_name), user_name) != 0) {
|
|
return -1;
|
|
}
|
|
|
|
if (rc_url_encode(urle_login_token, sizeof(urle_login_token), login_token) != 0) {
|
|
return -1;
|
|
}
|
|
|
|
written = snprintf(
|
|
buffer,
|
|
size,
|
|
"https://retroachievements.org/dorequest.php?r=unlocks&u=%s&t=%s&g=%u&h=%d",
|
|
urle_user_name,
|
|
urle_login_token,
|
|
gameid,
|
|
hardcore ? 1 : 0
|
|
);
|
|
|
|
return (size_t)written >= size ? -1 : 0;
|
|
}
|
|
|
|
int rc_url_post_playing(char* buffer, size_t size, const char* user_name, const char* login_token, unsigned gameid) {
|
|
char urle_user_name[64];
|
|
char urle_login_token[64];
|
|
int written;
|
|
|
|
if (rc_url_encode(urle_user_name, sizeof(urle_user_name), user_name) != 0) {
|
|
return -1;
|
|
}
|
|
|
|
if (rc_url_encode(urle_login_token, sizeof(urle_login_token), login_token) != 0) {
|
|
return -1;
|
|
}
|
|
|
|
written = snprintf(
|
|
buffer,
|
|
size,
|
|
"https://retroachievements.org/dorequest.php?r=postactivity&u=%s&t=%s&a=3&m=%u",
|
|
urle_user_name,
|
|
urle_login_token,
|
|
gameid
|
|
);
|
|
|
|
return (size_t)written >= size ? -1 : 0;
|
|
}
|
|
|
|
static int rc_url_append_param_equals(char* buffer, size_t buffer_size, size_t buffer_offset, const char* param)
|
|
{
|
|
int written = 0;
|
|
size_t param_len;
|
|
|
|
if (buffer_offset >= buffer_size)
|
|
return -1;
|
|
|
|
if (buffer_offset) {
|
|
buffer += buffer_offset;
|
|
buffer_size -= buffer_offset;
|
|
|
|
if (buffer[-1] != '?') {
|
|
*buffer++ = '&';
|
|
buffer_size--;
|
|
written = 1;
|
|
}
|
|
}
|
|
|
|
param_len = strlen(param);
|
|
if (param_len + 1 >= buffer_size)
|
|
return -1;
|
|
memcpy(buffer, param, param_len);
|
|
buffer[param_len] = '=';
|
|
|
|
written += (int)param_len + 1;
|
|
return written + (int)buffer_offset;
|
|
}
|
|
|
|
static int rc_url_append_unum(char* buffer, size_t buffer_size, size_t* buffer_offset, const char* param, unsigned value)
|
|
{
|
|
int written = rc_url_append_param_equals(buffer, buffer_size, *buffer_offset, param);
|
|
if (written > 0) {
|
|
char num[16];
|
|
int chars = sprintf(num, "%u", value);
|
|
|
|
if (chars + written < (int)buffer_size)
|
|
{
|
|
memcpy(&buffer[written], num, chars + 1);
|
|
*buffer_offset = written + chars;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
static int rc_url_append_str(char* buffer, size_t buffer_size, size_t* buffer_offset, const char* param, const char* value)
|
|
{
|
|
int written = rc_url_append_param_equals(buffer, buffer_size, *buffer_offset, param);
|
|
if (written > 0)
|
|
{
|
|
buffer += written;
|
|
buffer_size -= written;
|
|
|
|
if (rc_url_encode(buffer, buffer_size, value) == 0)
|
|
{
|
|
written += (int)strlen(buffer);
|
|
*buffer_offset = written;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
static int rc_url_build_dorequest(char* url_buffer, size_t url_buffer_size, size_t* buffer_offset,
|
|
const char* api, const char* user_name)
|
|
{
|
|
const char* base_url = "https://retroachievements.org/dorequest.php";
|
|
size_t written = strlen(base_url);
|
|
int failure = 0;
|
|
|
|
if (url_buffer_size < written + 1)
|
|
return -1;
|
|
memcpy(url_buffer, base_url, written);
|
|
url_buffer[written++] = '?';
|
|
|
|
failure |= rc_url_append_str(url_buffer, url_buffer_size, &written, "r", api);
|
|
failure |= rc_url_append_str(url_buffer, url_buffer_size, &written, "u", user_name);
|
|
|
|
*buffer_offset += written;
|
|
return failure;
|
|
}
|
|
|
|
int rc_url_ping(char* url_buffer, size_t url_buffer_size, char* post_buffer, size_t post_buffer_size,
|
|
const char* user_name, const char* login_token, unsigned gameid, const char* rich_presence)
|
|
{
|
|
size_t written = 0;
|
|
int failure = rc_url_build_dorequest(url_buffer, url_buffer_size, &written, "ping", user_name);
|
|
failure |= rc_url_append_unum(url_buffer, url_buffer_size, &written, "g", gameid);
|
|
|
|
written = 0;
|
|
failure |= rc_url_append_str(post_buffer, post_buffer_size, &written, "t", login_token);
|
|
|
|
if (rich_presence && *rich_presence)
|
|
failure |= rc_url_append_str(post_buffer, post_buffer_size, &written, "m", rich_presence);
|
|
|
|
if (failure) {
|
|
if (url_buffer_size)
|
|
url_buffer[0] = '\0';
|
|
if (post_buffer_size)
|
|
post_buffer[0] = '\0';
|
|
}
|
|
|
|
return failure;
|
|
}
|