From 2c3921a9fb50cbac291922703c737ca61534d5a1 Mon Sep 17 00:00:00 2001 From: Michael Neumann Date: Wed, 9 Sep 2015 13:23:48 +0200 Subject: [PATCH 1/8] Fix compile for DragonFlyBSD --- Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Makefile b/Makefile index 392b257..469876b 100644 --- a/Makefile +++ b/Makefile @@ -24,6 +24,9 @@ endif ifeq ($(UNAME_S), FreeBSD) -include $(CFG_DIR)/systems/FreeBSD.mk endif +ifeq ($(UNAME_S), DragonFly) + -include $(CFG_DIR)/systems/FreeBSD.mk +endif ifeq ($(UNAME_S), OpenBSD) -include $(CFG_DIR)/systems/FreeBSD.mk endif From 6aab9a79d8c3d9ca4e6bc7d2868d6d2cebd330a9 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Sat, 7 Nov 2015 01:00:56 -0500 Subject: [PATCH 2/8] Fix help menu --- src/help.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/help.c b/src/help.c index 3eaf4e9..67b34c7 100644 --- a/src/help.c +++ b/src/help.c @@ -304,7 +304,7 @@ void help_onKey(ToxWindow *self, wint_t key) #elif AUDIO help_init_window(self, 19, 80); #else - help_init_window(self, 9, 80); + help_init_window(self, 10, 80); #endif self->help->type = HELP_CHAT; break; @@ -313,6 +313,7 @@ void help_onKey(ToxWindow *self, wint_t key) #ifdef VIDEO help_init_window(self, 29, 80); #elif AUDIO + help_init_window(self, 25, 80); #else help_init_window(self, 21, 80); #endif From 14a8bdb874f537c98dca940ca55ce51db8c17571 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Sat, 7 Nov 2015 21:38:32 -0500 Subject: [PATCH 3/8] Store temp data in same directory as original file --- src/friendlist.c | 16 +++++++++++++--- src/toxic.c | 13 +++++++++---- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/src/friendlist.c b/src/friendlist.c index c752790..546b6f9 100644 --- a/src/friendlist.c +++ b/src/friendlist.c @@ -125,7 +125,13 @@ void kill_friendlist(void) realloc_friends(0); } -#define TEMP_BLOCKLIST_SAVE_NAME "toxic_blocklist.tmp" +/* Saves the blocklist to path. If there are no items in the blocklist the + * empty file will be removed. + * + * Returns 0 if stored successfully. + * Returns -1 on failure. + */ +#define TEMP_BLOCKLIST_EXT ".tmp" static int save_blocklist(char *path) { if (path == NULL) @@ -165,19 +171,23 @@ static int save_blocklist(char *path) return 0; } - FILE *fp = fopen(TEMP_BLOCKLIST_SAVE_NAME, "wb"); + char temp_path[strlen(path) + strlen(TEMP_BLOCKLIST_EXT) + 1]; + snprintf(temp_path, sizeof(temp_path), "%s%s", path, TEMP_BLOCKLIST_EXT); + + FILE *fp = fopen(temp_path, "wb"); if (fp == NULL) return -1; if (fwrite(data, len, 1, fp) != 1) { + fprintf(stderr, "Failed to write blocklist data.\n"); fclose(fp); return -1; } fclose(fp); - if (rename(TEMP_BLOCKLIST_SAVE_NAME, path) != 0) + if (rename(temp_path, path) != 0) return -1; return 0; diff --git a/src/toxic.c b/src/toxic.c index 2e57183..6fd04d0 100644 --- a/src/toxic.c +++ b/src/toxic.c @@ -537,18 +537,21 @@ static void first_time_encrypt(const char *msg) system("clear"); } -/* Store Tox profile data to given location +/* Store Tox profile data to path. * * Return 0 if stored successfully. * Return -1 on error. */ -#define TEMP_PROFILE_SAVE_NAME "toxic_profile.tmp" +#define TEMP_PROFILE_EXT ".tmp" int store_data(Tox *m, const char *path) { if (path == NULL) return -1; - FILE *fp = fopen(TEMP_PROFILE_SAVE_NAME, "wb"); + char temp_path[strlen(path) + strlen(TEMP_PROFILE_EXT) + 1]; + snprintf(temp_path, sizeof(temp_path), "%s%s", path, TEMP_PROFILE_EXT); + + FILE *fp = fopen(temp_path, "wb"); if (fp == NULL) return -1; @@ -573,11 +576,13 @@ int store_data(Tox *m, const char *path) } if (fwrite(enc_data, enc_len, 1, fp) != 1) { + fprintf(stderr, "Failed to write profile data.\n"); fclose(fp); return -1; } } else { /* data will not be encrypted */ if (fwrite(data, data_len, 1, fp) != 1) { + fprintf(stderr, "Failed to write profile data.\n"); fclose(fp); return -1; } @@ -585,7 +590,7 @@ int store_data(Tox *m, const char *path) fclose(fp); - if (rename(TEMP_PROFILE_SAVE_NAME, path) != 0) + if (rename(temp_path, path) != 0) return -1; return 0; From fa0e645a79ccefb3ca70a1bfc9f037ac648a3955 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Sun, 8 Nov 2015 03:57:01 -0500 Subject: [PATCH 4/8] Fix a bunch of misc bugs and corner cases --- src/audio_call.c | 5 ++-- src/autocomplete.c | 20 +++++++++------ src/chat.c | 13 +++++++++- src/configdir.c | 14 ++++++++--- src/friendlist.c | 2 +- src/groupchat.c | 11 ++++++++- src/help.c | 3 +++ src/name_lookup.c | 4 +-- src/prompt.c | 12 ++++++++- src/toxic.h | 1 + src/video_call.c | 61 +++++++++++++++++++++++----------------------- src/windows.c | 3 +++ 12 files changed, 99 insertions(+), 50 deletions(-) diff --git a/src/audio_call.c b/src/audio_call.c index 5dc72d5..0b7ce4b 100644 --- a/src/audio_call.c +++ b/src/audio_call.c @@ -169,8 +169,9 @@ void terminate_audio() void read_device_callback(const int16_t* captured, uint32_t size, void* data) { TOXAV_ERR_SEND_FRAME error; - uint32_t friend_number = *((uint32_t*)data); /* TODO: Or pass an array of call_idx's */ - int64_t sample_count = CallControl.audio_sample_rate * CallControl.audio_frame_duration / 1000; + uint32_t friend_number = *((uint32_t *)data); /* TODO: Or pass an array of call_idx's */ + int64_t sample_count = ((int64_t) CallControl.audio_sample_rate) * \ + ((int64_t) CallControl.audio_frame_duration) / 1000; if ( sample_count <= 0 || toxav_audio_send_frame(CallControl.av, friend_number, captured, sample_count, diff --git a/src/autocomplete.c b/src/autocomplete.c index 6bc3c6a..d3ea7a4 100644 --- a/src/autocomplete.c +++ b/src/autocomplete.c @@ -114,7 +114,7 @@ int complete_line(ToxWindow *self, const void *list, int n_items, int size) tmp[ctx->pos] = '\0'; const char *s = dir_search ? strchr(tmp, '\"') : strrchr(tmp, ' '); - char *sub = malloc(strlen(ubuf) + 1); + char *sub = calloc(1, strlen(ubuf) + 1); if (sub == NULL) exit_toxic_err("failed in complete_line", FATALERR_MEMORY); @@ -142,14 +142,14 @@ int complete_line(ToxWindow *self, const void *list, int n_items, int size) } int s_len = strlen(sub); - const char *str; int n_matches = 0; char matches[n_items][MAX_STR_SIZE]; int i = 0; /* put all list matches in matches array */ for (i = 0; i < n_items; ++i) { - str = &L[i * size]; + char str[MAX_CMDNAME_SIZE + 1]; + snprintf(str, sizeof(str), "%s", &L[i * size]); if (strncasecmp(str, sub, s_len) == 0) strcpy(matches[n_matches++], str); @@ -165,10 +165,11 @@ int complete_line(ToxWindow *self, const void *list, int n_items, int size) char match[MAX_STR_SIZE]; get_str_match(self, match, matches, n_matches); + size_t match_len = strlen(match); if (dir_search) { if (n_matches == 1) - endchrs = char_rfind(match, '.', strlen(match)) ? "\"" : "/"; + endchrs = char_rfind(match, '.', match_len) ? "\"" : "/"; else endchrs = ""; } else if (n_matches > 1) { @@ -177,18 +178,21 @@ int complete_line(ToxWindow *self, const void *list, int n_items, int size) /* put match in correct spot in buf and append endchars */ int n_endchrs = strlen(endchrs); - int m_len = strlen(match); int strt = ctx->pos - s_len; - int diff = m_len - s_len + n_endchrs; + int diff = match_len - s_len + n_endchrs; if (ctx->len + diff >= MAX_STR_SIZE) return -1; char tmpend[MAX_STR_SIZE]; snprintf(tmpend, sizeof(tmpend), "%s", &ubuf[ctx->pos]); + + if (match_len + n_endchrs + strlen(tmpend) >= sizeof(ubuf)) + return -1; + strcpy(&ubuf[strt], match); - strcpy(&ubuf[strt + m_len], endchrs); - strcpy(&ubuf[strt + m_len + n_endchrs], tmpend); + strcpy(&ubuf[strt + match_len], endchrs); + strcpy(&ubuf[strt + match_len + n_endchrs], tmpend); /* convert to widechar and copy back to original buf */ wchar_t newbuf[MAX_STR_SIZE]; diff --git a/src/chat.c b/src/chat.c index 87219e1..0e91b7e 100644 --- a/src/chat.c +++ b/src/chat.c @@ -795,6 +795,10 @@ static void init_infobox(ToxWindow *self) int x2, y2; getmaxyx(self->window, y2, x2); + + if (y2 <= 0 || x2 <= 0) + return; + (void) y2; memset(&ctx->infobox, 0, sizeof(struct infobox)); @@ -901,7 +905,7 @@ static void chat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr) getyx(self->window, y, x); getmaxyx(self->window, y2, x2); - if (x2 <= 0) + if (y2 <= 0 || x2 <= 0) return; if (self->help->active) { @@ -999,6 +1003,9 @@ static void chat_onDraw(ToxWindow *self, Tox *m) int x2, y2; getmaxyx(self->window, y2, x2); + if (y2 <= 0 || x2 <= 0) + return; + ChatContext *ctx = self->chatwin; pthread_mutex_lock(&Winthread.lock); @@ -1123,6 +1130,10 @@ static void chat_onInit(ToxWindow *self, Tox *m) curs_set(1); int x2, y2; getmaxyx(self->window, y2, x2); + + if (y2 <= 0 || x2 <= 0) + exit_toxic_err("failed in chat_onInit", FATALERR_CURSES); + self->x = x2; /* Init statusbar info */ diff --git a/src/configdir.c b/src/configdir.c index 8a9f60c..db63b6f 100644 --- a/src/configdir.c +++ b/src/configdir.c @@ -31,6 +31,7 @@ #include "toxic.h" #include "configdir.h" +#include "misc_tools.h" /* get the user's home directory */ void get_home_dir(char *home, int size) @@ -69,8 +70,8 @@ char *get_user_config_dir(void) char home[NSS_BUFLEN_PASSWD] = {0}; get_home_dir(home, sizeof(home)); - char *user_config_dir; - size_t len; + char *user_config_dir = NULL; + size_t len = 0; # if defined(__APPLE__) len = strlen(home) + strlen("/Library/Application Support") + 1; @@ -82,9 +83,9 @@ char *get_user_config_dir(void) snprintf(user_config_dir, len, "%s/Library/Application Support", home); # else /* __APPLE__ */ - const char *tmp; + const char *tmp = getenv("XDG_CONFIG_HOME"); - if (!(tmp = getenv("XDG_CONFIG_HOME"))) { + if (tmp == NULL) { len = strlen(home) + strlen("/.config") + 1; user_config_dir = malloc(len); @@ -98,6 +99,11 @@ char *get_user_config_dir(void) # endif /* __APPLE__ */ + if (!file_exists(user_config_dir)) { + free(user_config_dir); + return NULL; + } + return user_config_dir; } diff --git a/src/friendlist.c b/src/friendlist.c index 546b6f9..024d092 100644 --- a/src/friendlist.c +++ b/src/friendlist.c @@ -238,7 +238,7 @@ int load_blocklist(char *path) memcpy(&tmp, data + i * sizeof(BlockedFriend), sizeof(BlockedFriend)); Blocked.list[i].active = true; Blocked.list[i].num = i; - Blocked.list[i].namelength = ntohs(tmp.namelength); + Blocked.list[i].namelength = MIN(TOXIC_MAX_NAME_LENGTH, ntohs(tmp.namelength)); memcpy(Blocked.list[i].name, tmp.name, Blocked.list[i].namelength + 1); memcpy(Blocked.list[i].pub_key, tmp.pub_key, TOX_PUBLIC_KEY_SIZE); diff --git a/src/groupchat.c b/src/groupchat.c index 8aad7d4..95693cd 100644 --- a/src/groupchat.c +++ b/src/groupchat.c @@ -210,6 +210,9 @@ void redraw_groupchat_win(ToxWindow *self) getmaxyx(stdscr, y2, x2); y2 -= 2; + if (y2 <= 0 || x2 <= 0) + return; + if (ctx->sidebar) { delwin(ctx->sidebar); ctx->sidebar = NULL; @@ -559,7 +562,7 @@ static void groupchat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr) getyx(self->window, y, x); getmaxyx(self->window, y2, x2); - if (x2 <= 0) + if (x2 <= 0 || y2 <= 0) return; if (self->help->active) { @@ -649,6 +652,9 @@ static void groupchat_onDraw(ToxWindow *self, Tox *m) int x2, y2; getmaxyx(self->window, y2, x2); + if (x2 <= 0 || y2 <= 0) + return; + ChatContext *ctx = self->chatwin; pthread_mutex_lock(&Winthread.lock); @@ -713,6 +719,9 @@ static void groupchat_onInit(ToxWindow *self, Tox *m) int x2, y2; getmaxyx(self->window, y2, x2); + if (x2 <= 0 || y2 <= 0) + exit_toxic_err("failed in groupchat_onInit", FATALERR_CURSES); + ChatContext *ctx = self->chatwin; ctx->history = subwin(self->window, y2 - CHATBOX_HEIGHT + 1, x2 - SIDEBAR_WIDTH - 1, 0, 0); diff --git a/src/help.c b/src/help.c index 67b34c7..d00123a 100644 --- a/src/help.c +++ b/src/help.c @@ -60,6 +60,9 @@ static void help_init_window(ToxWindow *self, int height, int width) int y2, x2; getmaxyx(stdscr, y2, x2); + if (y2 <= 0 || x2 <= 0) + return; + height = MIN(height, y2); width = MIN(width, x2); diff --git a/src/name_lookup.c b/src/name_lookup.c index 464e206..fad4c9e 100644 --- a/src/name_lookup.c +++ b/src/name_lookup.c @@ -202,12 +202,12 @@ size_t write_lookup_data(void *data, size_t size, size_t nmemb, void *user_point struct Recv_Data *recv_data = (struct Recv_Data *) user_pointer; size_t real_size = size * nmemb; - if (real_size > MAX_RECV_LOOKUP_DATA_SIZE) + if (real_size >= MAX_RECV_LOOKUP_DATA_SIZE) return 0; memcpy(&recv_data->data, data, real_size); recv_data->size = real_size; - recv_data->data[real_size] = 0; + recv_data->data[real_size] = '\0'; return real_size; } diff --git a/src/prompt.c b/src/prompt.c index 1b8527d..b6b9334 100644 --- a/src/prompt.c +++ b/src/prompt.c @@ -185,7 +185,7 @@ static void prompt_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr) getyx(self->window, y, x); getmaxyx(self->window, y2, x2); - if (x2 <= 0) + if (x2 <= 0 || y2 <= 0) return; /* ignore non-menu related input if active */ @@ -256,6 +256,9 @@ static void prompt_onDraw(ToxWindow *self, Tox *m) int x2, y2; getmaxyx(self->window, y2, x2); + if (y2 <= 0 || x2 <= 0) + return; + ChatContext *ctx = self->chatwin; pthread_mutex_lock(&Winthread.lock); @@ -431,6 +434,10 @@ void prompt_init_statusbar(ToxWindow *self, Tox *m) { int x2, y2; getmaxyx(self->window, y2, x2); + + if (y2 <= 0 || x2 <= 0) + exit_toxic_err("failed in prompt_init_statusbar", FATALERR_CURSES); + (void) y2; /* Init statusbar info */ @@ -488,6 +495,9 @@ static void prompt_onInit(ToxWindow *self, Tox *m) int y2, x2; getmaxyx(self->window, y2, x2); + if (y2 <= 0 || x2 <= 0) + exit_toxic_err("failed in prompt_onInit", FATALERR_CURSES); + ChatContext *ctx = self->chatwin; ctx->history = subwin(self->window, y2 - CHATBOX_HEIGHT + 1, x2, 0, 0); ctx->linewin = subwin(self->window, CHATBOX_HEIGHT, x2, y2 - CHATBOX_HEIGHT, 0); diff --git a/src/toxic.h b/src/toxic.h index 67c8d85..5f7bd88 100644 --- a/src/toxic.h +++ b/src/toxic.h @@ -88,6 +88,7 @@ typedef enum _FATAL_ERRS { FATALERR_PROXY = -10, /* Tox network failed to init using a proxy */ FATALERR_ENCRYPT = -11, /* Data file encryption failure */ FATALERR_TOX_INIT = -12, /* Tox instance failed to initialize */ + FATALERR_CURSES = -13, /* Unrecoverable Ncurses error */ } FATAL_ERRS; /* Fixes text color problem on some terminals. diff --git a/src/video_call.c b/src/video_call.c index 950cf55..95da741 100644 --- a/src/video_call.c +++ b/src/video_call.c @@ -153,9 +153,10 @@ int stop_video_transmission(Call *call, int friend_number) CallControl.video_bit_rate = 0; toxav_bit_rate_set(CallControl.av, friend_number, -1, CallControl.video_bit_rate, NULL); - if ( call->vin_idx != -1 ) + if ( call->vin_idx != -1 ) { close_video_device(vdt_input, call->vin_idx); call->vin_idx = -1; + } return 0; } @@ -190,12 +191,12 @@ void callback_recv_video_starting(uint32_t friend_number) { return; - Call* this_call = &CallControl.calls[friend_number]; + // Call* this_call = &CallControl.calls[friend_number]; - if ( this_call->vout_idx != -1 ) - return; + // if ( this_call->vout_idx != -1 ) + // return; - open_primary_video_device(vdt_output, &this_call->vout_idx); + // open_primary_video_device(vdt_output, &this_call->vout_idx); } void callback_recv_video_end(uint32_t friend_number) { @@ -243,37 +244,37 @@ void cmd_video(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[M { return; // TODO: Fix video - const char *error_str; - Call* this_call = &CallControl.calls[self->num]; +// const char *error_str; +// Call* this_call = &CallControl.calls[self->num]; - if ( argc != 0 ) { - error_str = "Unknown arguments."; - goto on_error; - } +// if ( argc != 0 ) { +// error_str = "Unknown arguments."; +// goto on_error; +// } - if ( !CallControl.av ) { - error_str = "ToxAV not supported!"; - goto on_error; - } +// if ( !CallControl.av ) { +// error_str = "ToxAV not supported!"; +// goto on_error; +// } - if ( !self->stb->connection ) { - error_str = "Friend is offline."; - goto on_error; - } +// if ( !self->stb->connection ) { +// error_str = "Friend is offline."; +// goto on_error; +// } - if ( !self->is_call ) { - error_str = "Not in call!"; - goto on_error; - } +// if ( !self->is_call ) { +// error_str = "Not in call!"; +// goto on_error; +// } - if ( this_call->vin_idx == -1 ) - callback_video_starting(self->num); - else - callback_video_end(self->num); +// if ( this_call->vin_idx == -1 ) +// callback_video_starting(self->num); +// else +// callback_video_end(self->num); - return; -on_error: - print_err (self, error_str); +// return; +// on_error: +// print_err (self, error_str); } void cmd_list_video_devices(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) diff --git a/src/windows.c b/src/windows.c index f0f37be..0116a5a 100644 --- a/src/windows.c +++ b/src/windows.c @@ -400,6 +400,9 @@ void on_window_resize(void) getmaxyx(stdscr, y2, x2); y2 -= 2; + if (y2 <= 0 || x2 <= 0) + return; + size_t i; for (i = 0; i < MAX_WINDOWS_NUM; ++i) { From c5d9aca3e199fa93393283b08a1f51efcaa1f457 Mon Sep 17 00:00:00 2001 From: JFreegman Date: Sun, 8 Nov 2015 03:59:12 -0500 Subject: [PATCH 5/8] Add coverity badge to readme --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index da5d8b5..a61a887 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,8 @@ + + Coverity Scan Build Status + + Toxic is a [Tox](https://tox.chat)-based instant messenging client which formerly resided in the [Tox core repository](https://github.com/irungentoo/toxcore), and is now available as a standalone application. [![Toxic Screenshot](https://i.imgur.com/san99Z2.png "Home Screen")](https://i.imgur.com/san99Z2.png) From 39c4b7ecdd5ecfac488dbc85e3762e4a8aabf5e4 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Sun, 8 Nov 2015 22:51:46 -0500 Subject: [PATCH 6/8] Add ability to print your Tox ID's QR code to a file --- INSTALL.md | 1 + Makefile | 4 +- src/chat.c | 5 +- src/execute.c | 1 + src/friendlist.c | 1 - src/global_commands.c | 60 +++++++++++++++++++----- src/global_commands.h | 1 + src/groupchat.c | 5 +- src/help.c | 7 +-- src/misc_tools.c | 40 +++++++++++++++- src/misc_tools.h | 15 ++++++ src/prompt.c | 7 +-- src/qr_code.c | 103 ++++++++++++++++++++++++++++++++++++++++++ src/qr_code.h | 35 ++++++++++++++ 14 files changed, 259 insertions(+), 26 deletions(-) create mode 100644 src/qr_code.c create mode 100644 src/qr_code.h diff --git a/INSTALL.md b/INSTALL.md index 12d9749..15f96cc 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -16,6 +16,7 @@ | [LibConfig](http://www.hyperrealm.com/libconfig) | BASE | libconfig-dev | | [GNUmake](https://www.gnu.org/software/make) | BASE | make | | [libcurl](http://curl.haxx.se/) | BASE | libcurl4-openssl-dev| +| [libqrencode](https://fukuchi.org/works/qrencode/) | BASE | libqrencode-dev | | [Tox Core AV](https://github.com/irungentoo/toxcore) | AUDIO | *None* | | [OpenAL](http://openal.org) | AUDIO, SOUND NOTIFICATIONS | libopenal-dev | | [OpenALUT](http://openal.org) | SOUND NOTIFICATIONS | libalut-dev | diff --git a/Makefile b/Makefile index 3b69687..2f07ace 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ CFG_DIR = $(BASE_DIR)/cfg -include $(CFG_DIR)/global_vars.mk -LIBS = libtoxcore ncursesw libconfig +LIBS = libtoxcore ncursesw libconfig libqrencode CFLAGS = -std=gnu99 -pthread -Wall -g CFLAGS += '-DTOXICVER="$(VERSION)"' -DHAVE_WIDECHAR -D_XOPEN_SOURCE_EXTENDED -D_FILE_OFFSET_BITS=64 @@ -14,7 +14,7 @@ LDFLAGS = $(USER_LDFLAGS) OBJ = chat.o chat_commands.o configdir.o execute.o file_transfers.o notify.o OBJ += friendlist.o global_commands.o groupchat.o line_info.o input.o help.o autocomplete.o OBJ += log.o misc_tools.o prompt.o settings.o toxic.o toxic_strings.o windows.o message_queue.o -OBJ += group_commands.o term_mplex.o avatars.o name_lookup.o +OBJ += group_commands.o term_mplex.o avatars.o name_lookup.o qr_code.o # Check on wich system we are running UNAME_S = $(shell uname -s) diff --git a/src/chat.c b/src/chat.c index 0e91b7e..81dbb7a 100644 --- a/src/chat.c +++ b/src/chat.c @@ -63,9 +63,9 @@ static void kill_infobox(ToxWindow *self); #endif /* AUDIO */ #ifdef AUDIO -#define AC_NUM_CHAT_COMMANDS 28 +#define AC_NUM_CHAT_COMMANDS 29 #else -#define AC_NUM_CHAT_COMMANDS 21 +#define AC_NUM_CHAT_COMMANDS 22 #endif /* AUDIO */ /* Array of chat command names used for tab completion. */ @@ -84,6 +84,7 @@ static const char chat_cmd_list[AC_NUM_CHAT_COMMANDS][MAX_CMDNAME_SIZE] = { { "/join" }, { "/log" }, { "/myid" }, + { "/myqr" }, { "/nick" }, { "/note" }, { "/nospam" }, diff --git a/src/execute.c b/src/execute.c index 2683b5b..6483782 100644 --- a/src/execute.c +++ b/src/execute.c @@ -51,6 +51,7 @@ static struct cmd_func global_commands[] = { { "/help", cmd_prompt_help }, { "/log", cmd_log }, { "/myid", cmd_myid }, + { "/myqr", cmd_myqr }, { "/nick", cmd_nick }, { "/note", cmd_note }, { "/nospam", cmd_nospam }, diff --git a/src/friendlist.c b/src/friendlist.c index 024d092..a254750 100644 --- a/src/friendlist.c +++ b/src/friendlist.c @@ -26,7 +26,6 @@ #include #include #include -#include #include diff --git a/src/global_commands.c b/src/global_commands.c index 5166a7c..42c731c 100644 --- a/src/global_commands.c +++ b/src/global_commands.c @@ -22,7 +22,6 @@ #include #include -#include #include "toxic.h" #include "windows.h" @@ -36,6 +35,7 @@ #include "term_mplex.h" #include "avatars.h" #include "name_lookup.h" +#include "qr_code.h" extern char *DATA_FILE; extern ToxWindow *prompt; @@ -415,19 +415,57 @@ void cmd_log(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX void cmd_myid(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) { - char id[TOX_ADDRESS_SIZE * 2 + 1] = {0}; - char address[TOX_ADDRESS_SIZE]; - tox_self_get_address(m, (uint8_t *) address); + char id_string[TOX_ADDRESS_SIZE * 2 + 1]; + char bin_id[TOX_ADDRESS_SIZE]; + tox_self_get_address(m, (uint8_t *) bin_id); - size_t i; - - for (i = 0; i < TOX_ADDRESS_SIZE; ++i) { - char xx[3]; - snprintf(xx, sizeof(xx), "%02X", address[i] & 0xff); - strcat(id, xx); + if (bin_id_to_string(bin_id, sizeof(bin_id), id_string, sizeof(id_string)) == -1) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to print ID."); + return; } - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s", id); + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s", id_string); +} + +void cmd_myqr(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) +{ + char id_string[TOX_ADDRESS_SIZE * 2 + 1]; + char bin_id[TOX_ADDRESS_SIZE]; + tox_self_get_address(m, (uint8_t *) bin_id); + + if (bin_id_to_string(bin_id, sizeof(bin_id), id_string, sizeof(id_string)) == -1) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to create QR code."); + return; + } + + char nick[TOX_MAX_NAME_LENGTH]; + tox_self_get_name(m, (uint8_t *) nick); + size_t nick_len = tox_self_get_name_size(m); + nick[nick_len] = '\0'; + + size_t data_file_len = strlen(DATA_FILE); + char dir[data_file_len]; + size_t dir_len = get_base_dir(DATA_FILE, data_file_len, dir); + + char qr_path[dir_len + nick_len + strlen(QRCODE_FILENAME_EXT) + 1]; + snprintf(qr_path, sizeof(qr_path), "%s%s%s", dir, nick, QRCODE_FILENAME_EXT); + + FILE *output = fopen(qr_path, "wb"); + + if (output == NULL) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to create QR code."); + return; + } + + if (ID_to_QRcode(id_string, output) == -1) { + fclose(output); + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to create QR code."); + return; + } + + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "QR code has been printed to the file '%s'", qr_path); + + fclose(output); } void cmd_nick(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) diff --git a/src/global_commands.h b/src/global_commands.h index 72c573b..8c5c3e7 100644 --- a/src/global_commands.h +++ b/src/global_commands.h @@ -35,6 +35,7 @@ void cmd_decline(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv) void cmd_groupchat(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_log(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_myid(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]); +void cmd_myqr(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_nick(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_note(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_nospam(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); diff --git a/src/groupchat.c b/src/groupchat.c index 95693cd..1e9bcb4 100644 --- a/src/groupchat.c +++ b/src/groupchat.c @@ -70,9 +70,9 @@ extern struct user_settings *user_settings; extern struct Winthread Winthread; #ifdef AUDIO -#define AC_NUM_GROUP_COMMANDS 23 +#define AC_NUM_GROUP_COMMANDS 24 #else -#define AC_NUM_GROUP_COMMANDS 19 +#define AC_NUM_GROUP_COMMANDS 20 #endif /* AUDIO */ /* Array of groupchat command names used for tab completion. */ @@ -89,6 +89,7 @@ static const char group_cmd_list[AC_NUM_GROUP_COMMANDS][MAX_CMDNAME_SIZE] = { { "/help" }, { "/log" }, { "/myid" }, + { "/myqr" }, { "/nick" }, { "/note" }, { "/nospam" }, diff --git a/src/help.c b/src/help.c index d00123a..3ecc3f5 100644 --- a/src/help.c +++ b/src/help.c @@ -158,6 +158,7 @@ static void help_draw_global(ToxWindow *self) wprintw(win, " /log or : Enable/disable logging\n"); wprintw(win, " /group : Create a group chat where type: text | audio\n"); wprintw(win, " /myid : Print your Tox ID\n"); + wprintw(win, " /myqr : Print your Tox ID's QR code to a file.\n"); wprintw(win, " /clear : Clear window history\n"); wprintw(win, " /close : Close the current chat window\n"); wprintw(win, " /quit or /exit : Exit Toxic\n"); @@ -314,11 +315,11 @@ void help_onKey(ToxWindow *self, wint_t key) case 'g': #ifdef VIDEO - help_init_window(self, 29, 80); + help_init_window(self, 30, 80); #elif AUDIO - help_init_window(self, 25, 80); + help_init_window(self, 26, 80); #else - help_init_window(self, 21, 80); + help_init_window(self, 22, 80); #endif self->help->type = HELP_GLOBAL; break; diff --git a/src/misc_tools.c b/src/misc_tools.c index 68f1963..0214661 100644 --- a/src/misc_tools.c +++ b/src/misc_tools.c @@ -149,6 +149,24 @@ int hex_string_to_bytes(char *buf, int size, const char *keystr) return 0; } +/* Converts a binary representation of a Tox ID into a string. + * + * Returns 0 on success. + * Returns -1 on failure. + */ +int bin_id_to_string(const char *bin_id, size_t bin_id_size, char *output, size_t output_size) +{ + if (bin_id_size != TOX_ADDRESS_SIZE || output_size < (TOX_ADDRESS_SIZE * 2 + 1)) + return -1; + + size_t i; + + for (i = 0; i < TOX_ADDRESS_SIZE; ++i) + snprintf(&output[i*2], output_size - (i * 2), "%02X", bin_id[i] & 0xff); + + return 0; +} + /* Returns 1 if the string is empty, 0 otherwise */ int string_is_empty(const char *string) { @@ -263,6 +281,24 @@ size_t get_file_name(char *namebuf, size_t bufsize, const char *pathname) return strlen(namebuf); } +/* Gets the base directory of path and puts it in dir. + * dir must have at least as much space as path_len. + * + * Returns the length of the base directory. + */ +size_t get_base_dir(const char *path, size_t path_len, char *dir) +{ + size_t dir_len = char_rfind(path, '/', path_len); + + if (dir_len != 0 && dir_len < path_len) + ++dir_len; /* Leave trailing slash */ + + memcpy(dir, path, dir_len); + dir[dir_len] = '\0'; + + return dir_len; +} + /* converts str to all lowercase */ void str_to_lower(char *str) { @@ -332,8 +368,8 @@ int char_find(int idx, const char *s, char ch) return i; } -/* returns index of the last instance of ch in s starting at len - returns 0 if char not found (skips 0th index) */ +/* returns index of the last instance of ch in s starting at len. + returns 0 if char not found (skips 0th index). */ int char_rfind(const char *s, char ch, int len) { int i = 0; diff --git a/src/misc_tools.h b/src/misc_tools.h index 605555f..d49a288 100644 --- a/src/misc_tools.h +++ b/src/misc_tools.h @@ -53,6 +53,13 @@ int hex_string_to_bin(const char *hex_string, size_t hex_len, char *output, size /* convert a hex string to bytes. returns 0 on success, -1 on failure */ int hex_string_to_bytes(char *buf, int size, const char *keystr); +/* Converts a binary representation of a Tox ID into a string. + * + * Returns 0 on success. + * Returns -1 on failure. + */ +int bin_id_to_string(const char *bin_id, size_t bin_id_size, char *output, size_t output_size); + /* get the current unix time (not thread safe) */ uint64_t get_unix_time(void); @@ -103,6 +110,14 @@ void filter_str(char *str, size_t len); /* 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); +/* Gets the base directory of path and puts it in dir. + * dir must have at least as much space as path_len. + * + * Returns the length of the base directory on success. + * Returns -1 on failure. + */ +size_t get_base_dir(const char *path, size_t path_len, char *dir); + /* converts str to all lowercase */ void str_to_lower(char *str); diff --git a/src/prompt.c b/src/prompt.c index b6b9334..33b68b9 100644 --- a/src/prompt.c +++ b/src/prompt.c @@ -50,11 +50,11 @@ extern struct Winthread Winthread; extern FriendsList Friends; FriendRequests FrndRequests; #ifdef VIDEO -#define AC_NUM_GLOB_COMMANDS 21 +#define AC_NUM_GLOB_COMMANDS 22 #elif AUDIO -#define AC_NUM_GLOB_COMMANDS 19 +#define AC_NUM_GLOB_COMMANDS 20 #else -#define AC_NUM_GLOB_COMMANDS 17 +#define AC_NUM_GLOB_COMMANDS 18 #endif /* Array of global command names used for tab completion. */ @@ -70,6 +70,7 @@ static const char glob_cmd_list[AC_NUM_GLOB_COMMANDS][MAX_CMDNAME_SIZE] = { { "/help" }, { "/log" }, { "/myid" }, + { "/myqr" }, { "/nick" }, { "/note" }, { "/nospam" }, diff --git a/src/qr_code.c b/src/qr_code.c new file mode 100644 index 0000000..cd02c1a --- /dev/null +++ b/src/qr_code.c @@ -0,0 +1,103 @@ +/* qr_obj_code.c + * + * + * Copyright (C) 2015 Toxic All Rights Reserved. + * + * This file is part of Toxic. + * + * Toxic 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 Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Toxic 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 Toxic. If not, see . + * + */ + +#include +#include +#include + +#include "toxic.h" +#include "windows.h" +#include "qr_code.h" + +#define BORDER_CHAR "|" +#define BORDER_LEN 1 +#define CHAR_1 "\342\226\210" +#define CHAR_2 "\342\226\204" +#define CHAR_3 "\342\226\200" + +static void add_border(FILE *fp, size_t width) +{ + size_t i, j; + + for (i = 0; i < BORDER_LEN; i += 2) { + fprintf(fp, BORDER_CHAR); + + for (j = 0; j < BORDER_LEN + width + BORDER_LEN; ++j) + fprintf(fp, "%s", CHAR_1); + + fprintf(fp, "%s\n", BORDER_CHAR); + } +} + +/* Converts a tox ID string into a QRcode and prints it to the given file stream. + * + * Returns 0 on success. + * Returns -1 on failure. + */ +int ID_to_QRcode(const char *tox_id, FILE *fp) +{ + if (fp == NULL) + return -1; + + QRcode *qr_obj = QRcode_encodeString(tox_id, 0, QR_ECLEVEL_L, QR_MODE_8, 0); + + if (qr_obj == NULL) + return -1; + + size_t width = qr_obj->width; + add_border(fp, width); + + size_t i, j; + + for (i = 0; i < width; i += 2) { + const unsigned char *row_1 = qr_obj->data + width * i; + const unsigned char *row_2 = row_1 + width; + + fprintf(fp, BORDER_CHAR); + + for (j = 0; j < BORDER_LEN; ++j) + fprintf(fp, "%s", CHAR_1); + + for (j = 0; j < width; ++j) { + bool x = row_1[j] & 1; + bool y = (i + 1) < width ? (row_2[j] & 1) : false; + + if (x && y) + fprintf(fp, " "); + else if (x) + fprintf(fp, "%s", CHAR_2); + else if (y) + fprintf(fp, "%s", CHAR_3); + else + fprintf(fp, "%s", CHAR_1); + } + + for (j = 0; j < BORDER_LEN; ++j) + fprintf(fp, "%s", CHAR_1); + + fprintf(fp, "%s\n", BORDER_CHAR); + } + + QRcode_free(qr_obj); + + return 0; +} diff --git a/src/qr_code.h b/src/qr_code.h new file mode 100644 index 0000000..eb94ddf --- /dev/null +++ b/src/qr_code.h @@ -0,0 +1,35 @@ +/* qr_code.h + * + * + * Copyright (C) 2015 Toxic All Rights Reserved. + * + * This file is part of Toxic. + * + * Toxic 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 Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Toxic 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 Toxic. If not, see . + * + */ + +#ifndef QR_CODE +#define QR_CODE + +#define QRCODE_FILENAME_EXT ".QRcode" + +/* Converts a tox ID string into a QRcode and prints it to the given file stream. + * + * Returns 0 on success. + * Returns -1 on failure. + */ +int ID_to_QRcode(const char *tox_id, FILE *fp); + +#endif /* QR_CODE */ From 7e0b8b48708516c9bf76a37199744b7bea5ebd2f Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Mon, 9 Nov 2015 02:28:41 -0500 Subject: [PATCH 7/8] Slight improvement to qrcode printing --- src/qr_code.c | 31 +++++++++---------------------- 1 file changed, 9 insertions(+), 22 deletions(-) diff --git a/src/qr_code.c b/src/qr_code.c index cd02c1a..e496c8c 100644 --- a/src/qr_code.c +++ b/src/qr_code.c @@ -34,20 +34,6 @@ #define CHAR_2 "\342\226\204" #define CHAR_3 "\342\226\200" -static void add_border(FILE *fp, size_t width) -{ - size_t i, j; - - for (i = 0; i < BORDER_LEN; i += 2) { - fprintf(fp, BORDER_CHAR); - - for (j = 0; j < BORDER_LEN + width + BORDER_LEN; ++j) - fprintf(fp, "%s", CHAR_1); - - fprintf(fp, "%s\n", BORDER_CHAR); - } -} - /* Converts a tox ID string into a QRcode and prints it to the given file stream. * * Returns 0 on success. @@ -64,19 +50,20 @@ int ID_to_QRcode(const char *tox_id, FILE *fp) return -1; size_t width = qr_obj->width; - add_border(fp, width); - size_t i, j; + for (i = 0; i < width + BORDER_LEN * 2; ++i) + fprintf(fp, "%s", CHAR_1); + + fprintf(fp, "\n"); + for (i = 0; i < width; i += 2) { - const unsigned char *row_1 = qr_obj->data + width * i; - const unsigned char *row_2 = row_1 + width; - - fprintf(fp, BORDER_CHAR); - for (j = 0; j < BORDER_LEN; ++j) fprintf(fp, "%s", CHAR_1); + const unsigned char *row_1 = qr_obj->data + width * i; + const unsigned char *row_2 = row_1 + width; + for (j = 0; j < width; ++j) { bool x = row_1[j] & 1; bool y = (i + 1) < width ? (row_2[j] & 1) : false; @@ -94,7 +81,7 @@ int ID_to_QRcode(const char *tox_id, FILE *fp) for (j = 0; j < BORDER_LEN; ++j) fprintf(fp, "%s", CHAR_1); - fprintf(fp, "%s\n", BORDER_CHAR); + fprintf(fp, "\n"); } QRcode_free(qr_obj); From d16be574f3c8c1f4017bd0b0257e230da0a057c8 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Tue, 10 Nov 2015 23:34:46 -0500 Subject: [PATCH 8/8] Add stack protection compile flag to Makefile --- Makefile | 2 +- src/qr_code.c | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 2f07ace..6781c60 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ CFG_DIR = $(BASE_DIR)/cfg LIBS = libtoxcore ncursesw libconfig libqrencode -CFLAGS = -std=gnu99 -pthread -Wall -g +CFLAGS = -std=gnu99 -pthread -Wall -g -fstack-protector-all CFLAGS += '-DTOXICVER="$(VERSION)"' -DHAVE_WIDECHAR -D_XOPEN_SOURCE_EXTENDED -D_FILE_OFFSET_BITS=64 CFLAGS += '-DPACKAGE_DATADIR="$(abspath $(DATADIR))"' CFLAGS += $(USER_CFLAGS) diff --git a/src/qr_code.c b/src/qr_code.c index e496c8c..1341126 100644 --- a/src/qr_code.c +++ b/src/qr_code.c @@ -28,7 +28,6 @@ #include "windows.h" #include "qr_code.h" -#define BORDER_CHAR "|" #define BORDER_LEN 1 #define CHAR_1 "\342\226\210" #define CHAR_2 "\342\226\204"