diff --git a/src/chat.c b/src/chat.c index 35a05e272..eca8ce468 100644 --- a/src/chat.c +++ b/src/chat.c @@ -1578,7 +1578,7 @@ static void chat_onDraw(ToxWindow *self, Toxic *toxic) tox_friend_get_status_message(toxic->tox, self->num, (uint8_t *) statusmsg, NULL); const size_t s_len = tox_friend_get_status_message_size(toxic->tox, self->num, NULL); - filter_str(statusmsg, s_len); + filter_string(statusmsg, s_len, false); snprintf(statusbar->statusmsg, sizeof(statusbar->statusmsg), "%s", statusmsg); statusbar->statusmsg_len = strlen(statusbar->statusmsg); @@ -1738,7 +1738,7 @@ static void chat_onInit(ToxWindow *self, Toxic *toxic) char statusmsg[TOX_MAX_STATUS_MESSAGE_LENGTH + 1] = {0}; tox_friend_get_status_message(tox, self->num, (uint8_t *) statusmsg, NULL); statusmsg[s_len] = '\0'; - filter_str(statusmsg, s_len); + filter_string(statusmsg, s_len, false); snprintf(statusbar->statusmsg, sizeof(statusbar->statusmsg), "%s", statusmsg); } diff --git a/src/friendlist.c b/src/friendlist.c index 885eea160..a6ae137f3 100644 --- a/src/friendlist.c +++ b/src/friendlist.c @@ -1301,7 +1301,7 @@ static void friendlist_onDraw(ToxWindow *self, Toxic *toxic) statusmsg[s_len] = '\0'; - filter_str(statusmsg, s_len); + filter_string(statusmsg, s_len, false); pthread_mutex_lock(&Winthread.lock); snprintf(Friends.list[f].statusmsg, sizeof(Friends.list[f].statusmsg), "%s", statusmsg); @@ -1796,7 +1796,7 @@ bool friend_config_set_alias(const char *public_key, const char *alias, uint16_t char tmp[TOXIC_MAX_NAME_LENGTH + 1]; const uint16_t tmp_len = copy_tox_str(tmp, sizeof(tmp), alias, length); - filter_str(tmp, tmp_len); + filter_string(tmp, tmp_len, true); if (tmp_len == 0 || tmp_len > TOXIC_MAX_NAME_LENGTH) { return false; diff --git a/src/groupchats.c b/src/groupchats.c index 2fc6c665e..3877a11e3 100644 --- a/src/groupchats.c +++ b/src/groupchats.c @@ -451,7 +451,7 @@ void groupchat_update_statusbar_topic(ToxWindow *self, const Tox *tox) tox_group_get_topic(tox, self->num, (uint8_t *)topic, NULL); topic[t_len] = '\0'; - filter_str(topic, t_len); + filter_string(topic, t_len, false); snprintf(statusbar->topic, sizeof(statusbar->topic), "%s", topic); statusbar->topic_len = strlen(statusbar->topic); } diff --git a/src/misc_tools.c b/src/misc_tools.c index 174327559..d26c01637 100644 --- a/src/misc_tools.c +++ b/src/misc_tools.c @@ -305,19 +305,19 @@ int qsort_ptr_char_array_helper(const void *str1, const void *str2) return strcasecmp(*(const char *const *)str1, *(const char *const *)str2); } -static const char invalid_chars[] = {'/', '\n', '\t', '\v', '\r', '\0'}; +/* List of characters we don't allow in nicks. */ +static const char invalid_nick_chars[] = {':', '/', '\0', '\a', '\b', '\f', '\n', '\r', '\t', '\v'}; + +/* List of characters we don't allow in single-line strings. */ +static const char invalid_string_chars[] = {'\0', '\a', '\b', '\f', '\n', '\r', '\t', '\v'}; /* - * Helper function for `valid_nick()`. - * - * Returns true if `ch` is not in the `invalid_chars` array. + * Returns true if the character `ch` is not in the supplied `invalid_chars` array. */ -static bool is_valid_char(char ch) +static bool is_valid_char(char ch, const char *const invalid_chars, size_t list_length) { - char tmp; - - for (size_t i = 0; (tmp = invalid_chars[i]); ++i) { - if (tmp == ch) { + for (size_t i = 0; i < list_length; ++i) { + if (invalid_chars[i] == ch) { return false; } } @@ -325,25 +325,17 @@ static bool is_valid_char(char ch) return true; } -/* Returns true if nick is valid. - * - * A valid toxic nick: - * - cannot be empty - * - cannot start with a space - * - must not contain a forward slash (for logfile naming purposes) - * - must not contain contiguous spaces - * - must not contain a newline or tab seqeunce - */ bool valid_nick(const char *nick) { if (!nick[0] || nick[0] == ' ') { return false; } - for (size_t i = 0; nick[i]; ++i) { + for (size_t i = 0; nick[i] != '\0'; ++i) { char ch = nick[i]; - if ((ch == ' ' && nick[i + 1] == ' ') || !is_valid_char(ch)) { + if ((ch == ' ' && nick[i + 1] == ' ') + || !is_valid_char(ch, invalid_nick_chars, sizeof(invalid_nick_chars))) { return false; } } @@ -351,13 +343,15 @@ bool valid_nick(const char *nick) return true; } -/* Converts all newline/tab chars to spaces (use for strings that should be contained to a single line) */ -void filter_str(char *str, size_t len) +void filter_string(char *str, size_t len, bool is_nick) { + const char *const invalid_chars = is_nick ? invalid_nick_chars : invalid_string_chars; + const size_t list_length = is_nick ? sizeof(invalid_nick_chars) : sizeof(invalid_string_chars); + for (size_t i = 0; i < len; ++i) { char ch = str[i]; - if (!is_valid_char(ch) || str[i] == '\0') { + if (!is_valid_char(ch, invalid_chars, list_length)) { str[i] = ' '; } } @@ -450,7 +444,7 @@ size_t get_nick_truncate(Tox *tox, char *buf, uint16_t buf_size, uint32_t friend len = MIN(len, buf_size - 1); buf[len] = '\0'; - filter_str(buf, len); + filter_string(buf, len, false); return len; @@ -475,7 +469,7 @@ int get_conference_nick_truncate(Tox *tox, char *buf, uint32_t peernum, uint32_t len = MIN(len, TOXIC_MAX_NAME_LENGTH - 1); buf[len] = '\0'; - filter_str(buf, len); + filter_string(buf, len, true); return len; on_error: @@ -507,7 +501,7 @@ size_t get_group_nick_truncate(Tox *tox, char *buf, uint32_t peer_id, uint32_t g len = MIN(len, TOXIC_MAX_NAME_LENGTH - 1); buf[len] = '\0'; - filter_str(buf, len); + filter_string(buf, len, true); return len; } @@ -531,9 +525,9 @@ size_t get_group_self_nick_truncate(Tox *tox, char *buf, uint32_t groupnum) } len = MIN(len, TOXIC_MAX_NAME_LENGTH - 1); - buf[len] = 0; + buf[len] = '\0'; - filter_str(buf, len); + filter_string(buf, len, true); return len; } diff --git a/src/misc_tools.h b/src/misc_tools.h index d0adab7ee..eab7b69c6 100644 --- a/src/misc_tools.h +++ b/src/misc_tools.h @@ -162,16 +162,22 @@ int qsort_ptr_char_array_helper(const void *str1, const void *str2); * A valid toxic nick: * - cannot be empty * - cannot start with a space - * - must not contain a forward slash (for logfile naming purposes) - * - must not contain contiguous spaces - * - must not contain a newline or tab seqeunce + * - cannot contain contiguous spaces + * - cannot contain forward slash (for log file naming purposes) + * - cannot contain any characters in the `invalid_nick_chars` array that + * resides in misc_tools.c. */ bool valid_nick(const char *nick); -/* Converts all newline/tab chars to spaces - * (use for strings that should be contained to a single line) +/* Converts all invalid single-line string characters to spaces (newlines, + * tabs, nul etc.). + * + * If `is_nick` is true, additional characters specific to nicks are filtered. + * + * This function is used for strings that should be human-readable, and contained + * to a single line, such as status messages, nicks, and group topics. */ -void filter_str(char *str, size_t len); +void filter_string(char *str, size_t len, bool is_nick); /* gets base file name from path or original file name if no path is supplied */ size_t get_file_name(char *namebuf, size_t bufsize, const char *pathname); diff --git a/src/windows.c b/src/windows.c index 709e4797e..280b79061 100644 --- a/src/windows.c +++ b/src/windows.c @@ -54,6 +54,7 @@ void on_friend_request(Tox *tox, const uint8_t *public_key, const uint8_t *data, char msg[MAX_STR_SIZE + 1]; length = copy_tox_str(msg, sizeof(msg), (const char *) data, length); + filter_string(msg, length, false); for (uint16_t i = 0; i < windows->count; ++i) { ToxWindow *w = windows->list[i]; @@ -136,7 +137,7 @@ void on_friend_name(Tox *tox, uint32_t friendnumber, const uint8_t *string, size char nick[TOXIC_MAX_NAME_LENGTH + 1]; length = copy_tox_str(nick, sizeof(nick), (const char *) string, length); - filter_str(nick, length); + filter_string(nick, length, true); for (uint16_t i = 0; i < windows->count; ++i) { ToxWindow *w = windows->list[i]; @@ -159,7 +160,7 @@ void on_friend_status_message(Tox *tox, uint32_t friendnumber, const uint8_t *st char msg[TOX_MAX_STATUS_MESSAGE_LENGTH + 1]; length = copy_tox_str(msg, sizeof(msg), (const char *) string, length); - filter_str(msg, length); + filter_string(msg, length, false); for (uint16_t i = 0; i < windows->count; ++i) { ToxWindow *w = windows->list[i]; @@ -266,7 +267,7 @@ void on_conference_peer_name(Tox *tox, uint32_t conferencenumber, uint32_t peern char nick[TOXIC_MAX_NAME_LENGTH + 1]; length = copy_tox_str(nick, sizeof(nick), (const char *) name, length); - filter_str(nick, length); + filter_string(nick, length, true); for (uint16_t i = 0; i < windows->count; ++i) { ToxWindow *w = windows->list[i]; @@ -286,6 +287,7 @@ void on_conference_title(Tox *tox, uint32_t conferencenumber, uint32_t peernumbe char data[MAX_STR_SIZE + 1]; length = copy_tox_str(data, sizeof(data), (const char *) title, length); + filter_string(data, length, false); for (uint16_t i = 0; i < windows->count; ++i) { ToxWindow *w = windows->list[i]; @@ -570,12 +572,14 @@ void on_group_peer_exit(Tox *tox, uint32_t groupnumber, uint32_t peer_id, Tox_Gr char toxic_nick[TOXIC_MAX_NAME_LENGTH + 1]; nick_len = copy_tox_str(toxic_nick, sizeof(toxic_nick), (const char *) nick, nick_len); + filter_string(toxic_nick, nick_len, true); char buf[MAX_STR_SIZE + 1] = {0}; size_t buf_len = 0; if (part_message) { buf_len = copy_tox_str(buf, sizeof(buf), (const char *) part_message, length); + filter_string(buf, buf_len, false); } for (uint16_t i = 0; i < windows->count; ++i) { @@ -597,6 +601,7 @@ void on_group_topic_change(Tox *tox, uint32_t groupnumber, uint32_t peer_id, con char data[MAX_STR_SIZE + 1]; length = copy_tox_str(data, sizeof(data), (const char *) topic, length); + filter_string(data, length, false); for (uint16_t i = 0; i < windows->count; ++i) { ToxWindow *w = windows->list[i]; @@ -681,7 +686,7 @@ void on_group_nick_change(Tox *tox, uint32_t groupnumber, uint32_t peer_id, cons char name[TOXIC_MAX_NAME_LENGTH + 1]; length = copy_tox_str(name, sizeof(name), (const char *) newname, length); - filter_str(name, length); + filter_string(name, length, true); for (uint16_t i = 0; i < windows->count; ++i) { ToxWindow *w = windows->list[i];