This commit is contained in:
irungentoo 2014-09-29 13:49:59 -04:00
commit 627e4d3aa6
No known key found for this signature in database
GPG Key ID: 10349DC9BED89E98
2 changed files with 68 additions and 83 deletions

View File

@ -241,18 +241,22 @@ already downloaded by other clients can be reused.
Given the Tox data directory described in STS Draft v0.1.0: Given the Tox data directory described in STS Draft v0.1.0:
- The user avatar is stored in a file named "avatar.png". As more formats - Avatars are stored in a directory called "avatars" and named
may be used in the future, another extensions are reserved and clients as "xxxxx.png", where "xxxxx" is the complete client id (but not friend
should keep just one file named "avatar.*", with the data of the last address!) encoded as an uppercase hexadecimal string and "png" is the
avatar set by the user. If the user have no avatar, no such files should extension for the PNG avatar. As new image formats may be used in the
be kept in the data directory; future, clients should ensure no other file "xxxxx.*" exists. No file
should be kept for an user who have no avatar.
- Friends avatars are stored in a directory called "avatars" and named - The client's own avatar is not special and is stored like any other. This
as "xxxxx.png", where "xxxxx" is the complete client id encoded as an is partially for simplicity, and partially in anticipation of profiles.
uppercase hexadecimal string and "png" is the extension for the PNG
avatar. As new image formats may be used in the future, clients should - The avatar should be stored as its recieved, before any modifications by
ensure no other file "xxxxx.*" exists. No file should be kept for an user the client for display purposes.
who have no avatar.
- The hash, as calculated by toxcore and passed in to the data callback,
should be saved in "avatars/xxxxx.hash" where "xxxxx" means the
same thing as for avatars. (The filename is longer than the file :) )
**To be discussed:** User keys are usually presented in Tox clients as **To be discussed:** User keys are usually presented in Tox clients as
upper case strings, but lower case file names are more usual. upper case strings, but lower case file names are more usual.
@ -262,13 +266,14 @@ Example for Linux and other Unix systems, assuming an user called "gildor":
Tox data directory: /home/gildor/.config/tox/ Tox data directory: /home/gildor/.config/tox/
Tox data file: /home/gildor/.config/tox/data Tox data file: /home/gildor/.config/tox/data
Gildor's avatar: /home/gildor/.config/tox/avatar.png
Avatar data dir: /home/gildor/.config/tox/avatars/ Avatar data dir: /home/gildor/.config/tox/avatars/
Gildor's avatar: /home/gildor/.config/tox/avatars/E5809EEF5F11AB29B9BDF543C05B58DDF454AB9CA176C235C7699FDC2757DC33.png
Elrond's avatar: /home/gildor/.config/tox/avatars/43656C65627269616E20646F6E277420546F782E426164206D656D6F72696573.png Elrond's avatar: /home/gildor/.config/tox/avatars/43656C65627269616E20646F6E277420546F782E426164206D656D6F72696573.png
Elrond's hash: /home/gildor/.config/tox/avatars/43656C65627269616E20646F6E277420546F782E426164206D656D6F72696573.hash
Elladan's avatar: /home/gildor/.config/tox/avatars/49486174655768656E48756D616E735468696E6B49416D4D7942726F74686572.png Elladan's avatar: /home/gildor/.config/tox/avatars/49486174655768656E48756D616E735468696E6B49416D4D7942726F74686572.png
Elladan's hash: /home/gildor/.config/tox/avatars/49486174655768656E48756D616E735468696E6B49416D4D7942726F74686572.hash
Elrohir's avatar /home/gildor/.config/tox/avatars/726568746F7242794D6D41496B6E696854736E616D75486E6568576574614849.png Elrohir's avatar /home/gildor/.config/tox/avatars/726568746F7242794D6D41496B6E696854736E616D75486E6568576574614849.png
Arwen's avatar: /home/gildor/.config/tox/avatars/53686520746F6F6B20476C6F7266696E64656C277320706C6163652068657265.png Elrohir's hash: /home/gildor/.config/tox/avatars/726568746F7242794D6D41496B6E696854736E616D75486E6568576574614849.hash
Lindir's avatar: /home/gildor/.config/tox/avatars/417070735772697474656E42794D6F7274616C734C6F6F6B54686553616D652E.png
This recommendation is partially implemented by "testing/test_avatars.c". This recommendation is partially implemented by "testing/test_avatars.c".

View File

@ -17,17 +17,15 @@
* *
* Data dir MAY have: * Data dir MAY have:
* *
* - A file named avatar.png. If given, the bot will publish it. Otherwise, * - A directory named "avatars" with the user's avatar and cached avatars.
* no avatar will be set. * The user avatar must be named in the format: "<uppercase user id>.png"
*
* - A directory named "avatars" with the currently cached avatars.
* *
* *
* The bot will answer to these commands: * The bot will answer to these commands:
* *
* !debug-on - Enable extended debug messages * !debug-on - Enable extended debug messages
* !debug-off - Disenable extended debug messages * !debug-off - Disenable extended debug messages
* !set-avatar - Set our avatar to the contents of the file avatar.* * !set-avatar - Set our avatar from "avatars/<USERID>.png"
* !remove-avatar - Remove our avatar * !remove-avatar - Remove our avatar
* *
*/ */
@ -81,13 +79,12 @@ static void debug_printf(const char *fmt, ...)
typedef struct { typedef struct {
uint8_t format; uint8_t format;
char *suffix; char *suffix;
char *file_name; } avatar_format_data_t;
} def_avatar_name_t;
static const def_avatar_name_t def_avatar_names[] = { static const avatar_format_data_t avatar_formats[] = {
/* In order of preference */ /* In order of preference */
{ TOX_AVATAR_FORMAT_PNG, "png", "avatar.png" }, { TOX_AVATAR_FORMAT_PNG, "png" },
{ TOX_AVATAR_FORMAT_NONE, NULL, NULL }, /* Must be the last one */ { TOX_AVATAR_FORMAT_NONE, NULL }, /* Must be the last one */
}; };
@ -99,9 +96,9 @@ static char *get_avatar_suffix_from_format(uint8_t format)
{ {
int i; int i;
for (i = 0; def_avatar_names[i].format != TOX_AVATAR_FORMAT_NONE; i++) for (i = 0; avatar_formats[i].format != TOX_AVATAR_FORMAT_NONE; i++)
if (def_avatar_names[i].format == format) if (avatar_formats[i].format == format)
return def_avatar_names[i].suffix; return avatar_formats[i].suffix;
return NULL; return NULL;
} }
@ -169,8 +166,8 @@ static void byte_to_hex_str(const uint8_t *buf, const size_t buflen, char *dst)
/* Make the cache file name for a avatar of the given format for the given /* Make the cache file name for a avatar of the given format for the given
* client id. * client id.
*/ */
static int make_avatar_file_name(char *dst, size_t dst_len, static int make_avatar_file_name(char *dst, size_t dst_len, const char *base_dir,
char *base_dir, uint8_t format, uint8_t *client_id) const uint8_t format, uint8_t *client_id)
{ {
char client_id_str[2 * TOX_CLIENT_ID_SIZE + 1]; char client_id_str[2 * TOX_CLIENT_ID_SIZE + 1];
byte_to_hex_str(client_id, TOX_CLIENT_ID_SIZE, client_id_str); byte_to_hex_str(client_id, TOX_CLIENT_ID_SIZE, client_id_str);
@ -267,13 +264,13 @@ static int delete_user_avatar(Tox *tox, char *base_dir, int friendnum)
/* This iteration is dumb and inefficient */ /* This iteration is dumb and inefficient */
int i; int i;
for (i = 0; def_avatar_names[i].format != TOX_AVATAR_FORMAT_NONE; i++) { for (i = 0; avatar_formats[i].format != TOX_AVATAR_FORMAT_NONE; i++) {
int ret = make_avatar_file_name(path, sizeof(path), base_dir, int ret = make_avatar_file_name(path, sizeof(path), base_dir,
def_avatar_names[i].format, addr); avatar_formats[i].format, addr);
if (ret != 0) { if (ret != 0) {
DEBUG("Failed to create avatar path for friend #%d, format %d\n", DEBUG("Failed to create avatar path for friend #%d, format %d\n",
friendnum, def_avatar_names[i].format); friendnum, avatar_formats[i].format);
continue; continue;
} }
@ -438,66 +435,49 @@ static void friend_request_cb(Tox *tox, const uint8_t *public_key,
} }
static int try_avatar_file(Tox *tox, const char *base_dir, const def_avatar_name_t *an)
{
char path[PATH_MAX];
int n = snprintf(path, sizeof(path), "%s/%s", base_dir, an->file_name);
path[sizeof(path) - 1] = '\0';
if (n >= sizeof(path)) {
DEBUG("error: path %s too big\n", path);
return -1;
}
DEBUG("trying file %s: ", path);
FILE *fp = fopen(path, "rb");
if (fp != NULL) {
uint8_t buf[2 * TOX_AVATAR_MAX_DATA_LENGTH];
int len = fread(buf, 1, sizeof(buf), fp);
if (len >= 0 && len <= TOX_AVATAR_MAX_DATA_LENGTH) {
int r = tox_set_avatar(tox, an->format, buf, len);
DEBUG("%d bytes, tox_set_avatar returned=%d", len, r);
if (r == 0)
printf("Setting avatar file %s\n", path);
else
printf("Error setting avatar file %s\n", path);
} else if (len < 0) {
DEBUG("read error %d", len);
} else {
printf("Avatar file %s if too big (more than %d bytes)",
path, TOX_AVATAR_MAX_DATA_LENGTH);
}
fclose(fp);
return 0;
} else {
DEBUG("File %s not found", path);
}
return -1;
}
static void set_avatar(Tox *tox, const char *base_dir) static void set_avatar(Tox *tox, const char *base_dir)
{ {
int i; uint8_t addr[TOX_FRIEND_ADDRESS_SIZE];
char path[PATH_MAX];
uint8_t buf[2 * TOX_AVATAR_MAX_DATA_LENGTH];
for (i = 0; i < 4; i++) { tox_get_address(tox, addr);
if (def_avatar_names[i].format == TOX_AVATAR_FORMAT_NONE) {
int i;
for (i = 0; ; i++) {
if (avatar_formats[i].format == TOX_AVATAR_FORMAT_NONE) {
tox_set_avatar(tox, TOX_AVATAR_FORMAT_NONE, NULL, 0); tox_set_avatar(tox, TOX_AVATAR_FORMAT_NONE, NULL, 0);
printf("No avatar file found, setting to NONE.\n"); printf("No avatar file found, setting to NONE.\n");
return; break;
} else { } else {
if (try_avatar_file(tox, base_dir, &def_avatar_names[i]) == 0) int ret = make_avatar_file_name(path, sizeof(path), base_dir,
avatar_formats[i].format, addr);
if (ret < 0) {
printf("Failed to generate avatar file name.\n");
return; return;
} }
}
/* Should be unreachable */ int len = load_avatar_data(path, buf);
printf("UNEXPECTED CODE PATH\n"); if (len < 0) {
printf("Failed to load avatar data from file: %s\n", path);
continue;
}
if (len > TOX_AVATAR_MAX_DATA_LENGTH) {
printf("Avatar file %s is too big (more than %d bytes)",
path, TOX_AVATAR_MAX_DATA_LENGTH);
return;
}
ret = tox_set_avatar(tox, avatar_formats[i].format, buf, len);
DEBUG("tox_set_avatar returned=%d", ret);
if (ret == 0)
printf("Setting avatar from %s (%d bytes).\n", path, len);
else
printf("Error setting avatar from %s.\n", path);
return;
}
}
} }