From fba0732faa6995152b7cf9c0a614a11281916a16 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Thu, 31 Jul 2014 12:48:49 -0400 Subject: [PATCH 1/4] implement contact blocking --- src/audio_call.c | 6 +- src/friendlist.c | 417 +++++++++++++++++++++++++++++++++++++++++++---- src/friendlist.h | 9 + src/toxic.c | 82 +++++----- src/windows.h | 8 + 5 files changed, 453 insertions(+), 69 deletions(-) diff --git a/src/audio_call.c b/src/audio_call.c index aa57f9a..439d7c3 100644 --- a/src/audio_call.c +++ b/src/audio_call.c @@ -576,7 +576,7 @@ on_error: print_err (self, error_str); } -void cmd_ccur_device(WINDOW * window, ToxWindow * self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) +void cmd_ccur_device(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) { const char *msg; const char *error_str; @@ -651,7 +651,7 @@ void cmd_ccur_device(WINDOW * window, ToxWindow * self, Tox *m, int argc, char ( print_err (self, error_str); } -void cmd_mute(WINDOW * window, ToxWindow * self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) +void cmd_mute(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) { const char *msg; const char *error_str; @@ -699,7 +699,7 @@ void cmd_mute(WINDOW * window, ToxWindow * self, Tox *m, int argc, char (*argv)[ print_err (self, error_str); } -void cmd_sense(WINDOW * window, ToxWindow * self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) +void cmd_sense(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) { const char *error_str; diff --git a/src/friendlist.c b/src/friendlist.c index 7dc69c8..e8af47a 100644 --- a/src/friendlist.c +++ b/src/friendlist.c @@ -42,26 +42,142 @@ extern char *DATA_FILE; +extern char *BLOCK_FILE; extern ToxWindow *prompt; - -static int max_friends_index = 0; /* marks the index of the last friend in friends array */ -static int num_selected = 0; -static int num_friends = 0; - extern struct _Winthread Winthread; extern struct user_settings *user_settings_; +extern struct arg_opts arg_opts; + +static uint8_t blocklist_view = 0; /* 0 if we're in friendlist view, 1 if we're in blocklist view */ +static int num_selected = 0; +static int max_friends_index = 0; /* 1 + the index of the last friend in friends array */ +static int num_friends = 0; ToxicFriend friends[MAX_FRIENDS_NUM]; static int friendlist_index[MAX_FRIENDS_NUM] = {0}; +static struct _Blocked_Contacts { + int num_selected; + int max_index; + int num_blocked; + BlockedFriend list[MAX_FRIENDS_NUM]; + int index[MAX_FRIENDS_NUM]; +} Blocked_Contacts; + static struct _pendingDel { int num; bool active; WINDOW *popup; } pendingdelete; -#define S_WEIGHT 100000 +static int save_blocklist(char *path) +{ + if (arg_opts.ignore_data_file) + return 0; + if (path == NULL) + return -1; + + int len = sizeof(BlockedFriend) * Blocked_Contacts.num_blocked; + char *data = malloc(len); + + if (data == NULL) + exit_toxic_err("Failed in save_blocklist", FATALERR_MEMORY); + + int i; + int count = 0; + + for (i = 0; i < Blocked_Contacts.max_index; ++i) { + if (count > Blocked_Contacts.num_blocked) + return -1; + + if (Blocked_Contacts.list[i].active) { + BlockedFriend tmp; + memset(&tmp, 0, sizeof(BlockedFriend)); + tmp.namelength = Blocked_Contacts.list[i].namelength; + memcpy(tmp.name, Blocked_Contacts.list[i].name, Blocked_Contacts.list[i].namelength + 1); + memcpy(tmp.pub_key, Blocked_Contacts.list[i].pub_key, TOX_CLIENT_ID_SIZE); + memcpy(data + count * sizeof(BlockedFriend), &tmp, sizeof(BlockedFriend)); + ++count; + } + } + + FILE *fp = fopen(path, "wb"); + + if (fp == NULL) { + free(data); + return -1; + } + + int ret = 0; + + if (fwrite(data, len, 1, fp) != 1) + ret = -1; + + fclose(fp); + free(data); + return ret; +} + +static void sort_blocklist_index(void); + +int load_blocklist(char *path) +{ + if (path == NULL) + return -1; + + FILE *fp = fopen(path, "rb"); + + if (fp == NULL) + return -1; + + fseek(fp, 0, SEEK_END); + int len = ftell(fp); + fseek(fp, 0, SEEK_SET); + + char *data = malloc(len); + + if (data == NULL) { + fclose(fp); + exit_toxic_err("Failed in load_blocklist", FATALERR_MEMORY); + } + + if (fread(data, len, 1, fp) != 1) { + fclose(fp); + free(data); + return -1; + } + + if (len % sizeof(BlockedFriend) != 0) { + fclose(fp); + free(data); + return -1; + } + + int num = len / sizeof(BlockedFriend); + int i; + + for (i = 0; i < num; ++i) { + BlockedFriend tmp; + memcpy(&tmp, data + i * sizeof(BlockedFriend), sizeof(BlockedFriend)); + Blocked_Contacts.list[i].active = true; + Blocked_Contacts.list[i].num = i; + Blocked_Contacts.list[i].namelength = tmp.namelength; + memcpy(Blocked_Contacts.list[i].name, tmp.name, tmp.namelength + 1); + memcpy(Blocked_Contacts.list[i].pub_key, tmp.pub_key, TOX_CLIENT_ID_SIZE); + ++Blocked_Contacts.num_blocked; + } + + Blocked_Contacts.max_index = i + 1; + + free(data); + fclose(fp); + sort_blocklist_index(); + + return 0; +} + +#define S_WEIGHT 100000 static int index_name_cmp(const void *n1, const void *n2) { int res = qsort_strcasecmp_hlpr(friends[*(int *) n1].name, friends[*(int *) n2].name); @@ -87,6 +203,24 @@ void sort_friendlist_index(void) qsort(friendlist_index, num_friends, sizeof(int), index_name_cmp); } +static int index_name_cmp_block(const void *n1, const void *n2) +{ + return qsort_strcasecmp_hlpr(Blocked_Contacts.list[*(int *) n1].name, Blocked_Contacts.list[*(int *) n2].name); +} + +static void sort_blocklist_index(void) +{ + int i; + int n = 0; + + for (i = 0; i < Blocked_Contacts.max_index; ++i) { + if (Blocked_Contacts.list[i].active) + Blocked_Contacts.index[n++] = Blocked_Contacts.list[i].num; + } + + qsort(Blocked_Contacts.index, Blocked_Contacts.num_blocked, sizeof(int), index_name_cmp_block); +} + static void update_friend_last_online(int32_t num, uint64_t timestamp) { friends[num].last_online.last_on = timestamp; @@ -207,6 +341,38 @@ void friendlist_onFriendAdded(ToxWindow *self, Tox *m, int32_t num, bool sort) } } +/* puts blocked friend back in friendlist. fnum is new friend number, bnum is blocked number */ +static void friendlist_add_blocked(Tox *m, int32_t fnum, int32_t bnum) +{ + if (max_friends_index >= MAX_FRIENDS_NUM) + return; + + int i; + + for (i = 0; i <= max_friends_index; ++i) { + if (friends[i].active) + continue; + + friends[i].num = fnum; + friends[i].active = true; + friends[i].chatwin = -1; + friends[i].status = TOX_USERSTATUS_NONE; + friends[i].logging_on = (bool) user_settings_->autolog == AUTOLOG_ON; + friends[i].namelength = Blocked_Contacts.list[bnum].namelength; + memcpy(friends[i].name, Blocked_Contacts.list[bnum].name, friends[i].namelength + 1); + memcpy(friends[i].pub_key, Blocked_Contacts.list[bnum].pub_key, TOX_CLIENT_ID_SIZE); + + num_friends = tox_count_friendlist(m); + + if (i == max_friends_index) + ++max_friends_index; + + sort_blocklist_index(); + sort_friendlist_index(); + return; + } +} + static void friendlist_onFileSendRequest(ToxWindow *self, Tox *m, int32_t num, uint8_t filenum, uint64_t filesize, const char *filename, uint16_t filename_len) { @@ -253,13 +419,17 @@ static void friendlist_onGroupInvite(ToxWindow *self, Tox *m, int32_t num, const } } -static void select_friend(ToxWindow *self, Tox *m, wint_t key) +/* move friendlist/blocklist cursor up and down */ +static void select_friend(ToxWindow *self, wint_t key, int *selected, int count) { + if (count <= 0) + return; + if (key == KEY_UP) { - if (--num_selected < 0) - num_selected = num_friends - 1; + if (--(*selected) < 0) + *selected = count - 1; } else if (key == KEY_DOWN) { - num_selected = (num_selected + 1) % num_friends; + *selected = (*selected + 1) % count; } } @@ -282,7 +452,6 @@ static void delete_friend(Tox *m, int32_t f_num) if (num_friends && num_selected == num_friends) --num_selected; - sort_friendlist_index(); store_data(m, DATA_FILE); } @@ -294,11 +463,20 @@ static void del_friend_activate(ToxWindow *self, Tox *m, int32_t f_num) pendingdelete.num = f_num; } +static void remove_friend_blocked(int32_t bnum); + /* deactivates delete friend popup and deletes friend if instructed */ static void del_friend_deactivate(ToxWindow *self, Tox *m, wint_t key) { - if (key == 'y') - delete_friend(m, pendingdelete.num); + if (key == 'y') { + if (blocklist_view == 0) { + delete_friend(m, pendingdelete.num); + sort_friendlist_index(); + } else { + remove_friend_blocked(pendingdelete.num); + sort_blocklist_index(); + } + } delwin(pendingdelete.popup); memset(&pendingdelete, 0, sizeof(pendingdelete)); @@ -318,19 +496,99 @@ static void draw_popup(void) wmove(pendingdelete.popup, 1, 1); wprintw(pendingdelete.popup, "Delete contact "); wattron(pendingdelete.popup, A_BOLD); - wprintw(pendingdelete.popup, "%s", friends[pendingdelete.num].name); + + if (blocklist_view == 0) + wprintw(pendingdelete.popup, "%s", friends[pendingdelete.num].name); + else + wprintw(pendingdelete.popup, "%s", Blocked_Contacts.list[pendingdelete.num].name); + wattroff(pendingdelete.popup, A_BOLD); wprintw(pendingdelete.popup, "? y/n"); wrefresh(pendingdelete.popup); } -static void friendlist_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr) +/* Deletes friend from friendlist, puts in blocklist */ +void block_friend(Tox *m, int32_t fnum) { - if (num_friends == 0) + if (Blocked_Contacts.max_index >= MAX_FRIENDS_NUM || num_friends <= 0) return; - int f = friendlist_index[num_selected]; + int i; + + for (i = 0; i <= Blocked_Contacts.max_index; ++i) { + if (Blocked_Contacts.list[i].active) + continue; + + Blocked_Contacts.list[i].active = true; + Blocked_Contacts.list[i].num = i; + Blocked_Contacts.list[i].namelength = friends[fnum].namelength; + memcpy(Blocked_Contacts.list[i].pub_key, friends[fnum].pub_key, TOX_CLIENT_ID_SIZE); + memcpy(Blocked_Contacts.list[i].name, friends[fnum].name, friends[fnum].namelength + 1); + + ++Blocked_Contacts.num_blocked; + + if (i == Blocked_Contacts.max_index) + ++Blocked_Contacts.max_index; + + delete_friend(m, fnum); + save_blocklist(BLOCK_FILE); + sort_blocklist_index(); + sort_friendlist_index(); + + return; + } +} + +/* permanently deletes friend from blocked list */ +static void remove_friend_blocked(int32_t bnum) +{ + memset(&Blocked_Contacts.list[bnum], 0, sizeof(BlockedFriend)); + + int i; + + for (i = Blocked_Contacts.max_index; i >= 0; --i) { + if (Blocked_Contacts.list[i - 1].active) + break; + } + + --Blocked_Contacts.num_blocked; + Blocked_Contacts.max_index = i; + save_blocklist(BLOCK_FILE); + + if (Blocked_Contacts.num_blocked && Blocked_Contacts.num_selected == Blocked_Contacts.num_blocked) + --Blocked_Contacts.num_selected; +} + +/* removes friend from blocklist, puts back in friendlist */ +static void unblock_friend(Tox *m, int32_t bnum) +{ + if (Blocked_Contacts.num_blocked <= 0) + return; + + int32_t friendnum = tox_add_friend_norequest(m, (uint8_t *) Blocked_Contacts.list[bnum].pub_key); + + if (friendnum == -1) { + line_info_add(prompt, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to unblock friend"); + return; + } + + friendlist_add_blocked(m, friendnum, bnum); + remove_friend_blocked(bnum); + sort_blocklist_index(); + sort_friendlist_index(); +} + +static void friendlist_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr) +{ + if (!blocklist_view && !num_friends && (key != KEY_RIGHT && key != KEY_LEFT)) + return; + + if (blocklist_view && !Blocked_Contacts.num_blocked && (key != KEY_RIGHT && key != KEY_LEFT)) + return; + + int f = blocklist_view == 1 ? Blocked_Contacts.index[Blocked_Contacts.num_selected] + : friendlist_index[num_selected]; /* lock screen and force decision on deletion popup */ if (pendingdelete.active) { @@ -340,8 +598,14 @@ static void friendlist_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr) return; } - if (key != ltr) { - if (key == '\n') { + if (key == ltr) + return; + + switch (key) { + case '\n': + if (blocklist_view) + break; + /* Jump to chat window if already open */ if (friends[f].chatwin != -1) { set_active_window(friends[f].chatwin); @@ -351,19 +615,106 @@ static void friendlist_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr) } else { const char *msg = "* Warning: Too many windows are open."; line_info_add(prompt, NULL, NULL, NULL, SYS_MSG, 0, RED, msg); - notify(prompt, error, NT_WNDALERT_1); } - } else if (key == KEY_DC) { + + break; + + case KEY_DC: del_friend_activate(self, m, f); - } else { - select_friend(self, m, key); - } + break; + + case 'b': + if (!blocklist_view) + block_friend(m, f); + else + unblock_friend(m, f); + break; + + case KEY_RIGHT: + case KEY_LEFT: + blocklist_view ^= 1; + break; + + default: + if (blocklist_view == 0) + select_friend(self, key, &num_selected, num_friends); + else + select_friend(self, key, &Blocked_Contacts.num_selected, Blocked_Contacts.num_blocked); + break; } } #define FLIST_OFST 6 /* Accounts for space at top and bottom */ +static void blocklist_onDraw(ToxWindow *self, Tox *m, int y2, int x2) +{ + wattron(self->window, A_BOLD); + wprintw(self->window, " Blocked: "); + wattroff(self->window, A_BOLD); + wprintw(self->window, "%d\n\n", Blocked_Contacts.num_blocked); + + if ((y2 - FLIST_OFST) <= 0) + return; + + int selected_num = 0; + + /* Determine which portion of friendlist to draw based on current position */ + int page = Blocked_Contacts.num_selected / (y2 - FLIST_OFST); + int start = (y2 - FLIST_OFST) * page; + int end = y2 - FLIST_OFST + start; + + int i; + + for (i = start; i < Blocked_Contacts.num_blocked && i < end; ++i) { + int f = Blocked_Contacts.index[i]; + bool f_selected = false; + + if (i == Blocked_Contacts.num_selected) { + wattron(self->window, A_BOLD); + wprintw(self->window, " > "); + wattroff(self->window, A_BOLD); + selected_num = f; + f_selected = true; + } else { + wprintw(self->window, " "); + } + + wattron(self->window, COLOR_PAIR(RED)); + wprintw(self->window, "x"); + wattroff(self->window, COLOR_PAIR(RED)); + + if (f_selected) + wattron(self->window, COLOR_PAIR(BLUE)); + + wattron(self->window, A_BOLD); + wprintw(self->window, " %s\n", Blocked_Contacts.list[f].name); + wattroff(self->window, A_BOLD); + + if (f_selected) + wattroff(self->window, COLOR_PAIR(BLUE)); + } + + wprintw(self->window, "\n"); + self->x = x2; + + if (Blocked_Contacts.num_blocked) { + wmove(self->window, y2 - 1, 1); + + wattron(self->window, A_BOLD); + wprintw(self->window, "ID: "); + wattroff(self->window, A_BOLD); + + int i; + + for (i = 0; i < TOX_CLIENT_ID_SIZE; ++i) + wprintw(self->window, "%02X", Blocked_Contacts.list[selected_num].pub_key[i] & 0xff); + } + + wrefresh(self->window); + draw_popup(); +} + static void friendlist_onDraw(ToxWindow *self, Tox *m) { curs_set(0); @@ -371,9 +722,6 @@ static void friendlist_onDraw(ToxWindow *self, Tox *m) int x2, y2; getmaxyx(self->window, y2, x2); - uint64_t cur_time = get_unix_time(); - struct tm cur_loc_tm = *localtime((const time_t*)&cur_time); - bool fix_statuses = x2 != self->x; /* true if window max x value has changed */ wattron(self->window, COLOR_PAIR(CYAN)); @@ -385,9 +733,22 @@ static void friendlist_onDraw(ToxWindow *self, Tox *m) wattron(self->window, A_BOLD); wprintw(self->window, " Delete "); wattroff(self->window, A_BOLD); - wprintw(self->window, "key.\n\n"); + wprintw(self->window, "key.\n"); + wprintw(self->window, " Block a contact with the"); + wattron(self->window, A_BOLD); + wprintw(self->window, " b "); + wattroff(self->window, A_BOLD); + wprintw(self->window, "key, toggle blocklist with the."); wattroff(self->window, COLOR_PAIR(CYAN)); + if (blocklist_view == 1) { + blocklist_onDraw(self, m, y2, x2); + return; + } + + uint64_t cur_time = get_unix_time(); + struct tm cur_loc_tm = *localtime((const time_t *) &cur_time); + pthread_mutex_lock(&Winthread.lock); int nf = tox_get_num_online_friends(m); pthread_mutex_unlock(&Winthread.lock); diff --git a/src/friendlist.h b/src/friendlist.h index b4f6f7c..2a2b1dd 100644 --- a/src/friendlist.h +++ b/src/friendlist.h @@ -64,9 +64,18 @@ typedef struct { struct FileReceiver file_receiver; } ToxicFriend; +typedef struct { + char name[TOXIC_MAX_NAME_LENGTH]; + int namelength; + char pub_key[TOX_CLIENT_ID_SIZE]; + int32_t num; + bool active; +} BlockedFriend; + ToxWindow new_friendlist(void); void disable_chatwin(int32_t f_num); int get_friendnum(uint8_t *name); +int load_blocklist(char *data); void friendlist_onFriendAdded(ToxWindow *self, Tox *m, int32_t num, bool sort); diff --git a/src/toxic.c b/src/toxic.c index 22df49a..88f35c9 100644 --- a/src/toxic.c +++ b/src/toxic.c @@ -67,19 +67,13 @@ ToxAv *av; /* Export for use in Callbacks */ char *DATA_FILE = NULL; +char *BLOCK_FILE = NULL; ToxWindow *prompt = NULL; #define AUTOSAVE_FREQ 60 -struct arg_opts { - int ignore_data_file; - int use_ipv4; - int default_locale; - char config_path[MAX_STR_SIZE]; - char nodes_path[MAX_STR_SIZE]; -} arg_opts; - struct _Winthread Winthread; +struct arg_opts arg_opts; struct user_settings *user_settings_ = NULL; static void catch_SIGINT(int sig) @@ -371,15 +365,17 @@ static void load_friendlist(Tox *m) for (i = 0; i < numfriends; ++i) friendlist_onFriendAdded(NULL, m, i, false); + + sort_friendlist_index(); } /* * Store Messenger to given location * Return 0 stored successfully or ignoring data file - * Return 1 file path is NULL - * Return 2 malloc failed - * Return 3 opening path failed - * Return 4 fwrite failed + * Return -1 file path is NULL + * Return -2 malloc failed + * Return -3 opening path failed + * Return -4 fwrite failed */ int store_data(Tox *m, char *path) { @@ -387,13 +383,13 @@ int store_data(Tox *m, char *path) return 0; if (path == NULL) - return 1; + return -1; int len = tox_size(m); char *buf = malloc(len); if (buf == NULL) - return 2; + return -2; tox_save(m, (uint8_t *) buf); @@ -401,13 +397,13 @@ int store_data(Tox *m, char *path) if (fd == NULL) { free(buf); - return 3; + return -3; } if (fwrite(buf, len, 1, fd) != 1) { free(buf); fclose(fd); - return 4; + return -4; } free(buf); @@ -442,6 +438,7 @@ static void load_data(Tox *m, char *path) tox_load(m, (uint8_t *) buf, len); load_friendlist(m); + load_blocklist(BLOCK_FILE); free(buf); fclose(fd); @@ -526,10 +523,12 @@ static void parse_args(int argc, char *argv[]) switch (opt) { case 'f': DATA_FILE = strdup(optarg); + BLOCK_FILE = strdup(optarg); - if (DATA_FILE == NULL) + if (DATA_FILE == NULL || BLOCK_FILE == NULL) exit_toxic_err("failed in parse_args", FATALERR_MEMORY); + strcat(BLOCK_FILE, "-blocklist"); break; case 'x': @@ -560,39 +559,48 @@ static void parse_args(int argc, char *argv[]) } } -int main(int argc, char *argv[]) +#define DATANAME "data" +#define BLOCKNAME "data-blocklist" +static int init_data_files(void) { char *user_config_dir = get_user_config_dir(); - int config_err = 0; - - parse_args(argc, argv); - - /* Make sure all written files are read/writeable only by the current user. */ - umask(S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); - - signal(SIGINT, catch_SIGINT); - - config_err = create_user_config_dir(user_config_dir); + int config_err = create_user_config_dir(user_config_dir); if (DATA_FILE == NULL ) { if (config_err) { - DATA_FILE = strdup("data"); + DATA_FILE = strdup(DATANAME); + BLOCK_FILE = strdup(BLOCKNAME); - if (DATA_FILE == NULL) - exit_toxic_err("failed in main", FATALERR_MEMORY); + if (DATA_FILE == NULL || BLOCK_FILE == NULL) + exit_toxic_err("failed in load_data_structures", FATALERR_MEMORY); } else { - DATA_FILE = malloc(strlen(user_config_dir) + strlen(CONFIGDIR) + strlen("data") + 1); + DATA_FILE = malloc(strlen(user_config_dir) + strlen(CONFIGDIR) + strlen(DATANAME) + 1); + BLOCK_FILE = malloc(strlen(user_config_dir) + strlen(CONFIGDIR) + strlen(BLOCKNAME) + 1); - if (DATA_FILE == NULL) - exit_toxic_err("failed in main", FATALERR_MEMORY); + if (DATA_FILE == NULL || BLOCK_FILE == NULL) + exit_toxic_err("failed in load_data_structures", FATALERR_MEMORY); strcpy(DATA_FILE, user_config_dir); strcat(DATA_FILE, CONFIGDIR); - strcat(DATA_FILE, "data"); + strcat(DATA_FILE, DATANAME); + + strcpy(BLOCK_FILE, user_config_dir); + strcat(BLOCK_FILE, CONFIGDIR); + strcat(BLOCK_FILE, BLOCKNAME); } } free(user_config_dir); + return config_err; +} + +int main(int argc, char *argv[]) +{ + parse_args(argc, argv); + /* Make sure all written files are read/writeable only by the current user. */ + umask(S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); + signal(SIGINT, catch_SIGINT); + int config_err = init_data_files(); /* init user_settings struct and load settings from conf file */ user_settings_ = calloc(1, sizeof(struct user_settings)); @@ -644,7 +652,7 @@ int main(int argc, char *argv[]) const char *msg; if (config_err) { - msg = "Unable to determine configuration directory. Defaulting to 'data' for a keyfile..."; + msg = "Unable to determine configuration directory. Defaulting to 'data' for data file..."; line_info_add(prompt, NULL, NULL, NULL, SYS_MSG, 0, 0, msg); } @@ -653,8 +661,6 @@ int main(int argc, char *argv[]) line_info_add(prompt, NULL, NULL, NULL, SYS_MSG, 0, 0, msg); } - sort_friendlist_index(); - uint64_t last_save = (uint64_t) time(NULL); while (true) { diff --git a/src/windows.h b/src/windows.h index d56fa43..7522431 100644 --- a/src/windows.h +++ b/src/windows.h @@ -71,6 +71,14 @@ struct _Winthread { bool flag_resize; }; +struct arg_opts { + int ignore_data_file; + int use_ipv4; + int default_locale; + char config_path[MAX_STR_SIZE]; + char nodes_path[MAX_STR_SIZE]; +}; + typedef struct ToxWindow ToxWindow; typedef struct StatusBar StatusBar; typedef struct PromptBuf PromptBuf; From 0254596c73bb548953074bd92e98cbe7b96815ee Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Thu, 31 Jul 2014 13:49:15 -0400 Subject: [PATCH 2/4] add help menu for friendlist --- src/friendlist.c | 101 +++++++++++++++++++++++++++-------------------- src/help.c | 43 ++++++++++++++++++-- src/help.h | 1 + 3 files changed, 99 insertions(+), 46 deletions(-) diff --git a/src/friendlist.c b/src/friendlist.c index e8af47a..5962c6c 100644 --- a/src/friendlist.c +++ b/src/friendlist.c @@ -35,6 +35,7 @@ #include "line_info.h" #include "settings.h" #include "notify.h" +#include "help.h" #ifdef _AUDIO #include "audio_call.h" @@ -420,16 +421,16 @@ static void friendlist_onGroupInvite(ToxWindow *self, Tox *m, int32_t num, const } /* move friendlist/blocklist cursor up and down */ -static void select_friend(ToxWindow *self, wint_t key, int *selected, int count) +static void select_friend(ToxWindow *self, wint_t key, int *selected, int num) { - if (count <= 0) + if (num <= 0) return; if (key == KEY_UP) { if (--(*selected) < 0) - *selected = count - 1; + *selected = num - 1; } else if (key == KEY_DOWN) { - *selected = (*selected + 1) % count; + *selected = (*selected + 1) % num; } } @@ -463,7 +464,7 @@ static void del_friend_activate(ToxWindow *self, Tox *m, int32_t f_num) pendingdelete.num = f_num; } -static void remove_friend_blocked(int32_t bnum); +static void delete_blocked_friend(int32_t bnum); /* deactivates delete friend popup and deletes friend if instructed */ static void del_friend_deactivate(ToxWindow *self, Tox *m, wint_t key) @@ -473,7 +474,7 @@ static void del_friend_deactivate(ToxWindow *self, Tox *m, wint_t key) delete_friend(m, pendingdelete.num); sort_friendlist_index(); } else { - remove_friend_blocked(pendingdelete.num); + delete_blocked_friend(pendingdelete.num); sort_blocklist_index(); } } @@ -484,7 +485,7 @@ static void del_friend_deactivate(ToxWindow *self, Tox *m, wint_t key) refresh(); } -static void draw_popup(void) +static void draw_del_popup(void) { if (!pendingdelete.active) return; @@ -508,7 +509,27 @@ static void draw_popup(void) wrefresh(pendingdelete.popup); } -/* Deletes friend from friendlist, puts in blocklist */ +/* deletes contact from blocked list */ +static void delete_blocked_friend(int32_t bnum) +{ + memset(&Blocked_Contacts.list[bnum], 0, sizeof(BlockedFriend)); + + int i; + + for (i = Blocked_Contacts.max_index; i >= 0; --i) { + if (Blocked_Contacts.list[i - 1].active) + break; + } + + --Blocked_Contacts.num_blocked; + Blocked_Contacts.max_index = i; + save_blocklist(BLOCK_FILE); + + if (Blocked_Contacts.num_blocked && Blocked_Contacts.num_selected == Blocked_Contacts.num_blocked) + --Blocked_Contacts.num_selected; +} + +/* deletes contact from friendlist and puts in blocklist */ void block_friend(Tox *m, int32_t fnum) { if (Blocked_Contacts.max_index >= MAX_FRIENDS_NUM || num_friends <= 0) @@ -540,26 +561,6 @@ void block_friend(Tox *m, int32_t fnum) } } -/* permanently deletes friend from blocked list */ -static void remove_friend_blocked(int32_t bnum) -{ - memset(&Blocked_Contacts.list[bnum], 0, sizeof(BlockedFriend)); - - int i; - - for (i = Blocked_Contacts.max_index; i >= 0; --i) { - if (Blocked_Contacts.list[i - 1].active) - break; - } - - --Blocked_Contacts.num_blocked; - Blocked_Contacts.max_index = i; - save_blocklist(BLOCK_FILE); - - if (Blocked_Contacts.num_blocked && Blocked_Contacts.num_selected == Blocked_Contacts.num_blocked) - --Blocked_Contacts.num_selected; -} - /* removes friend from blocklist, puts back in friendlist */ static void unblock_friend(Tox *m, int32_t bnum) { @@ -574,13 +575,24 @@ static void unblock_friend(Tox *m, int32_t bnum) } friendlist_add_blocked(m, friendnum, bnum); - remove_friend_blocked(bnum); + delete_blocked_friend(bnum); sort_blocklist_index(); sort_friendlist_index(); } static void friendlist_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr) { + + if (self->help->active) { + help_onKey(self, key); + return; + } + + if (key == 'h') { + help_init_menu(self); + return; + } + if (!blocklist_view && !num_friends && (key != KEY_RIGHT && key != KEY_LEFT)) return; @@ -712,7 +724,10 @@ static void blocklist_onDraw(ToxWindow *self, Tox *m, int y2, int x2) } wrefresh(self->window); - draw_popup(); + draw_del_popup(); + + if (self->help->active) + help_onDraw(self); } static void friendlist_onDraw(ToxWindow *self, Tox *m) @@ -725,20 +740,11 @@ static void friendlist_onDraw(ToxWindow *self, Tox *m) bool fix_statuses = x2 != self->x; /* true if window max x value has changed */ wattron(self->window, COLOR_PAIR(CYAN)); - wprintw(self->window, " Open a chat window with the"); + wprintw(self->window, " Press the"); wattron(self->window, A_BOLD); - wprintw(self->window, " Enter "); + wprintw(self->window, " H "); wattroff(self->window, A_BOLD); - wprintw(self->window, "key. Delete a contact with the"); - wattron(self->window, A_BOLD); - wprintw(self->window, " Delete "); - wattroff(self->window, A_BOLD); - wprintw(self->window, "key.\n"); - wprintw(self->window, " Block a contact with the"); - wattron(self->window, A_BOLD); - wprintw(self->window, " b "); - wattroff(self->window, A_BOLD); - wprintw(self->window, "key, toggle blocklist with the."); + wprintw(self->window, "key for help\n\n"); wattroff(self->window, COLOR_PAIR(CYAN)); if (blocklist_view == 1) { @@ -902,7 +908,10 @@ static void friendlist_onDraw(ToxWindow *self, Tox *m) } wrefresh(self->window); - draw_popup(); + draw_del_popup(); + + if (self->help->active) + help_onDraw(self); } void disable_chatwin(int32_t f_num) @@ -982,7 +991,13 @@ ToxWindow new_friendlist(void) #ifdef _SOUND_NOTIFY ret.active_sound = -1; #endif /* _SOUND_NOTIFY */ + + Help *help = calloc(1, sizeof(Help)); + + if (help == NULL) + exit_toxic_err("failed in new_friendlist", FATALERR_MEMORY); + ret.help = help; strcpy(ret.name, "contacts"); return ret; } diff --git a/src/help.c b/src/help.c index ba8603c..e9b3f33 100644 --- a/src/help.c +++ b/src/help.c @@ -27,7 +27,7 @@ #include "help.h" #include "misc_tools.h" -#define HELP_MENU_HEIGHT 7 +#define HELP_MENU_HEIGHT 8 #define HELP_MENU_WIDTH 26 void help_init_menu(ToxWindow *self) @@ -86,6 +86,11 @@ static void help_draw_menu(ToxWindow *self) wattroff(win, A_BOLD | COLOR_PAIR(BLUE)); wprintw(win, "hat commands\n"); + wattron(win, A_BOLD | COLOR_PAIR(BLUE)); + wprintw(win, " F"); + wattroff(win, A_BOLD | COLOR_PAIR(BLUE)); + wprintw(win, "riendlist controls\n"); + wattron(win, A_BOLD | COLOR_PAIR(BLUE)); wprintw(win, " K"); wattroff(win, A_BOLD | COLOR_PAIR(BLUE)); @@ -209,7 +214,30 @@ static void help_draw_keys(ToxWindow *self) wprintw(win, " Page Up and Page Down : Scroll window history one line\n"); wprintw(win, " Ctrl+F and Ctrl+V : Scroll window history half a page\n"); wprintw(win, " Ctrl+H : Move to the bottom of window history\n"); - wprintw(win, " Ctrl+[ and Ctrl+] : Scroll peer list in groupchats\n"); + wprintw(win, " Ctrl+[ and Ctrl+] : Scroll peer list in groupchats\n\n"); + wprintw(win, " (Note: Custom keybindings override these defaults.)\n\n"); + + help_draw_bottom_menu(win); + + box(win, ACS_VLINE, ACS_HLINE); + wrefresh(win); +} + +static void help_draw_contacts(ToxWindow *self) +{ + WINDOW *win = self->help->win; + + wmove(win, 1, 1); + + wattron(win, A_BOLD | COLOR_PAIR(RED)); + wprintw(win, "Friendlist controls:\n"); + wattroff(win, A_BOLD | COLOR_PAIR(RED)); + + wprintw(win, " Up and Down arrows : Scroll through list\n"); + wprintw(win, " Right and Left arrows : Switch between friendlist and blocked list\n"); + wprintw(win, " Enter : Open a chat window with selected contact\n"); + wprintw(win, " Delete : Permanently delete a contact\n"); + wprintw(win, " B : Block or unblock a contact\n"); help_draw_bottom_menu(win); @@ -243,8 +271,13 @@ void help_onKey(ToxWindow *self, wint_t key) self->help->type = HELP_GLOBAL; break; - case 'k': + case 'f': help_init_window(self, 10, 80); + self->help->type = HELP_CONTACTS; + break; + + case 'k': + help_init_window(self, 12, 80); self->help->type = HELP_KEYS; break; @@ -276,6 +309,10 @@ void help_onDraw(ToxWindow *self) help_draw_keys(self); break; + case HELP_CONTACTS: + help_draw_contacts(self); + break; + case HELP_GROUP: break; } diff --git a/src/help.h b/src/help.h index d4583c4..d46e703 100644 --- a/src/help.h +++ b/src/help.h @@ -32,6 +32,7 @@ typedef enum { HELP_CHAT, HELP_GROUP, HELP_KEYS, + HELP_CONTACTS, } HELP_TYPES; void help_onDraw(ToxWindow *self); From 5da789cc37f5f054b588373e41811c34d0e1b28c Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Thu, 31 Jul 2014 14:53:02 -0400 Subject: [PATCH 3/4] save last online data in blocked list --- src/friendlist.c | 16 +++++++++++++++- src/friendlist.h | 1 + src/misc_tools.c | 15 +++++++++++++++ src/misc_tools.h | 6 ++++++ 4 files changed, 37 insertions(+), 1 deletion(-) diff --git a/src/friendlist.c b/src/friendlist.c index 5962c6c..90f5b9a 100644 --- a/src/friendlist.c +++ b/src/friendlist.c @@ -98,6 +98,12 @@ static int save_blocklist(char *path) tmp.namelength = Blocked_Contacts.list[i].namelength; memcpy(tmp.name, Blocked_Contacts.list[i].name, Blocked_Contacts.list[i].namelength + 1); memcpy(tmp.pub_key, Blocked_Contacts.list[i].pub_key, TOX_CLIENT_ID_SIZE); + + uint8_t lastonline[sizeof(uint64_t)]; + memcpy(lastonline, &Blocked_Contacts.list[i].last_on, sizeof(uint64_t)); + host_to_net(lastonline, sizeof(uint64_t)); + memcpy(&tmp.last_on, lastonline, sizeof(uint64_t)); + memcpy(data + count * sizeof(BlockedFriend), &tmp, sizeof(BlockedFriend)); ++count; } @@ -166,6 +172,12 @@ int load_blocklist(char *path) Blocked_Contacts.list[i].namelength = tmp.namelength; memcpy(Blocked_Contacts.list[i].name, tmp.name, tmp.namelength + 1); memcpy(Blocked_Contacts.list[i].pub_key, tmp.pub_key, TOX_CLIENT_ID_SIZE); + + uint8_t lastonline[sizeof(uint64_t)]; + memcpy(lastonline, &tmp.last_on, sizeof(uint64_t)); + net_to_host(lastonline, sizeof(uint64_t)); + memcpy(&Blocked_Contacts.list[i].last_on, lastonline, sizeof(uint64_t)); + ++Blocked_Contacts.num_blocked; } @@ -360,6 +372,7 @@ static void friendlist_add_blocked(Tox *m, int32_t fnum, int32_t bnum) friends[i].status = TOX_USERSTATUS_NONE; friends[i].logging_on = (bool) user_settings_->autolog == AUTOLOG_ON; friends[i].namelength = Blocked_Contacts.list[bnum].namelength; + update_friend_last_online(i, Blocked_Contacts.list[bnum].last_on); memcpy(friends[i].name, Blocked_Contacts.list[bnum].name, friends[i].namelength + 1); memcpy(friends[i].pub_key, Blocked_Contacts.list[bnum].pub_key, TOX_CLIENT_ID_SIZE); @@ -516,7 +529,7 @@ static void delete_blocked_friend(int32_t bnum) int i; - for (i = Blocked_Contacts.max_index; i >= 0; --i) { + for (i = Blocked_Contacts.max_index; i > 0; --i) { if (Blocked_Contacts.list[i - 1].active) break; } @@ -544,6 +557,7 @@ void block_friend(Tox *m, int32_t fnum) Blocked_Contacts.list[i].active = true; Blocked_Contacts.list[i].num = i; Blocked_Contacts.list[i].namelength = friends[fnum].namelength; + Blocked_Contacts.list[i].last_on = friends[fnum].last_online.last_on; memcpy(Blocked_Contacts.list[i].pub_key, friends[fnum].pub_key, TOX_CLIENT_ID_SIZE); memcpy(Blocked_Contacts.list[i].name, friends[fnum].name, friends[fnum].namelength + 1); diff --git a/src/friendlist.h b/src/friendlist.h index 2a2b1dd..24cf943 100644 --- a/src/friendlist.h +++ b/src/friendlist.h @@ -70,6 +70,7 @@ typedef struct { char pub_key[TOX_CLIENT_ID_SIZE]; int32_t num; bool active; + uint64_t last_on; } BlockedFriend; ToxWindow new_friendlist(void); diff --git a/src/misc_tools.c b/src/misc_tools.c index a0315c3..c26c6a0 100644 --- a/src/misc_tools.c +++ b/src/misc_tools.c @@ -37,6 +37,21 @@ extern struct user_settings *user_settings_; static uint64_t current_unix_time; +void host_to_net(uint8_t *num, uint16_t numbytes) +{ +#ifndef WORDS_BIGENDIAN + uint32_t i; + uint8_t buff[numbytes]; + + for (i = 0; i < numbytes; ++i) { + buff[i] = num[numbytes - i - 1]; + } + + memcpy(num, buff, numbytes); +#endif + return; +} + void update_unix_time(void) { current_unix_time = (uint64_t) time(NULL); diff --git a/src/misc_tools.h b/src/misc_tools.h index bea928b..1e92f8c 100644 --- a/src/misc_tools.h +++ b/src/misc_tools.h @@ -33,6 +33,12 @@ #define MAX(x, y) (((x) > (y)) ? (x) : (y)) #endif +#ifndef net_to_host +#define net_to_host(x, y) host_to_net(x, y) +#endif + +void host_to_net(uint8_t *num, uint16_t numbytes); + /* convert a hex string to binary */ char *hex_string_to_bin(const char *hex_string); From af68fa7ee081f64de9b297b2e1ae81e6b66dc174 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Thu, 31 Jul 2014 15:02:19 -0400 Subject: [PATCH 4/4] endian correctness --- src/friendlist.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/friendlist.c b/src/friendlist.c index 90f5b9a..7ccc0c0 100644 --- a/src/friendlist.c +++ b/src/friendlist.c @@ -24,6 +24,7 @@ #include #include #include +#include #include @@ -95,7 +96,7 @@ static int save_blocklist(char *path) if (Blocked_Contacts.list[i].active) { BlockedFriend tmp; memset(&tmp, 0, sizeof(BlockedFriend)); - tmp.namelength = Blocked_Contacts.list[i].namelength; + tmp.namelength = htons(Blocked_Contacts.list[i].namelength); memcpy(tmp.name, Blocked_Contacts.list[i].name, Blocked_Contacts.list[i].namelength + 1); memcpy(tmp.pub_key, Blocked_Contacts.list[i].pub_key, TOX_CLIENT_ID_SIZE); @@ -169,8 +170,8 @@ int load_blocklist(char *path) memcpy(&tmp, data + i * sizeof(BlockedFriend), sizeof(BlockedFriend)); Blocked_Contacts.list[i].active = true; Blocked_Contacts.list[i].num = i; - Blocked_Contacts.list[i].namelength = tmp.namelength; - memcpy(Blocked_Contacts.list[i].name, tmp.name, tmp.namelength + 1); + Blocked_Contacts.list[i].namelength = ntohs(tmp.namelength); + memcpy(Blocked_Contacts.list[i].name, tmp.name, Blocked_Contacts.list[i].namelength + 1); memcpy(Blocked_Contacts.list[i].pub_key, tmp.pub_key, TOX_CLIENT_ID_SIZE); uint8_t lastonline[sizeof(uint64_t)];