From 26dda8dbf919ac9e31fab5639198ba10b9624f14 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Sun, 4 Jan 2015 01:56:37 -0500 Subject: [PATCH 01/45] implement new groupchats --- src/chat.c | 96 +++------ src/chat_commands.c | 67 +------ src/chat_commands.h | 2 - src/execute.c | 8 +- src/execute.h | 2 +- src/friendlist.c | 30 --- src/friendlist.h | 8 - src/global_commands.c | 88 ++++++-- src/global_commands.h | 1 + src/group_commands.c | 51 +++-- src/group_commands.h | 3 +- src/groupchat.c | 453 ++++++++++++++++++++++-------------------- src/groupchat.h | 13 +- src/help.c | 28 +-- src/line_info.c | 2 +- src/line_info.h | 2 +- src/misc_tools.c | 16 +- src/toxic.c | 50 +++-- src/toxic.h | 17 +- src/windows.c | 119 +++++++++-- src/windows.h | 23 ++- 21 files changed, 563 insertions(+), 516 deletions(-) diff --git a/src/chat.c b/src/chat.c index 88ae56a..a47aefc 100644 --- a/src/chat.c +++ b/src/chat.c @@ -64,9 +64,9 @@ static void kill_infobox(ToxWindow *self); #endif /* AUDIO */ #ifdef AUDIO -#define AC_NUM_CHAT_COMMANDS 27 +#define AC_NUM_CHAT_COMMANDS 26 #else -#define AC_NUM_CHAT_COMMANDS 20 +#define AC_NUM_CHAT_COMMANDS 19 #endif /* AUDIO */ /* Array of chat command names used for tab completion. */ @@ -81,7 +81,6 @@ static const char chat_cmd_list[AC_NUM_CHAT_COMMANDS][MAX_CMDNAME_SIZE] = { { "/exit" }, { "/group" }, { "/help" }, - { "/invite" }, { "/join" }, { "/log" }, { "/myid" }, @@ -160,12 +159,12 @@ static void chat_onMessage(ToxWindow *self, Tox *m, int32_t num, const char *msg line_info_add(self, timefrmt, nick, NULL, IN_MSG, 0, 0, "%s", msg); write_to_log(msg, nick, ctx->log, false); - - if (self->active_box != -1) - box_notify2(self, generic_message, NT_WNDALERT_1 | NT_NOFOCUS, self->active_box, "%s", msg); - else + + if (self->active_box != -1) + box_notify2(self, generic_message, NT_WNDALERT_1 | NT_NOFOCUS, self->active_box, "%s", msg); + else box_notify(self, generic_message, NT_WNDALERT_1 | NT_NOFOCUS, &self->active_box, nick, "%s", msg); - + } static void chat_resume_file_transfers(Tox *m, int fnum); @@ -188,7 +187,7 @@ static void chat_onConnectionChange(ToxWindow *self, Tox *m, int32_t num, uint8_ if (status == 1) { /* Friend goes online */ statusbar->is_online = true; - Friends.list[num].is_typing = user_settings->show_typing_other == SHOW_TYPING_ON + Friends.list[num].is_typing = user_settings->show_typing_other == SHOW_TYPING_ON ? tox_get_is_typing(m, num) : 0; chat_resume_file_transfers(m, num); @@ -233,7 +232,7 @@ static void chat_onAction(ToxWindow *self, Tox *m, int32_t num, const char *acti line_info_add(self, timefrmt, nick, NULL, IN_ACTION, 0, 0, "%s", action); write_to_log(action, nick, ctx->log, true); - + if (self->active_box != -1) box_notify2(self, generic_message, NT_WNDALERT_1 | NT_NOFOCUS, self->active_box, "* %s %s", nick, action ); else @@ -352,10 +351,10 @@ static void chat_onFileSendRequest(ToxWindow *self, Tox *m, int32_t num, uint8_t strcpy(Friends.list[num].file_receiver[filenum].filename, filename); if (self->active_box != -1) - box_notify2(self, transfer_pending, NT_WNDALERT_0 | NT_NOFOCUS, self->active_box, + box_notify2(self, transfer_pending, NT_WNDALERT_0 | NT_NOFOCUS, self->active_box, "Incoming file: %s", filename ); else - box_notify(self, transfer_pending, NT_WNDALERT_0 | NT_NOFOCUS, &self->active_box, self->name, + box_notify(self, transfer_pending, NT_WNDALERT_0 | NT_NOFOCUS, &self->active_box, self->name, "Incoming file: %s", filename ); } @@ -478,7 +477,7 @@ static void chat_onFileControl(ToxWindow *self, Tox *m, int32_t num, uint8_t rec snprintf(msg, sizeof(msg), "File transfer for '%s' failed.", filename); if (self->active_box != -1) - box_notify2(self, error, NT_NOFOCUS | NT_WNDALERT_2, + box_notify2(self, error, NT_NOFOCUS | NT_WNDALERT_2, self->active_box, "File transfer for '%s' failed!", filename ); else box_notify(self, error, NT_NOFOCUS | NT_WNDALERT_2, &self->active_box, @@ -507,7 +506,7 @@ static void chat_onFileControl(ToxWindow *self, Tox *m, int32_t num, uint8_t rec if (self->active_box != -1) box_notify2(self, transfer_completed, NT_NOFOCUS | NT_WNDALERT_2, self->active_box, "%s", msg); else - box_notify(self, transfer_completed, NT_NOFOCUS | NT_WNDALERT_2, &self->active_box, + box_notify(self, transfer_completed, NT_NOFOCUS | NT_WNDALERT_2, &self->active_box, self->name, "%s", msg); break; @@ -561,40 +560,6 @@ static void chat_onFileData(ToxWindow *self, Tox *m, int32_t num, uint8_t filenu Friends.list[num].file_receiver[filenum].bytes_recv += length; } -static void chat_onGroupInvite(ToxWindow *self, Tox *m, int32_t friendnumber, uint8_t type, const char *group_pub_key, - uint16_t length) -{ - if (self->num != friendnumber) - return; - - if (Friends.list[friendnumber].group_invite.key != NULL) - free(Friends.list[friendnumber].group_invite.key); - - char *k = malloc(length); - - if (k == NULL) - exit_toxic_err("Failed in chat_onGroupInvite", FATALERR_MEMORY); - - memcpy(k, group_pub_key, length); - Friends.list[friendnumber].group_invite.key = k; - Friends.list[friendnumber].group_invite.pending = true; - Friends.list[friendnumber].group_invite.length = length; - Friends.list[friendnumber].group_invite.type = type; - - sound_notify(self, generic_message, NT_WNDALERT_2, NULL); - - char name[TOX_MAX_NAME_LENGTH]; - get_nick_truncate(m, name, friendnumber); - - if (self->active_box != -1) - box_silent_notify2(self, NT_WNDALERT_2 | NT_NOFOCUS, self->active_box, "invites you to join group chat"); - else - box_silent_notify(self, NT_WNDALERT_2 | NT_NOFOCUS, &self->active_box, name, "invites you to join group chat"); - - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s has invited you to a group chat.", name); - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Type \"/join\" to join the chat."); -} - /* Av Stuff */ #ifdef AUDIO @@ -604,14 +569,14 @@ void chat_onInvite (ToxWindow *self, ToxAv *av, int call_index) return; /* call_index is set here and reset on call end */ - + self->call_idx = call_index; line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Incoming audio call! Type: \"/answer\" or \"/reject\""); - + if (self->ringing_sound == -1) sound_notify(self, call_incoming, NT_LOOP, &self->ringing_sound); - - + + if (self->active_box != -1) box_silent_notify2(self, NT_NOFOCUS | NT_WNDALERT_0, self->active_box, "Incoming audio call!"); else @@ -624,7 +589,7 @@ void chat_onRinging (ToxWindow *self, ToxAv *av, int call_index) return; line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Ringing...type \"/hangup\" to cancel it."); - + #ifdef SOUND_NOTIFY if (self->ringing_sound == -1) sound_notify(self, call_outgoing, NT_LOOP, &self->ringing_sound); @@ -639,7 +604,7 @@ void chat_onStarting (ToxWindow *self, ToxAv *av, int call_index) init_infobox(self); line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Call started! Type: \"/hangup\" to end it."); - + #ifdef SOUND_NOTIFY stop_sound(self->ringing_sound); #endif /* SOUND_NOTIFY */ @@ -653,7 +618,7 @@ void chat_onEnding (ToxWindow *self, ToxAv *av, int call_index) kill_infobox(self); self->call_idx = -1; line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Call ended!"); - + #ifdef SOUND_NOTIFY stop_sound(self->ringing_sound); #endif /* SOUND_NOTIFY */ @@ -666,7 +631,7 @@ void chat_onError (ToxWindow *self, ToxAv *av, int call_index) self->call_idx = -1; line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Error!"); - + #ifdef SOUND_NOTIFY stop_sound(self->ringing_sound); #endif /* SOUND_NOTIFY */ @@ -680,7 +645,7 @@ void chat_onStart (ToxWindow *self, ToxAv *av, int call_index) init_infobox(self); line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Call started! Type: \"/hangup\" to end it."); - + #ifdef SOUND_NOTIFY stop_sound(self->ringing_sound); #endif /* SOUND_NOTIFY */ @@ -694,7 +659,7 @@ void chat_onCancel (ToxWindow *self, ToxAv *av, int call_index) kill_infobox(self); self->call_idx = -1; line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Call canceled!"); - + #ifdef SOUND_NOTIFY stop_sound(self->ringing_sound); #endif /* SOUND_NOTIFY */ @@ -707,7 +672,7 @@ void chat_onReject (ToxWindow *self, ToxAv *av, int call_index) self->call_idx = -1; line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Rejected!"); - + #ifdef SOUND_NOTIFY stop_sound(self->ringing_sound); #endif /* SOUND_NOTIFY */ @@ -721,7 +686,7 @@ void chat_onEnd (ToxWindow *self, ToxAv *av, int call_index) kill_infobox(self); self->call_idx = -1; line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Call ended!"); - + #ifdef SOUND_NOTIFY stop_sound(self->ringing_sound); #endif /* SOUND_NOTIFY */ @@ -734,7 +699,7 @@ void chat_onRequestTimeout (ToxWindow *self, ToxAv *av, int call_index) self->call_idx = -1; line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "No answer!"); - + #ifdef SOUND_NOTIFY stop_sound(self->ringing_sound); #endif /* SOUND_NOTIFY */ @@ -748,7 +713,7 @@ void chat_onPeerTimeout (ToxWindow *self, ToxAv *av, int call_index) kill_infobox(self); self->call_idx = -1; line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Peer disconnected; call ended!"); - + #ifdef SOUND_NOTIFY stop_sound(self->ringing_sound); #endif /* SOUND_NOTIFY */ @@ -1140,7 +1105,6 @@ ToxWindow new_chat(Tox *m, int32_t friendnum) ret.onMessage = &chat_onMessage; ret.onConnectionChange = &chat_onConnectionChange; ret.onTypingChange = & chat_onTypingChange; - ret.onGroupInvite = &chat_onGroupInvite; ret.onNickChange = &chat_onNickChange; ret.onStatusChange = &chat_onStatusChange; ret.onStatusMessageChange = &chat_onStatusMessageChange; @@ -1162,14 +1126,14 @@ ToxWindow new_chat(Tox *m, int32_t friendnum) ret.onEnd = &chat_onEnd; ret.onRequestTimeout = &chat_onRequestTimeout; ret.onPeerTimeout = &chat_onPeerTimeout; - + ret.call_idx = -1; ret.device_selection[0] = ret.device_selection[1] = -1; ret.ringing_sound = -1; #endif /* AUDIO */ - + ret.active_box = -1; - + char nick[TOX_MAX_NAME_LENGTH]; int n_len = get_nick_truncate(m, nick, friendnum); set_window_title(&ret, nick, n_len); diff --git a/src/chat_commands.c b/src/chat_commands.c index a510cfa..48de478 100644 --- a/src/chat_commands.c +++ b/src/chat_commands.c @@ -58,7 +58,7 @@ void cmd_cancelfile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*ar if (strcasecmp(inoutstr, "in") == 0) { /* cancel an incoming file transfer */ if (!Friends.list[self->num].file_receiver[filenum].active) { line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid file ID."); - return; + return; } const char *filepath = Friends.list[self->num].file_receiver[filenum].filename; @@ -80,7 +80,7 @@ void cmd_cancelfile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*ar if (!match) { line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid file ID."); - return; + return; } const char *filename = file_senders[i].filename; @@ -94,67 +94,6 @@ void cmd_cancelfile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*ar } } -void cmd_groupinvite(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) -{ - if (argc < 1) { - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group number required."); - return; - } - - int groupnum = atoi(argv[1]); - - if (groupnum == 0 && strcmp(argv[1], "0")) { /* atoi returns 0 value on invalid input */ - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid group number."); - return; - } - - if (tox_invite_friend(m, self->num, groupnum) == -1) { - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to invite contact to group."); - return; - } - - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invited contact to Group %d.", groupnum); -} - -void cmd_join_group(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) -{ - if (get_num_active_windows() >= MAX_WINDOWS_NUM) { - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, RED, " * Warning: Too many windows are open."); - return; - } - - const char *groupkey = Friends.list[self->num].group_invite.key; - uint16_t length = Friends.list[self->num].group_invite.length; - uint8_t type = Friends.list[self->num].group_invite.type; - - if (!Friends.list[self->num].group_invite.pending) { - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "No pending group chat invite."); - return; - } - - int groupnum = -1; - - if (type == TOX_GROUPCHAT_TYPE_TEXT) - groupnum = tox_join_groupchat(m, self->num, (uint8_t *) groupkey, length); -#ifdef AUDIO - else - groupnum = toxav_join_av_groupchat(m, self->num, (uint8_t *) groupkey, length, - write_device_callback_group, NULL); -#endif - - if (groupnum == -1) { - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group chat instance failed to initialize."); - return; - } - - if (init_groupchat_win(prompt, m, groupnum, type) == -1) { - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group chat window failed to initialize."); - tox_del_groupchat(m, groupnum); - return; - } - -} - void cmd_savefile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) { if (argc < 1) { @@ -272,7 +211,7 @@ void cmd_sendfile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv char sizestr[32]; bytes_convert_str(sizestr, sizeof(sizestr), filesize); - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Sending file [%d]: '%s' (%s)", filenum, filename, sizestr); ++num_active_file_senders; diff --git a/src/chat_commands.h b/src/chat_commands.h index c66b77a..9c87ede 100644 --- a/src/chat_commands.h +++ b/src/chat_commands.h @@ -27,8 +27,6 @@ #include "toxic.h" void cmd_cancelfile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); -void cmd_groupinvite(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]); -void cmd_join_group(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_savefile(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_sendfile(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]); diff --git a/src/execute.c b/src/execute.c index 9e83a83..ea64117 100644 --- a/src/execute.c +++ b/src/execute.c @@ -49,6 +49,7 @@ static struct cmd_func global_commands[] = { { "/exit", cmd_quit }, { "/group", cmd_groupchat }, { "/help", cmd_prompt_help }, + { "/join", cmd_join }, { "/log", cmd_log }, { "/myid", cmd_myid }, { "/nick", cmd_nick }, @@ -66,8 +67,6 @@ static struct cmd_func global_commands[] = { static struct cmd_func chat_commands[] = { { "/cancel", cmd_cancelfile }, - { "/invite", cmd_groupinvite }, - { "/join", cmd_join_group }, { "/savefile", cmd_savefile }, { "/sendfile", cmd_sendfile }, #ifdef AUDIO @@ -82,8 +81,8 @@ static struct cmd_func chat_commands[] = { }; static struct cmd_func group_commands[] = { - { "/title", cmd_set_title }, - + { "/topic", cmd_set_topic }, + { "/chatid", cmd_chatid }, #ifdef AUDIO { "/mute", cmd_mute }, { "/sense", cmd_sense }, @@ -177,6 +176,7 @@ void execute(WINDOW *w, ToxWindow *self, Tox *m, const char *input, int mode) case GROUPCHAT_COMMAND_MODE: if (do_command(w, self, m, num_args, group_commands, args) == 0) return; + break; } diff --git a/src/execute.h b/src/execute.h index 03c121b..b755c8b 100644 --- a/src/execute.h +++ b/src/execute.h @@ -32,7 +32,7 @@ enum { GLOBAL_COMMAND_MODE, CHAT_COMMAND_MODE, GROUPCHAT_COMMAND_MODE, -}; +} COMMAND_MODE; void execute(WINDOW *w, ToxWindow *self, Tox *m, const char *input, int mode); diff --git a/src/friendlist.c b/src/friendlist.c index 6ce0cc9..ba925f0 100644 --- a/src/friendlist.c +++ b/src/friendlist.c @@ -112,13 +112,6 @@ static void realloc_blocklist(int n) void kill_friendlist(void) { - int i; - - for (i = 0; i < Friends.max_idx; ++i) { - if (Friends.list[i].active && Friends.list[i].group_invite.key != NULL) - free(Friends.list[i].group_invite.key); - } - realloc_blocklist(0); realloc_friends(0); } @@ -483,25 +476,6 @@ static void friendlist_onFileSendRequest(ToxWindow *self, Tox *m, int32_t num, u } } -static void friendlist_onGroupInvite(ToxWindow *self, Tox *m, int32_t num, uint8_t type, const char *group_pub_key, - uint16_t length) -{ - if (num >= Friends.max_idx) - return; - - if (Friends.list[num].chatwin == -1) { - if (get_num_active_windows() < MAX_WINDOWS_NUM) { - Friends.list[num].chatwin = add_window(m, new_chat(m, Friends.list[num].num)); - } else { - char nick[TOX_MAX_NAME_LENGTH]; - get_nick_truncate(m, nick, num); - line_info_add(prompt, NULL, NULL, NULL, SYS_MSG, 0, RED, - "* Group chat invite from %s failed: too many windows are open.", nick); - sound_notify(prompt, error, NT_WNDALERT_1, NULL); - } - } -} - /* move friendlist/blocklist cursor up and down */ static void select_friend(ToxWindow *self, wint_t key, int *selected, int num) { @@ -527,9 +501,6 @@ static void delete_friend(Tox *m, int32_t f_num) } } - if (Friends.list[f_num].group_invite.key != NULL) - free(Friends.list[f_num].group_invite.key); - tox_del_friend(m, f_num); memset(&Friends.list[f_num], 0, sizeof(ToxicFriend)); @@ -1075,7 +1046,6 @@ ToxWindow new_friendlist(void) ret.onStatusChange = &friendlist_onStatusChange; ret.onStatusMessageChange = &friendlist_onStatusMessageChange; ret.onFileSendRequest = &friendlist_onFileSendRequest; - ret.onGroupInvite = &friendlist_onGroupInvite; #ifdef AUDIO ret.onInvite = &friendlist_onAv; diff --git a/src/friendlist.h b/src/friendlist.h index 3beb633..599d4a7 100644 --- a/src/friendlist.h +++ b/src/friendlist.h @@ -48,13 +48,6 @@ struct LastOnline { char hour_min_str[TIME_STR_SIZE]; /* holds 12/24-hour time string e.g. "10:43 PM" */ }; -struct GroupChatInvite { - char *key; - uint16_t length; - uint8_t type; - bool pending; -}; - typedef struct { char name[TOXIC_MAX_NAME_LENGTH + 1]; int namelength; @@ -70,7 +63,6 @@ typedef struct { uint8_t status; struct LastOnline last_online; struct FileReceiver file_receiver[MAX_FILES]; - struct GroupChatInvite group_invite; uint8_t active_file_receivers; } ToxicFriend; diff --git a/src/global_commands.c b/src/global_commands.c index b2321b9..a513115 100644 --- a/src/global_commands.c +++ b/src/global_commands.c @@ -179,7 +179,7 @@ void cmd_add(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX } cmd_add_helper(self, m, id_bin, msg); - } else { /* assume id is a username@domain address and do DNS lookup */ + } else { /* assume id is a username@domain address */ dns3_lookup(self, m, id_bin, id, msg); } } @@ -326,42 +326,90 @@ void cmd_groupchat(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*arg } if (argc < 1) { - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Please specify group type: text | audio"); + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Error: Please specify the group name."); return; } - uint8_t type; + const char *tmp_name = argv[1]; + int len = strlen(tmp_name); - if (!strcasecmp(argv[1], "audio")) - type = TOX_GROUPCHAT_TYPE_AV; - else if (!strcasecmp(argv[1], "text")) - type = TOX_GROUPCHAT_TYPE_TEXT; - else { - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Valid group types are: text | audio"); + if (len == 0 || len > TOX_MAX_GROUP_NAME_LENGTH) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Error: Invalid group name."); return; } - int groupnum = -1; + char name[TOX_MAX_GROUP_NAME_LENGTH]; - if (type == TOX_GROUPCHAT_TYPE_TEXT) - groupnum = tox_add_groupchat(m); -#ifdef AUDIO - else - groupnum = toxav_add_av_groupchat(m, write_device_callback_group, NULL); -#endif + if (argv[1][0] == '\"') { /* remove opening and closing quotes */ + snprintf(name, sizeof(name), "%s", &argv[1][1]); + len -= 2; + name[len] = '\0'; + } else { + snprintf(name, sizeof(name), "%s", argv[1]); + } + + int groupnum = tox_group_new(m, (uint8_t *) name, len); if (groupnum == -1) { line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group chat instance failed to initialize."); return; } - if (init_groupchat_win(prompt, m, groupnum, type) == -1) { + if (init_groupchat_win(prompt, m, groupnum, name, len) == -1) { line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group chat window failed to initialize."); - tox_del_groupchat(m, groupnum); + tox_group_delete(m, groupnum, NULL, 0); + return; + } +} + +void cmd_join(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) +{ + if (get_num_active_windows() >= MAX_WINDOWS_NUM) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, RED, " * Warning: Too many windows are open."); return; } - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group chat [%d] created.", groupnum); + if (argc < 1) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Error: Group chat ID is required."); + return; + } + + const char *chat_id = argv[1]; + + if (strlen(chat_id) != TOX_GROUP_CHAT_ID_SIZE * 2) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Error: Invalid chat ID"); + return; + } + + char id_bin[TOX_GROUP_CHAT_ID_SIZE] = {0}; + + size_t i; + char xch[3]; + uint32_t x; + + for (i = 0; i < TOX_GROUP_CHAT_ID_SIZE; ++i) { + xch[0] = chat_id[2 * i]; + xch[1] = chat_id[2 * i + 1]; + xch[2] = '\0'; + + if (sscanf(xch, "%02x", &x) != 1) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid chat ID."); + return; + } + + id_bin[i] = x; + } + + if (tox_group_new_join(m, (uint8_t *) id_bin) == -1) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group chat instance failed to initialize."); + return; + } + + if (init_groupchat_win(prompt, m, self->num, NULL, 0) == -1) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group chat window failed to initialize."); + tox_group_delete(m, self->num, NULL, 0); + return; + } } void cmd_log(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) @@ -524,7 +572,7 @@ void cmd_requests(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv } void cmd_status(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) -{ +{ bool have_note = false; const char *errmsg; diff --git a/src/global_commands.h b/src/global_commands.h index 9d3f34b..6f2ff03 100644 --- a/src/global_commands.h +++ b/src/global_commands.h @@ -33,6 +33,7 @@ void cmd_clear(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE void cmd_connect(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_decline(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_groupchat(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]); +void cmd_join(WINDOW *window, ToxWindow *self, Tox *m, 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_nick(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]); diff --git a/src/group_commands.c b/src/group_commands.c index cc8374a..8f54c2a 100644 --- a/src/group_commands.c +++ b/src/group_commands.c @@ -28,50 +28,65 @@ #include "misc_tools.h" #include "log.h" -void cmd_set_title(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) +void cmd_set_topic(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) { - char title[MAX_STR_SIZE]; + char topic[MAX_STR_SIZE]; if (argc < 1) { - int tlen = tox_group_get_title(m, self->num, (uint8_t *) title, TOX_MAX_NAME_LENGTH); + int tlen = tox_group_get_topic(m, self->num, (uint8_t *) topic); - if (tlen != -1) { - title[tlen] = '\0'; - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Title is set to: %s", title); + if (tlen > 0) { + topic[tlen] = '\0'; + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Topic is set to: %s", topic); } else { - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Title is not set"); + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Topic is not set"); } return; } if (argv[1][0] != '\"') { - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Title must be enclosed in quotes."); + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Topic must be enclosed in quotes."); return; } /* remove opening and closing quotes */ - snprintf(title, sizeof(title), "%s", &argv[1][1]); - int len = strlen(title) - 1; - title[len] = '\0'; + snprintf(topic, sizeof(topic), "%s", &argv[1][1]); + int len = strlen(topic) - 1; + topic[len] = '\0'; - if (tox_group_set_title(m, self->num, (uint8_t *) title, len) != 0) { - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set title."); + if (tox_group_set_topic(m, self->num, (uint8_t *) topic, len) != 0) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set topic."); return; } - set_window_title(self, title, len); - char timefrmt[TIME_STR_SIZE]; char selfnick[TOX_MAX_NAME_LENGTH]; get_time_str(timefrmt, sizeof(timefrmt)); - uint16_t sn_len = tox_get_self_name(m, (uint8_t *) selfnick); + int sn_len = tox_group_get_self_name(m, self->num, (uint8_t *) selfnick); selfnick[sn_len] = '\0'; - line_info_add(self, timefrmt, selfnick, NULL, NAME_CHANGE, 0, 0, " set the group title to: %s", title); + line_info_add(self, timefrmt, selfnick, NULL, NAME_CHANGE, 0, 0, " set the group topic to: %s", topic); char tmp_event[MAX_STR_SIZE]; - snprintf(tmp_event, sizeof(tmp_event), "set title to %s", title); + snprintf(tmp_event, sizeof(tmp_event), "set topic to %s", topic); write_to_log(tmp_event, selfnick, self->chatwin->log, true); } + +void cmd_chatid(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) +{ + char chatid[TOX_GROUP_CHAT_ID_SIZE * 2 + 1] = {0}; + char chat_public_key[TOX_GROUP_CHAT_ID_SIZE]; + tox_group_get_invite_key(m, self->num, (uint8_t *) chat_public_key); + + size_t i; + + for (i = 0; i < TOX_GROUP_CHAT_ID_SIZE; ++i) { + char xx[3]; + snprintf(xx, sizeof(xx), "%02X", chat_public_key[i] & 0xff); + strcat(chatid, xx); + } + + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s", chatid); +} diff --git a/src/group_commands.h b/src/group_commands.h index 5d9a1b6..17c3eeb 100644 --- a/src/group_commands.h +++ b/src/group_commands.h @@ -26,6 +26,7 @@ #include "windows.h" #include "toxic.h" -void cmd_set_title(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); +void cmd_set_topic(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); +void cmd_chatid(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); #endif /* GROUP_COMMANDS_H */ diff --git a/src/groupchat.c b/src/groupchat.c index e568947..80a5988 100644 --- a/src/groupchat.c +++ b/src/groupchat.c @@ -70,16 +70,17 @@ extern struct user_settings *user_settings; extern struct Winthread Winthread; #ifdef AUDIO -#define AC_NUM_GROUP_COMMANDS 22 +#define AC_NUM_GROUP_COMMANDS 24 #else -#define AC_NUM_GROUP_COMMANDS 18 +#define AC_NUM_GROUP_COMMANDS 20 #endif /* AUDIO */ -/* Array of groupchat command names used for tab completion. */ +/* groupchat command names used for tab completion. */ static const char group_cmd_list[AC_NUM_GROUP_COMMANDS][MAX_CMDNAME_SIZE] = { { "/accept" }, { "/add" }, { "/avatar" }, + { "/chatid" }, { "/clear" }, { "/close" }, { "/connect" }, @@ -87,6 +88,7 @@ static const char group_cmd_list[AC_NUM_GROUP_COMMANDS][MAX_CMDNAME_SIZE] = { { "/exit" }, { "/group" }, { "/help" }, + { "/join" }, { "/log" }, { "/myid" }, { "/nick" }, @@ -94,7 +96,7 @@ static const char group_cmd_list[AC_NUM_GROUP_COMMANDS][MAX_CMDNAME_SIZE] = { { "/quit" }, { "/requests" }, { "/status" }, - { "/title" }, + { "/topic" }, #ifdef AUDIO @@ -106,45 +108,32 @@ static const char group_cmd_list[AC_NUM_GROUP_COMMANDS][MAX_CMDNAME_SIZE] = { #endif /* AUDIO */ }; +ToxWindow new_group_chat(Tox *m, int groupnum, const char *groupname, int length); + #ifdef AUDIO static int group_audio_open_out_device(int groupnum); static int group_audio_close_out_device(int groupnum); #endif /* AUDIO */ -int init_groupchat_win(ToxWindow *prompt, Tox *m, int groupnum, uint8_t type) +int init_groupchat_win(ToxWindow *prompt, Tox *m, int groupnum, const char *groupname, int length) { if (groupnum > MAX_GROUPCHAT_NUM) return -1; - ToxWindow self = new_group_chat(m, groupnum); + ToxWindow self = new_group_chat(m, groupnum, groupname, length); + int i; for (i = 0; i <= max_groupchat_index; ++i) { if (!groupchats[i].active) { groupchats[i].chatwin = add_window(m, self); groupchats[i].active = true; - groupchats[i].num_peers = 0; - groupchats[i].type = type; - groupchats[i].start_time = get_unix_time(); - groupchats[i].peer_names = malloc(sizeof(uint8_t) * TOX_MAX_NAME_LENGTH); - groupchats[i].oldpeer_names = malloc(sizeof(uint8_t) * TOX_MAX_NAME_LENGTH); - groupchats[i].peer_name_lengths = malloc(sizeof(uint16_t)); - groupchats[i].oldpeer_name_lengths = malloc(sizeof(uint16_t)); + groupchats[i].peer_name_lengths = malloc(sizeof(uint32_t)); - if (groupchats[i].peer_names == NULL || groupchats[i].oldpeer_names == NULL - || groupchats[i].peer_name_lengths == NULL || groupchats[i].oldpeer_name_lengths == NULL) + if (groupchats[i].peer_names == NULL || groupchats[i].peer_name_lengths == NULL) exit_toxic_err("failed in init_groupchat_win", FATALERR_MEMORY); - memcpy(&groupchats[i].oldpeer_names[0], UNKNOWN_NAME, sizeof(UNKNOWN_NAME)); - groupchats[i].oldpeer_name_lengths[0] = (uint16_t) strlen(UNKNOWN_NAME); - -#ifdef AUDIO - if (type == TOX_GROUPCHAT_TYPE_AV) - if (group_audio_open_out_device(i) == -1) - fprintf(stderr, "Group Audio failed to init\n"); -#endif /* AUDIO */ - set_active_window(groupchats[i].chatwin); if (i == max_groupchat_index) @@ -172,17 +161,16 @@ static void kill_groupchat_window(ToxWindow *self) del_window(self); } -void close_groupchat(ToxWindow *self, Tox *m, int groupnum) +void close_groupchat(ToxWindow *self, Tox *m, int groupnum, const char *partmessage, int length) { - tox_del_groupchat(m, groupnum); + tox_group_delete(m, groupnum, (const uint8_t *) partmessage, (uint16_t) length); + #ifdef AUDIO group_audio_close_out_device(groupnum); #endif free(groupchats[groupnum].peer_names); - free(groupchats[groupnum].oldpeer_names); free(groupchats[groupnum].peer_name_lengths); - free(groupchats[groupnum].oldpeer_name_lengths); memset(&groupchats[groupnum], 0, sizeof(GroupChat)); int i; @@ -244,15 +232,15 @@ static void groupchat_onGroupMessage(ToxWindow *self, Tox *m, int groupnum, int get_group_nick_truncate(m, nick, peernum, groupnum); char selfnick[TOX_MAX_NAME_LENGTH]; - uint16_t sn_len = tox_get_self_name(m, (uint8_t *) selfnick); + uint16_t sn_len = tox_group_get_self_name(m, groupnum, (uint8_t *) selfnick); selfnick[sn_len] = '\0'; - int nick_clr = strcmp(nick, selfnick) == 0 ? GREEN : CYAN; + int nick_clr = CYAN; /* Only play sound if mentioned by someone else */ if (strcasestr(msg, selfnick) && strcmp(selfnick, nick)) { sound_notify(self, generic_message, NT_WNDALERT_0, NULL); - + if (self->active_box != -1) box_silent_notify2(self, NT_NOFOCUS, self->active_box, "%s %s", nick, msg); else @@ -283,12 +271,12 @@ static void groupchat_onGroupAction(ToxWindow *self, Tox *m, int groupnum, int p get_group_nick_truncate(m, nick, peernum, groupnum); char selfnick[TOX_MAX_NAME_LENGTH]; - uint16_t n_len = tox_get_self_name(m, (uint8_t *) selfnick); + uint16_t n_len = tox_group_get_self_name(m, groupnum, (uint8_t *) selfnick); selfnick[n_len] = '\0'; if (strcasestr(action, selfnick)) { sound_notify(self, generic_message, NT_WNDALERT_0, NULL); - + if (self->active_box != -1) box_silent_notify2(self, NT_NOFOCUS, self->active_box, "* %s %s", nick, action ); else @@ -305,52 +293,61 @@ static void groupchat_onGroupAction(ToxWindow *self, Tox *m, int groupnum, int p write_to_log(action, nick, ctx->log, true); } -static void groupchat_onGroupTitleChange(ToxWindow *self, Tox *m, int groupnum, int peernum, const char *title, - uint8_t length) +static void groupchat_onGroupPrivateMessage(ToxWindow *self, Tox *m, int groupnum, uint32_t peernum, + const char *action, uint16_t len) +{ + if (self->num != groupnum) + return; + + ChatContext *ctx = self->chatwin; + + char nick[TOX_MAX_NAME_LENGTH]; + get_group_nick_truncate(m, nick, peernum, groupnum); + + char timefrmt[TIME_STR_SIZE]; + get_time_str(timefrmt, sizeof(timefrmt)); + + line_info_add(self, timefrmt, nick, NULL, IN_MSG, 0, RED, "%s", action); + write_to_log(action, nick, ctx->log, false); + sound_notify(self, silent, NT_WNDALERT_1, NULL); +} + +static void groupchat_onGroupTopicChange(ToxWindow *self, Tox *m, int groupnum, uint32_t peernum, + const char *topic, uint16_t length) { ChatContext *ctx = self->chatwin; if (self->num != groupnum) return; - set_window_title(self, title, length); - char timefrmt[TIME_STR_SIZE]; get_time_str(timefrmt, sizeof(timefrmt)); - /* don't announce title when we join the room */ - if (!timed_out(groupchats[self->num].start_time, get_unix_time(), GROUP_EVENT_WAIT)) - return; - char nick[TOX_MAX_NAME_LENGTH]; get_group_nick_truncate(m, nick, peernum, groupnum); - line_info_add(self, timefrmt, nick, NULL, NAME_CHANGE, 0, 0, " set the group title to: %s", title); + line_info_add(self, timefrmt, nick, NULL, NAME_CHANGE, 0, 0, " set the group topic to: %s", topic); char tmp_event[MAX_STR_SIZE]; - snprintf(tmp_event, sizeof(tmp_event), "set title to %s", title); + snprintf(tmp_event, sizeof(tmp_event), "set topic to %s", topic); write_to_log(tmp_event, nick, ctx->log, true); } -/* Puts two copies of peerlist/lengths in chat instance */ -static void copy_peernames(int gnum, uint8_t peerlist[][TOX_MAX_NAME_LENGTH], uint16_t lengths[], int npeers) +/* Copies peer names/lengths */ +static void copy_peernames(int gnum, uint8_t peerlist[][TOX_MAX_NAME_LENGTH], uint32_t lengths[], int npeers) { - /* Assumes these are initiated in init_groupchat_win */ free(groupchats[gnum].peer_names); - free(groupchats[gnum].oldpeer_names); free(groupchats[gnum].peer_name_lengths); - free(groupchats[gnum].oldpeer_name_lengths); int N = TOX_MAX_NAME_LENGTH; - groupchats[gnum].peer_names = malloc(sizeof(uint8_t) * npeers * N); - groupchats[gnum].oldpeer_names = malloc(sizeof(uint8_t) * npeers * N); - groupchats[gnum].peer_name_lengths = malloc(sizeof(uint16_t) * npeers); - groupchats[gnum].oldpeer_name_lengths = malloc(sizeof(uint16_t) * npeers); + groupchats[gnum].peer_names = calloc(1, sizeof(uint8_t) * npeers * N); + groupchats[gnum].peer_name_lengths = calloc(1, sizeof(uint32_t) * npeers); - if (groupchats[gnum].peer_names == NULL || groupchats[gnum].oldpeer_names == NULL - || groupchats[gnum].peer_name_lengths == NULL || groupchats[gnum].oldpeer_name_lengths == NULL) { + if (groupchats[gnum].peer_names == NULL || groupchats[gnum].peer_name_lengths == NULL) exit_toxic_err("failed in copy_peernames", FATALERR_MEMORY); - } + + if (npeers == 0) + return; uint16_t u_len = strlen(UNKNOWN_NAME); int i; @@ -366,184 +363,199 @@ static void copy_peernames(int gnum, uint8_t peerlist[][TOX_MAX_NAME_LENGTH], ui groupchats[gnum].peer_names[i * N + n_len] = '\0'; groupchats[gnum].peer_name_lengths[i] = n_len; filter_str((char *) &groupchats[gnum].peer_names[i * N], n_len); - } - } - - memcpy(groupchats[gnum].oldpeer_names, groupchats[gnum].peer_names, N * npeers); - memcpy(groupchats[gnum].oldpeer_name_lengths, groupchats[gnum].peer_name_lengths, sizeof(uint16_t) * npeers); -} - -struct group_add_thrd { - Tox *m; - ToxWindow *self; - int peernum; - int groupnum; - uint64_t timestamp; - pthread_t tid; - pthread_attr_t attr; -}; - -/* Waits GROUP_EVENT_WAIT seconds for a new peer to set their name before announcing them */ -void *group_add_wait(void *data) -{ - struct group_add_thrd *thrd = (struct group_add_thrd *) data; - ToxWindow *self = thrd->self; - Tox *m = thrd->m; - char peername[TOX_MAX_NAME_LENGTH]; - - /* keep polling for a name that differs from the default until we run out of time */ - while (true) { - usleep(100000); - - pthread_mutex_lock(&Winthread.lock); - get_group_nick_truncate(m, peername, thrd->peernum, thrd->groupnum); - - if (strcmp(peername, DEFAULT_TOX_NAME) || timed_out(thrd->timestamp, get_unix_time(), GROUP_EVENT_WAIT)) { - pthread_mutex_unlock(&Winthread.lock); - break; } - - pthread_mutex_unlock(&Winthread.lock); } - - const char *event = "has joined the room"; - char timefrmt[TIME_STR_SIZE]; - get_time_str(timefrmt, sizeof(timefrmt)); - - pthread_mutex_lock(&Winthread.lock); - line_info_add(self, timefrmt, (char *) peername, NULL, CONNECTION, 0, GREEN, event); - write_to_log(event, (char *) peername, self->chatwin->log, true); - pthread_mutex_unlock(&Winthread.lock); - - pthread_attr_destroy(&thrd->attr); - free(thrd); - pthread_exit(NULL); } -static void groupchat_onGroupNamelistChange(ToxWindow *self, Tox *m, int groupnum, int peernum, uint8_t change) +static void groupchat_onGroupNamelistChange(ToxWindow *self, Tox *m, int groupnum) { if (self->num != groupnum) return; - if (groupnum > max_groupchat_index) - return; + int num_peers = tox_group_get_number_peers(m, groupnum); + groupchats[groupnum].num_peers = num_peers; - groupchats[groupnum].num_peers = tox_group_number_peers(m, groupnum); - int num_peers = groupchats[groupnum].num_peers; - - if (peernum > num_peers) - return; - - /* get old peer name before updating name list */ - uint8_t oldpeername[TOX_MAX_NAME_LENGTH]; - - if (change != TOX_CHAT_CHANGE_PEER_ADD) { - memcpy(oldpeername, &groupchats[groupnum].oldpeer_names[peernum * TOX_MAX_NAME_LENGTH], - sizeof(oldpeername)); - uint16_t old_n_len = groupchats[groupnum].oldpeer_name_lengths[peernum]; - oldpeername[old_n_len] = '\0'; - } - - /* Update name/len lists */ uint8_t tmp_peerlist[num_peers][TOX_MAX_NAME_LENGTH]; - uint16_t tmp_peerlens[num_peers]; + uint32_t tmp_peerlens[num_peers]; - if (tox_group_get_names(m, groupnum, tmp_peerlist, tmp_peerlens, num_peers) == -1) { - memset(tmp_peerlist, 0, sizeof(tmp_peerlist)); - memset(tmp_peerlens, 0, sizeof(tmp_peerlens)); - } + if (tox_group_get_names(m, groupnum, tmp_peerlist, tmp_peerlens, num_peers) == -1) + return; copy_peernames(groupnum, tmp_peerlist, tmp_peerlens, num_peers); +} - /* get current peername then sort namelist */ - uint8_t peername[TOX_MAX_NAME_LENGTH]; +static void groupchat_onGroupPeerJoin(ToxWindow *self, Tox *m, int groupnum, uint32_t peernum) +{ + if (groupnum != self->num) + return; - if (change != TOX_CHAT_CHANGE_PEER_DEL) { - uint16_t n_len = groupchats[groupnum].peer_name_lengths[peernum]; - memcpy(peername, &groupchats[groupnum].peer_names[peernum * TOX_MAX_NAME_LENGTH], sizeof(peername)); - peername[n_len] = '\0'; - } + if (peernum > groupchats[groupnum].num_peers) + return; - qsort(groupchats[groupnum].peer_names, groupchats[groupnum].num_peers, TOX_MAX_NAME_LENGTH, qsort_strcasecmp_hlpr); + char name[TOX_MAX_NAME_LENGTH]; + get_group_nick_truncate(m, name, peernum, groupnum); - ChatContext *ctx = self->chatwin; - - const char *event; char timefrmt[TIME_STR_SIZE]; get_time_str(timefrmt, sizeof(timefrmt)); - switch (change) { - case TOX_CHAT_CHANGE_PEER_ADD: - if (!timed_out(groupchats[groupnum].start_time, get_unix_time(), GROUP_EVENT_WAIT)) - break; + line_info_add(self, timefrmt, name, NULL, CONNECTION, 0, GREEN, "has joined the room"); - struct group_add_thrd *thrd = malloc(sizeof(struct group_add_thrd)); - thrd->m = m; - thrd->peernum = peernum; - thrd->groupnum = groupnum; - thrd->self = self; - thrd->timestamp = get_unix_time(); - - if (pthread_attr_init(&thrd->attr) != 0) { - free(thrd); - return; - } - - if (pthread_attr_setdetachstate(&thrd->attr, PTHREAD_CREATE_DETACHED) != 0) { - pthread_attr_destroy(&thrd->attr); - free(thrd); - return; - } - - if (pthread_create(&thrd->tid, &thrd->attr, group_add_wait, (void *) thrd) != 0) { - pthread_attr_destroy(&thrd->attr); - free(thrd); - return; - } - - break; - - case TOX_CHAT_CHANGE_PEER_DEL: - event = "has left the room"; - line_info_add(self, timefrmt, (char *) oldpeername, NULL, CONNECTION, 0, RED, event); - - if (groupchats[self->num].side_pos > 0) - --groupchats[self->num].side_pos; - - write_to_log(event, (char *) oldpeername, ctx->log, true); - break; - - case TOX_CHAT_CHANGE_PEER_NAME: - if (!timed_out(groupchats[self->num].start_time, get_unix_time(), GROUP_EVENT_WAIT)) - return; - - /* ignore initial name change (TODO: this is a bad way to do this) */ - if (strcmp((char *) oldpeername, DEFAULT_TOX_NAME) == 0) - return; - - event = " is now known as "; - line_info_add(self, timefrmt, (char *) oldpeername, (char *) peername, NAME_CHANGE, 0, 0, event); - - char tmp_event[TOXIC_MAX_NAME_LENGTH * 2 + 32]; - snprintf(tmp_event, sizeof(tmp_event), "is now known as %s", (char *) peername); - write_to_log(tmp_event, (char *) oldpeername, ctx->log, true); - break; - } + char log_str[TOXIC_MAX_NAME_LENGTH + 32]; + snprintf(log_str, sizeof(log_str), "%s has joined the room", name); + write_to_log(log_str, name, self->chatwin->log, true); sound_notify(self, silent, NT_WNDALERT_2, NULL); } -static void send_group_action(ToxWindow *self, ChatContext *ctx, Tox *m, char *action) +static void groupchat_onGroupPeerExit(ToxWindow *self, Tox *m, int groupnum, uint32_t peernum, + const char *partmessage, uint16_t len) { + if (groupnum != self->num) + return; + + if (peernum > groupchats[groupnum].num_peers) + return; + + char name[TOX_MAX_NAME_LENGTH]; + get_group_nick_truncate(m, name, peernum, groupnum); + + char timefrmt[TIME_STR_SIZE]; + get_time_str(timefrmt, sizeof(timefrmt)); + + line_info_add(self, timefrmt, name, NULL, CONNECTION, 0, GREEN, "has left the room (%s)", partmessage); + + char log_str[TOXIC_MAX_NAME_LENGTH + MAX_STR_SIZE]; + snprintf(log_str, sizeof(log_str), "%s has left the room (%s)", name, partmessage); + + write_to_log(log_str, name, self->chatwin->log, true); + sound_notify(self, silent, NT_WNDALERT_2, NULL); +} + +static void groupchat_onGroupSelfJoin(ToxWindow *self, Tox *m, int groupnum) +{ + if (groupnum != self->num) + return; + + char groupname[TOX_MAX_GROUP_NAME_LENGTH]; + int len = tox_group_get_group_name(m, groupnum, (uint8_t *) groupname); + + if (len > 0) + set_window_title(self, groupname, len); + + char topic[TOX_MAX_GROUP_TOPIC_LENGTH]; + tox_group_get_topic(m, groupnum, (uint8_t *) topic); + + char timefrmt[TIME_STR_SIZE]; + get_time_str(timefrmt, sizeof(timefrmt)); + + line_info_add(self, timefrmt, NULL, NULL, SYS_MSG, 0, 0, "Connected."); + line_info_add(self, timefrmt, NULL, NULL, SYS_MSG, 0, 0, "Topic set to: %s", topic); +} + +static void groupchat_onGroupSelfTimeout(ToxWindow *self, Tox *m, int groupnum) +{ + if (groupnum != self->num) + return; + + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Disconnected from group. Attempting to reconnect..."); +} + +static void groupchat_onGroupOpCertificate(ToxWindow *self, Tox *m, int groupnum, uint32_t src_peernum, + uint32_t tgt_peernum, uint8_t type) +{ + if (groupnum != self->num) + return; + + char src_name[TOX_MAX_NAME_LENGTH]; + get_group_nick_truncate(m, src_name, src_peernum, groupnum); + + char tgt_name[TOX_MAX_NAME_LENGTH]; + get_group_nick_truncate(m, tgt_name, tgt_peernum, groupnum); + + const char *msg = NULL; + + switch (type) { + case TOX_GC_BAN: + msg = "has banned"; + break; + case TOX_GC_PROMOTE_OP: + msg = "has given operator status to"; + break; + case TOX_GC_REVOKE_OP: + msg = "has removed operator status from"; + break; + case TOX_GC_SILENCE: + msg = "has silenced"; + break; + default: + return; + } + + char timefrmt[TIME_STR_SIZE]; + get_time_str(timefrmt, sizeof(timefrmt)); + line_info_add(self, timefrmt, src_name, tgt_name, NAME_CHANGE, 0, MAGENTA, "%s", msg); +} + +static void groupchat_onGroupNickChange(ToxWindow *self, Tox *m, int groupnum, uint32_t peernum, + const char *newnick, uint16_t len) +{ + if (groupnum != self->num) + return; + + char oldnick[TOX_MAX_NAME_LENGTH]; + get_group_nick_truncate(m, oldnick, peernum, groupnum); + + char timefrmt[TIME_STR_SIZE]; + get_time_str(timefrmt, sizeof(timefrmt)); + line_info_add(self, timefrmt, oldnick, (char *) newnick, NAME_CHANGE, 0, MAGENTA, "is now known as"); +} + + +static void send_group_message(ToxWindow *self, Tox *m, int groupnum, const char *msg) +{ + ChatContext *ctx = self->chatwin; + + if (tox_group_message_send(m, self->num, (uint8_t *) msg, strlen(msg)) == -1) { + const char *errmsg = " * Failed to send message."; + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, RED, errmsg); + return; + } + + char selfname[TOX_MAX_NAME_LENGTH]; + uint16_t len = tox_group_get_self_name(m, groupnum, (uint8_t *) selfname); + selfname[len] = '\0'; + + char timefrmt[TIME_STR_SIZE]; + get_time_str(timefrmt, sizeof(timefrmt)); + + line_info_add(self, timefrmt, selfname, NULL, OUT_MSG_READ, 0, 0, msg); + write_to_log(msg, selfname, ctx->log, false); +} + +static void send_group_action(ToxWindow *self, Tox *m, int groupnum, char *action) +{ + ChatContext *ctx = self->chatwin; + if (action == NULL) { wprintw(ctx->history, "Invalid syntax.\n"); return; } - if (tox_group_action_send(m, self->num, (uint8_t *) action, strlen(action)) == -1) { + if (tox_group_action_send(m, groupnum, (uint8_t *) action, strlen(action)) == -1) { const char *errmsg = " * Failed to send action."; line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, RED, errmsg); + return; } + + char selfname[TOX_MAX_NAME_LENGTH]; + uint16_t len = tox_group_get_self_name(m, groupnum, (uint8_t *) selfname); + selfname[len] = '\0'; + + char timefrmt[TIME_STR_SIZE]; + get_time_str(timefrmt, sizeof(timefrmt)); + + line_info_add(self, timefrmt, selfname, NULL, OUT_ACTION_READ, 0, 0, action); + write_to_log(action, selfname, ctx->log, true); } static void groupchat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr) @@ -579,7 +591,7 @@ static void groupchat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr) /* TODO: make this not suck */ if (ctx->line[0] != L'/' || wcscmp(ctx->line, L"/me") == 0) { - diff = complete_line(self, groupchats[self->num].peer_names, groupchats[self->num].num_peers, + diff = complete_line(self, groupchats[self->num].peer_names, groupchats[self->num].num_peers, TOX_MAX_NAME_LENGTH); } else if (wcsncmp(ctx->line, L"/avatar \"", wcslen(L"/avatar \"")) == 0) { diff = dir_match(self, m, ctx->line, L"/avatar"); @@ -618,19 +630,16 @@ static void groupchat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr) add_line_to_hist(ctx); if (line[0] == '/') { - if (strcmp(line, "/close") == 0) { - close_groupchat(self, m, self->num); + if (strncmp(line, "/close", 6) == 0) { + close_groupchat(self, m, self->num, line + 6, ctx->len - 6); return; } else if (strncmp(line, "/me ", strlen("/me ")) == 0) { - send_group_action(self, ctx, m, line + strlen("/me ")); + send_group_action(self, m, self->num, line + strlen("/me ")); } else { execute(ctx->history, self, m, line, GROUPCHAT_COMMAND_MODE); } } else if (!string_is_empty(line)) { - if (tox_group_message_send(m, self->num, (uint8_t *) line, strlen(line)) == -1) { - const char *errmsg = " * Failed to send message."; - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, RED, errmsg); - } + send_group_message(self, m, self->num, line); } wclear(ctx->linewin); @@ -727,13 +736,21 @@ static void groupchat_onInit(ToxWindow *self, Tox *m) execute(ctx->history, self, m, "/log", GLOBAL_COMMAND_MODE); + char selfname[TOX_MAX_NAME_LENGTH]; + uint16_t len = tox_get_self_name(m, (uint8_t *) selfname); + selfname[len] = '\0'; + tox_group_set_name(m, self->num, (uint8_t *) selfname, len); + + uint8_t status = tox_get_self_user_status(m); + tox_group_set_status(m, self->num, status); + scrollok(ctx->history, 0); wmove(self->window, y2 - CURS_Y_OFFSET, 0); } #ifdef AUDIO -static int group_audio_open_out_device(int groupnum) +static int group_audio_open_out_device(int groupnum) { char dname[MAX_STR_SIZE]; get_primary_device_name(output, dname, sizeof(dname)); @@ -821,13 +838,13 @@ static int group_audio_write(int peernum, int groupnum, const int16_t *pcm, unsi ALint state; alGetSourcei(groupchats[groupnum].audio.source, AL_SOURCE_STATE, &state); - if (state != AL_PLAYING) + if (state != AL_PLAYING) alSourcePlay(groupchats[groupnum].audio.source); return 0; } -static void groupchat_onWriteDevice(ToxWindow *self, Tox *m, int groupnum, int peernum, const int16_t *pcm, +static void groupchat_onWriteDevice(ToxWindow *self, Tox *m, int groupnum, int peernum, const int16_t *pcm, unsigned int samples, uint8_t channels, unsigned int sample_rate) { return; @@ -849,7 +866,7 @@ static void groupchat_onWriteDevice(ToxWindow *self, Tox *m, int groupnum, int p } #endif /* AUDIO */ -ToxWindow new_group_chat(Tox *m, int groupnum) +ToxWindow new_group_chat(Tox *m, int groupnum, const char *groupname, int length) { ToxWindow ret; memset(&ret, 0, sizeof(ret)); @@ -862,14 +879,24 @@ ToxWindow new_group_chat(Tox *m, int groupnum) ret.onInit = &groupchat_onInit; ret.onGroupMessage = &groupchat_onGroupMessage; ret.onGroupNamelistChange = &groupchat_onGroupNamelistChange; + ret.onGroupPrivateMessage = &groupchat_onGroupPrivateMessage; ret.onGroupAction = &groupchat_onGroupAction; - ret.onGroupTitleChange = &groupchat_onGroupTitleChange; + ret.onGroupPeerJoin = &groupchat_onGroupPeerJoin; + ret.onGroupPeerExit = &groupchat_onGroupPeerExit; + ret.onGroupTopicChange = &groupchat_onGroupTopicChange; + ret.onGroupOpCertificate = &groupchat_onGroupOpCertificate; + ret.onGroupNickChange = &groupchat_onGroupNickChange; + ret.onGroupSelfJoin = &groupchat_onGroupSelfJoin; + ret.onGroupSelfTimeout = &groupchat_onGroupSelfTimeout; #ifdef AUDIO ret.onWriteDevice = &groupchat_onWriteDevice; #endif - snprintf(ret.name, sizeof(ret.name), "Group %d", groupnum); + if (groupname && length) + set_window_title(&ret, groupname, length); + else + snprintf(ret.name, sizeof(ret.name), "Group %d", groupnum); ChatContext *chatwin = calloc(1, sizeof(ChatContext)); Help *help = calloc(1, sizeof(Help)); diff --git a/src/groupchat.h b/src/groupchat.h index 59d59c8..1118e58 100644 --- a/src/groupchat.h +++ b/src/groupchat.h @@ -61,26 +61,19 @@ struct GAudio { typedef struct { int chatwin; bool active; - uint8_t type; int num_peers; int side_pos; /* current position of the sidebar - used for scrolling up and down */ - uint64_t start_time; uint8_t *peer_names; - uint8_t *oldpeer_names; - uint16_t *peer_name_lengths; - uint16_t *oldpeer_name_lengths; - + uint32_t *peer_name_lengths; #ifdef AUDIO struct GAudio audio; #endif } GroupChat; -void close_groupchat(ToxWindow *self, Tox *m, int groupnum); -int init_groupchat_win(ToxWindow *prompt, Tox *m, int groupnum, uint8_t type); +void close_groupchat(ToxWindow *self, Tox *m, int groupnum, const char *partmessage, int length); +int init_groupchat_win(ToxWindow *prompt, Tox *m, int groupnum, const char *groupname, int length); /* destroys and re-creates groupchat window with or without the peerlist */ void redraw_groupchat_win(ToxWindow *self); -ToxWindow new_group_chat(Tox *m, int groupnum); - #endif /* #define GROUPCHAT_H */ diff --git a/src/help.c b/src/help.c index 0a97697..3087c35 100644 --- a/src/help.c +++ b/src/help.c @@ -150,9 +150,10 @@ static void help_draw_global(ToxWindow *self) wprintw(win, " /connect : Manually connect to a DHT node\n"); wprintw(win, " /status : Set status with optional note\n"); wprintw(win, " /note : Set a personal note\n"); + wprintw(win, " /group : Create a group chat\n"); + wprintw(win, " /join : Join a group chat\n"); wprintw(win, " /nick : Set your nickname\n"); 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, " /clear : Clear window history\n"); wprintw(win, " /close : Close the current chat window\n"); @@ -183,8 +184,6 @@ static void help_draw_chat(ToxWindow *self) wprintw(win, "Chat Commands:\n"); wattroff(win, A_BOLD | COLOR_PAIR(RED)); - wprintw(win, " /invite : Invite contact to a group chat\n"); - wprintw(win, " /join : Join a pending group chat\n"); wprintw(win, " /sendfile : Send a file\n"); wprintw(win, " /savefile : Receive a file\n"); wprintw(win, " /cancel : Cancel file transfer where type: in|out\n"); @@ -219,7 +218,7 @@ static void help_draw_keys(ToxWindow *self) wprintw(win, "Key bindings:\n"); wattroff(win, A_BOLD | COLOR_PAIR(RED)); - wprintw(win, " Ctrl+O and Ctrl+P : Navigate through the tabs\n"); + wprintw(win, " Ctrl+O and Ctrl+P : Navigate through the tabs\n"); 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"); @@ -243,14 +242,17 @@ static void help_draw_group(ToxWindow *self) wprintw(win, "Group commands:\n"); wattroff(win, A_BOLD | COLOR_PAIR(RED)); - wprintw(win, " /title : Set group title (show current title if no msg)\n\n"); + wprintw(win, " /topic : Set group topic (show current topic if no msg)\n"); + wprintw(win, " /chatid : Print the group chat id to share with others.\n\n"); +#ifdef AUDIO wattron(win, A_BOLD); wprintw(win, " Audio commands:\n"); wattroff(win, A_BOLD); wprintw(win, " /mute : Mute active device where type: in | out\n"); wprintw(win, " /sense : VAD sensitivity threshold\n\n"); +#endif /* AUDIO */ help_draw_bottom_menu(win); @@ -290,28 +292,30 @@ void help_onKey(ToxWindow *self, wint_t key) case 'c': #ifdef AUDIO - help_init_window(self, 19, 80); + help_init_window(self, 18, 80); #else - help_init_window(self, 9, 80); + help_init_window(self, 8, 80); #endif self->help->type = HELP_CHAT; break; case 'g': #ifdef AUDIO - help_init_window(self, 24, 80); + help_init_window(self, 25, 80); #else - help_init_window(self, 20, 80); + help_init_window(self, 21, 80); #endif self->help->type = HELP_GLOBAL; break; -#ifdef AUDIO /* remove if/when we add non-audio group commands */ case 'r': - help_init_window(self, 10, 80); +#ifdef AUDIO + help_init_window(self, 11, 80); +#else + help_init_window(self, 7, 80); +#endif self->help->type = HELP_GROUP; break; -#endif case 'f': help_init_window(self, 10, 80); diff --git a/src/line_info.c b/src/line_info.c index 6c6f872..baca619 100644 --- a/src/line_info.c +++ b/src/line_info.c @@ -222,7 +222,7 @@ void line_info_add(ToxWindow *self, const char *timestr, const char *name1, cons } /* adds a single queue item to hst if possible. only called once per call to line_info_print() */ -static void line_info_check_queue(ToxWindow *self) +static void line_info_check_queue(ToxWindow *self) { struct history *hst = self->chatwin->hst; struct line_info *line = line_info_ret_queue(hst); diff --git a/src/line_info.h b/src/line_info.h index cb91365..c9bdd39 100644 --- a/src/line_info.h +++ b/src/line_info.h @@ -35,7 +35,7 @@ enum { SYS_MSG, IN_MSG, OUT_MSG, - OUT_MSG_READ, /* for sent messages that have received a read reply. don't set this with line_info_add */ + OUT_MSG_READ, /* for sent messages that have received a read reply. */ IN_ACTION, OUT_ACTION, OUT_ACTION_READ, /* same as OUT_MSG_READ but for actions */ diff --git a/src/misc_tools.c b/src/misc_tools.c index 0b977b2..62cdd2c 100644 --- a/src/misc_tools.c +++ b/src/misc_tools.c @@ -199,9 +199,9 @@ int valid_nick(const char *nick) for (i = 0; nick[i]; ++i) { if ((nick[i] == ' ' && nick[i + 1] == ' ') - || nick[i] == '/' - || nick[i] == '\n' - || nick[i] == '\t' + || nick[i] == '/' + || nick[i] == '\n' + || nick[i] == '\t' || nick[i] == '\v' || nick[i] == '\r') @@ -281,7 +281,7 @@ int get_nick_truncate(Tox *m, char *buf, int friendnum) /* same as get_nick_truncate but for groupchats */ int get_group_nick_truncate(Tox *m, char *buf, int peernum, int groupnum) { - int len = tox_group_peername(m, groupnum, peernum, (uint8_t *) buf); + int len = tox_group_get_peer_name(m, groupnum, peernum, (uint8_t *) buf); if (len == -1) { strcpy(buf, UNKNOWN_NAME); @@ -372,7 +372,7 @@ off_t file_size(const char *path) return st.st_size; } -/* compares the first size bytes of fp to signature. +/* compares the first size bytes of fp to signature. Returns 0 if they are the same, 1 if they differ, and -1 on error. On success this function will seek back to the beginning of fp */ @@ -395,11 +395,7 @@ int check_file_signature(const char *signature, size_t size, FILE *fp) void set_window_title(ToxWindow *self, const char *title, int len) { char cpy[TOXIC_MAX_NAME_LENGTH + 1]; - - if (self->is_groupchat) /* keep groupnumber in title */ - snprintf(cpy, sizeof(cpy), "%d %s", self->num, title); - else - snprintf(cpy, sizeof(cpy), "%s", title); + snprintf(cpy, sizeof(cpy), "%s", title); if (len > MAX_WINDOW_NAME_LENGTH) { strcpy(&cpy[MAX_WINDOW_NAME_LENGTH - 3], "..."); diff --git a/src/toxic.c b/src/toxic.c index 23046b8..f2a0936 100644 --- a/src/toxic.c +++ b/src/toxic.c @@ -136,14 +136,14 @@ void exit_toxic_success(Tox *m) tox_kill(m); endwin(); - + #ifdef X11 /* We have to terminate xtra last coz reasons * Please don't call this anywhere else coz trust me */ terminate_xtra(); #endif /* X11 */ - + exit(EXIT_SUCCESS); } @@ -306,15 +306,21 @@ static Tox *init_tox(void) tox_callback_user_status(m, on_statuschange, NULL); tox_callback_status_message(m, on_statusmessagechange, NULL); tox_callback_friend_action(m, on_action, NULL); - tox_callback_group_invite(m, on_groupinvite, NULL); - tox_callback_group_message(m, on_groupmessage, NULL); - tox_callback_group_action(m, on_groupaction, NULL); - tox_callback_group_namelist_change(m, on_group_namelistchange, NULL); - tox_callback_group_title(m, on_group_titlechange, NULL); tox_callback_file_send_request(m, on_file_sendrequest, NULL); tox_callback_file_control(m, on_file_control, NULL); tox_callback_file_data(m, on_file_data, NULL); tox_callback_read_receipt(m, on_read_receipt, NULL); + tox_callback_group_message(m, on_group_message, NULL); + tox_callback_group_action(m, on_group_action, NULL); + tox_callback_group_private_message(m, on_group_private_message, NULL); + tox_callback_group_op_certificate(m, on_group_op_certificate, NULL); + tox_callback_group_peerlist_update(m, on_group_namelistchange, NULL); + tox_callback_group_peer_join(m, on_group_peer_join, NULL); + tox_callback_group_peer_exit(m, on_group_peer_exit, NULL); + tox_callback_group_nick_change(m, on_group_nick_change, NULL); + tox_callback_group_topic_change(m, on_group_topic_change, NULL); + tox_callback_group_self_join(m, on_group_self_join, NULL); + tox_callback_group_self_timeout(m, on_group_self_timeout, NULL); tox_set_name(m, (uint8_t *) "Toxic User", strlen("Toxic User")); @@ -518,7 +524,7 @@ static void first_time_encrypt(const char *msg) system("clear"); printf("%s ", msg); - if (!strcasecmp(ch, "y\n") || !strcasecmp(ch, "n\n") || !strcasecmp(ch, "yes\n") + if (!strcasecmp(ch, "y\n") || !strcasecmp(ch, "n\n") || !strcasecmp(ch, "yes\n") || !strcasecmp(ch, "no\n") || !strcasecmp(ch, "q\n")) break; @@ -1043,37 +1049,37 @@ int main(int argc, char *argv[]) if (init_xtra(DnD_callback) == -1) queue_init_message("X failed to initialize"); #endif - + Tox *m = init_tox(); - + if (m == NULL) - exit_toxic_err("failed in main", FATALERR_NETWORKINIT); - + exit_toxic_err("failed in main", FATALERR_NETWORKINIT); + if (!arg_opts.ignore_data_file) { if (arg_opts.encrypt_data && !datafile_exists) arg_opts.encrypt_data = 0; - + load_data(m, DATA_FILE); - + } - + init_term(); prompt = init_windows(m); prompt_init_statusbar(prompt, m); - + /* thread for ncurses stuff */ if (pthread_mutex_init(&Winthread.lock, NULL) != 0) exit_toxic_err("failed in main", FATALERR_MUTEX_INIT); - + if (pthread_create(&Winthread.tid, NULL, thread_winref, (void *) m) != 0) exit_toxic_err("failed in main", FATALERR_THREAD_CREATE); - + /* thread for message queue */ if (pthread_create(&cqueue_thread.tid, NULL, thread_cqueue, (void *) m) != 0) exit_toxic_err("failed in main", FATALERR_THREAD_CREATE); - + #ifdef AUDIO - + av = init_audio(prompt, m); /* audio thread */ @@ -1088,11 +1094,11 @@ int main(int argc, char *argv[]) queue_init_message("Failed to init audio devices"); #endif /* AUDIO */ - + init_notify(60, 3000); const char *msg; - + if (config_err) { msg = "Unable to determine configuration directory. Defaulting to 'data' for data file..."; queue_init_message("%s", msg); diff --git a/src/toxic.h b/src/toxic.h index 8c38498..5527060 100644 --- a/src/toxic.h +++ b/src/toxic.h @@ -103,11 +103,6 @@ void on_nickchange(Tox *m, int32_t friendnumber, const uint8_t *string, uint16_t void on_statuschange(Tox *m, int32_t friendnumber, uint8_t status, void *userdata); void on_statusmessagechange(Tox *m, int32_t friendnumber, const uint8_t *string, uint16_t length, void *userdata); void on_friendadded(Tox *m, int32_t friendnumber, bool sort); -void on_groupmessage(Tox *m, int groupnumber, int peernumber, const uint8_t *message, uint16_t length, void *userdata); -void on_groupaction(Tox *m, int groupnumber, int peernumber, const uint8_t *action, uint16_t length, void *userdata); -void on_groupinvite(Tox *m, int32_t friendnumber, uint8_t type, const uint8_t *group_pub_key, uint16_t length, void *userdata); -void on_group_namelistchange(Tox *m, int groupnumber, int peernumber, uint8_t change, void *userdata); -void on_group_titlechange(Tox *m, int groupnumber, int peernumber, const uint8_t *title, uint8_t length, void *userdata); void on_file_sendrequest(Tox *m, int32_t friendnumber, uint8_t filenumber, uint64_t filesize, const uint8_t *pathname, uint16_t pathname_length, void *userdata); void on_file_control(Tox *m, int32_t friendnumber, uint8_t receive_send, uint8_t filenumber, uint8_t control_type, @@ -116,6 +111,18 @@ void on_file_data(Tox *m, int32_t friendnumber, uint8_t filenumber, const uint8_ void on_typing_change(Tox *m, int32_t friendnumber, uint8_t is_typing, void *userdata); void on_read_receipt(Tox *m, int32_t, uint32_t, void *userdata); +void on_group_message(Tox *m, int groupnumber, uint32_t peernumber, const uint8_t *message, uint16_t length, void *userdata); +void on_group_action(Tox *m, int groupnumber, uint32_t peernumber, const uint8_t *action, uint16_t length, void *userdata); +void on_group_private_message(Tox *m, int groupnumber, uint32_t peernumber, const uint8_t *message, uint16_t length, void *userdata); +void on_group_namelistchange(Tox *m, int groupnumber, void *userdata); +void on_group_peer_join(Tox *m, int groupnumber, uint32_t peernumber, void *userdata); +void on_group_peer_exit(Tox *m, int groupnumber, uint32_t peernumber, const uint8_t *partmsg, uint16_t length, void *userdata); +void on_group_topic_change(Tox *m, int groupnumber, uint32_t peernumber, const uint8_t *topic, uint16_t length, void *userdata); +void on_group_nick_change(Tox *m, int groupnumber, uint32_t peernumber, const uint8_t *newname, uint16_t length, void *userdata); +void on_group_op_certificate(Tox *m, int groupnumber, uint32_t src_peernum, uint32_t tgt_peernum, uint8_t cert_type, void *userdata); +void on_group_self_join(Tox *m, int groupnumber, void *userdata); +void on_group_self_timeout(Tox *m, int groupnumber, void *userdata); + #ifdef AUDIO void write_device_callback_group(Tox *m, int groupnum, int peernum, const int16_t *pcm, unsigned int samples, uint8_t channels, unsigned int sample_rate, void *arg); diff --git a/src/windows.c b/src/windows.c index 8282840..21c9215 100644 --- a/src/windows.c +++ b/src/windows.c @@ -161,8 +161,8 @@ void on_friendadded(Tox *m, int32_t friendnumber, bool sort) store_data(m, DATA_FILE); } -void on_groupmessage(Tox *m, int groupnumber, int peernumber, const uint8_t *message, uint16_t length, - void *userdata) +void on_group_message(Tox *m, int groupnumber, uint32_t peernumber, const uint8_t *message, uint16_t length, + void *userdata) { char msg[MAX_STR_SIZE + 1]; length = copy_tox_str(msg, sizeof(msg), (const char *) message, length); @@ -175,8 +175,8 @@ void on_groupmessage(Tox *m, int groupnumber, int peernumber, const uint8_t *mes } } -void on_groupaction(Tox *m, int groupnumber, int peernumber, const uint8_t *action, uint16_t length, - void *userdata) +void on_group_action(Tox *m, int groupnumber, uint32_t peernumber, const uint8_t *action, uint16_t length, + void *userdata) { char msg[MAX_STR_SIZE + 1]; length = copy_tox_str(msg, sizeof(msg), (const char *) action, length); @@ -189,38 +189,117 @@ void on_groupaction(Tox *m, int groupnumber, int peernumber, const uint8_t *acti } } -void on_groupinvite(Tox *m, int32_t friendnumber, uint8_t type, const uint8_t *group_pub_key, uint16_t length, - void *userdata) +void on_group_private_message(Tox *m, int groupnumber, uint32_t peernumber, const uint8_t *message, uint16_t length, + void *userdata) { + char msg[MAX_STR_SIZE + 1]; + length = copy_tox_str(msg, sizeof(msg), (const char *) message, length); + int i; for (i = 0; i < MAX_WINDOWS_NUM; ++i) { - if (windows[i].onGroupInvite != NULL) - windows[i].onGroupInvite(&windows[i], m, friendnumber, type, (char *) group_pub_key, length); + if (windows[i].onGroupPrivateMessage != NULL) + windows[i].onGroupPrivateMessage(&windows[i], m, groupnumber, peernumber, msg, length); } } -void on_group_namelistchange(Tox *m, int groupnumber, int peernumber, uint8_t change, void *userdata) +void on_group_namelistchange(Tox *m, int groupnumber, void *userdata) { int i; for (i = 0; i < MAX_WINDOWS_NUM; ++i) { if (windows[i].onGroupNamelistChange != NULL) - windows[i].onGroupNamelistChange(&windows[i], m, groupnumber, peernumber, change); + windows[i].onGroupNamelistChange(&windows[i], m, groupnumber); } } -void on_group_titlechange(Tox *m, int groupnumber, int peernumber, const uint8_t *title, uint8_t length, - void *userdata) +void on_group_peer_join(Tox *m, int groupnumber, uint32_t peernumber, void *userdata) { - char data[MAX_STR_SIZE + 1]; - length = copy_tox_str(data, sizeof(data), (const char *) title, length); + int i; + + for (i = 0; i < MAX_WINDOWS_NUM; ++i) { + if (windows[i].onGroupPeerJoin != NULL) + windows[i].onGroupPeerJoin(&windows[i], m, groupnumber, peernumber); + } +} + +void on_group_peer_exit(Tox *m, int groupnumber, uint32_t peernumber, const uint8_t *partmsg, uint16_t length, + void *userdata) +{ + char msg[MAX_STR_SIZE + 1]; + + if (length == 0 || !partmsg) { + strcpy(msg, "Quit."); + length = 5; + } else { + length = copy_tox_str(msg, sizeof(msg), (const char *) partmsg, length); + } int i; for (i = 0; i < MAX_WINDOWS_NUM; ++i) { - if (windows[i].onGroupTitleChange != NULL) - windows[i].onGroupTitleChange(&windows[i], m, groupnumber, peernumber, data, length); + if (windows[i].onGroupPeerExit != NULL) + windows[i].onGroupPeerExit(&windows[i], m, groupnumber, peernumber, msg, length); + } +} + +void on_group_topic_change(Tox *m, int groupnumber, uint32_t peernumber, const uint8_t *topic, uint16_t length, + void *userdata) +{ + char data[MAX_STR_SIZE + 1]; + length = copy_tox_str(data, sizeof(data), (const char *) topic, length); + + int i; + + for (i = 0; i < MAX_WINDOWS_NUM; ++i) { + if (windows[i].onGroupTopicChange != NULL) + windows[i].onGroupTopicChange(&windows[i], m, groupnumber, peernumber, data, length); + } +} + +void on_group_nick_change(Tox *m, int groupnumber, uint32_t peernumber, const uint8_t *newname, uint16_t length, + void *userdata) +{ + char name[TOXIC_MAX_NAME_LENGTH + 1]; + length = copy_tox_str(name, sizeof(name), (const char *) newname, length); + filter_str(name, length); + + int i; + + for (i = 0; i < MAX_WINDOWS_NUM; ++i) { + if (windows[i].onGroupNickChange != NULL) + windows[i].onGroupNickChange(&windows[i], m, groupnumber, peernumber, name, length); + } +} + +void on_group_op_certificate(Tox *m, int groupnumber, uint32_t src_peernum, uint32_t tgt_peernum, uint8_t cert_type, + void *userdata) +{ + int i; + + for (i = 0; i < MAX_WINDOWS_NUM; ++i) { + if (windows[i].onGroupOpCertificate != NULL) + windows[i].onGroupOpCertificate(&windows[i], m, groupnumber, src_peernum, tgt_peernum, cert_type); + } +} + +void on_group_self_join(Tox *m, int groupnumber, void *userdata) +{ + int i; + + for (i = 0; i < MAX_WINDOWS_NUM; ++i) { + if (windows[i].onGroupSelfJoin != NULL) + windows[i].onGroupSelfJoin(&windows[i], m, groupnumber); + } +} + +void on_group_self_timeout(Tox *m, int groupnumber, void *userdata) +{ + int i; + + for (i = 0; i < MAX_WINDOWS_NUM; ++i) { + if (windows[i].onGroupSelfTimeout != NULL) + windows[i].onGroupSelfTimeout(&windows[i], m, groupnumber); } } @@ -270,14 +349,14 @@ void on_read_receipt(Tox *m, int32_t friendnumber, uint32_t receipt, void *userd } #ifdef AUDIO -void write_device_callback_group(Tox *m, int groupnum, int peernum, const int16_t *pcm, unsigned int samples, +void write_device_callback_group(Tox *m, int groupnum, int peernumber, const int16_t *pcm, unsigned int samples, uint8_t channels, unsigned int sample_rate, void *arg) { int i; for (i = 0; i < MAX_WINDOWS_NUM; ++i) { if (windows[i].onWriteDevice != NULL) - windows[i].onWriteDevice(&windows[i], m, groupnum, peernum, pcm, samples, channels, samples); + windows[i].onWriteDevice(&windows[i], m, groupnum, peernumber, pcm, samples, channels, samples); } } #endif /* AUDIO */ @@ -529,7 +608,7 @@ void draw_active_window(Tox *m) } } -/* refresh inactive windows to prevent scrolling bugs. +/* refresh inactive windows to prevent scrolling bugs. call at least once per second */ void refresh_inactive_windows(void) { @@ -575,7 +654,7 @@ void kill_all_windows(Tox *m) if (windows[i].is_chat) kill_chat_window(&windows[i], m); else if (windows[i].is_groupchat) - close_groupchat(&windows[i], m, i); + close_groupchat(&windows[i], m, i, "Quit.", 5); } kill_prompt_window(prompt); diff --git a/src/windows.h b/src/windows.h index 73f027c..a368b6c 100644 --- a/src/windows.h +++ b/src/windows.h @@ -117,17 +117,24 @@ struct ToxWindow { void(*onStatusChange)(ToxWindow *, Tox *, int32_t, uint8_t); void(*onStatusMessageChange)(ToxWindow *, int32_t, const char *, uint16_t); void(*onAction)(ToxWindow *, Tox *, int32_t, const char *, uint16_t); - void(*onGroupMessage)(ToxWindow *, Tox *, int, int, const char *, uint16_t); - void(*onGroupAction)(ToxWindow *, Tox *, int, int, const char *, uint16_t); - void(*onGroupInvite)(ToxWindow *, Tox *, int32_t, uint8_t, const char *, uint16_t); - void(*onGroupNamelistChange)(ToxWindow *, Tox *, int, int, uint8_t); - void(*onGroupTitleChange)(ToxWindow *, Tox *, int, int, const char *, uint8_t); void(*onFileSendRequest)(ToxWindow *, Tox *, int32_t, uint8_t, uint64_t, const char *, uint16_t); void(*onFileControl)(ToxWindow *, Tox *, int32_t, uint8_t, uint8_t, uint8_t, const char *, uint16_t); void(*onFileData)(ToxWindow *, Tox *, int32_t, uint8_t, const char *, uint16_t); void(*onTypingChange)(ToxWindow *, Tox *, int32_t, uint8_t); void(*onReadReceipt)(ToxWindow *, Tox *, int32_t, uint32_t); + void(*onGroupMessage)(ToxWindow *, Tox *, int, int, const char *, uint16_t); + void(*onGroupAction)(ToxWindow *, Tox *, int, int, const char *, uint16_t); + void(*onGroupPrivateMessage)(ToxWindow *, Tox *, int, uint32_t, const char *, uint16_t); + void(*onGroupOpCertificate)(ToxWindow *, Tox *, int, uint32_t, uint32_t, uint8_t); + void(*onGroupNamelistChange)(ToxWindow *, Tox *, int); + void(*onGroupPeerJoin)(ToxWindow *, Tox *, int, uint32_t); + void(*onGroupPeerExit)(ToxWindow *, Tox *, int, uint32_t, const char *, uint16_t); + void(*onGroupNickChange)(ToxWindow *, Tox *, int, uint32_t, const char *, uint16_t); + void(*onGroupTopicChange)(ToxWindow *, Tox *, int, uint32_t, const char *, uint16_t); + void(*onGroupSelfJoin)(ToxWindow *, Tox *, int); + void(*onGroupSelfTimeout)(ToxWindow *, Tox *, int); + #ifdef AUDIO void(*onInvite)(ToxWindow *, ToxAv *, int); @@ -143,7 +150,7 @@ struct ToxWindow { void(*onPeerTimeout)(ToxWindow *, ToxAv *, int); void(*onWriteDevice)(ToxWindow *, Tox *, int, int, const int16_t *, unsigned int, uint8_t, unsigned int); - int call_idx; /* If in a call will have this index set, otherwise it's -1. + int call_idx; /* If in a call will have this index set, otherwise it's -1. * Don't modify outside av callbacks. */ int device_selection[2]; /* -1 if not set, if set uses these selections instead of primary device */ @@ -151,7 +158,7 @@ struct ToxWindow { #endif /* AUDIO */ int active_box; /* For box notify */ - + char name[TOXIC_MAX_NAME_LENGTH + 1]; int32_t num; /* corresponds to friendnumber in chat windows */ bool active; @@ -252,7 +259,7 @@ void on_window_resize(void); void force_refresh(WINDOW *w); ToxWindow *get_window_ptr(int i); -/* refresh inactive windows to prevent scrolling bugs. +/* refresh inactive windows to prevent scrolling bugs. call at least once per second */ void refresh_inactive_windows(void); From b3ab0bde053cd25868e6c466275d9ec47a6a56db Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Sun, 4 Jan 2015 17:22:24 -0500 Subject: [PATCH 02/45] a couple fixes --- src/global_commands.c | 6 ++++-- src/group_commands.c | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/global_commands.c b/src/global_commands.c index a513115..9d5d2e6 100644 --- a/src/global_commands.c +++ b/src/global_commands.c @@ -400,12 +400,14 @@ void cmd_join(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA id_bin[i] = x; } - if (tox_group_new_join(m, (uint8_t *) id_bin) == -1) { + int groupnum = tox_group_new_join(m, (uint8_t *) id_bin); + + if (groupnum == -1) { line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group chat instance failed to initialize."); return; } - if (init_groupchat_win(prompt, m, self->num, NULL, 0) == -1) { + if (init_groupchat_win(prompt, m, groupnum, NULL, 0) == -1) { line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group chat window failed to initialize."); tox_group_delete(m, self->num, NULL, 0); return; diff --git a/src/group_commands.c b/src/group_commands.c index 8f54c2a..3692c8a 100644 --- a/src/group_commands.c +++ b/src/group_commands.c @@ -67,7 +67,7 @@ void cmd_set_topic(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*arg int sn_len = tox_group_get_self_name(m, self->num, (uint8_t *) selfnick); selfnick[sn_len] = '\0'; - line_info_add(self, timefrmt, selfnick, NULL, NAME_CHANGE, 0, 0, " set the group topic to: %s", topic); + line_info_add(self, timefrmt, selfnick, NULL, SYS_MSG, 0, 0, " set the group topic to: %s", topic); char tmp_event[MAX_STR_SIZE]; snprintf(tmp_event, sizeof(tmp_event), "set topic to %s", topic); From ff3da5f657e335f732e1bcb8836c5ade94534f21 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Sun, 11 Jan 2015 16:48:40 -0500 Subject: [PATCH 03/45] implement group status/nick changes, various fixes --- src/global_commands.c | 22 +++++++--- src/group_commands.c | 2 +- src/groupchat.c | 93 +++++++++++++++++++++++++++++++------------ src/groupchat.h | 5 ++- src/misc_tools.c | 16 +++++--- src/misc_tools.h | 5 ++- src/prompt.c | 15 +++---- src/windows.c | 4 +- 8 files changed, 113 insertions(+), 49 deletions(-) diff --git a/src/global_commands.c b/src/global_commands.c index 9d5d2e6..c78e5ce 100644 --- a/src/global_commands.c +++ b/src/global_commands.c @@ -326,7 +326,7 @@ void cmd_groupchat(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*arg } if (argc < 1) { - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Error: Please specify the group name."); + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group name required"); return; } @@ -334,7 +334,7 @@ void cmd_groupchat(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*arg int len = strlen(tmp_name); if (len == 0 || len > TOX_MAX_GROUP_NAME_LENGTH) { - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Error: Invalid group name."); + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid group name."); return; } @@ -370,14 +370,14 @@ void cmd_join(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA } if (argc < 1) { - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Error: Group chat ID is required."); + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group chat ID is required."); return; } const char *chat_id = argv[1]; if (strlen(chat_id) != TOX_GROUP_CHAT_ID_SIZE * 2) { - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Error: Invalid chat ID"); + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid chat ID"); return; } @@ -506,8 +506,13 @@ void cmd_nick(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA len = MIN(len, TOXIC_MAX_NAME_LENGTH - 1); nick[len] = '\0'; - tox_set_name(m, (uint8_t *) nick, (uint16_t) len); + if (tox_set_name(m, (uint8_t *) nick, (uint16_t) len) == -1) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Core error setting nick."); + return; + } + prompt_update_nick(prompt, nick); + set_nick_all_groups(m, nick, len); store_data(m, DATA_FILE); } @@ -604,7 +609,12 @@ void cmd_status(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[ return; } - tox_set_user_status(m, status_kind); + if (tox_set_user_status(m, status_kind) == -1) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Core failed to set status\n"); + return; + } + + set_status_all_groups(m, status_kind); prompt_update_status(prompt, status_kind); if (have_note) { diff --git a/src/group_commands.c b/src/group_commands.c index 3692c8a..8f54c2a 100644 --- a/src/group_commands.c +++ b/src/group_commands.c @@ -67,7 +67,7 @@ void cmd_set_topic(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*arg int sn_len = tox_group_get_self_name(m, self->num, (uint8_t *) selfnick); selfnick[sn_len] = '\0'; - line_info_add(self, timefrmt, selfnick, NULL, SYS_MSG, 0, 0, " set the group topic to: %s", topic); + line_info_add(self, timefrmt, selfnick, NULL, NAME_CHANGE, 0, 0, " set the group topic to: %s", topic); char tmp_event[MAX_STR_SIZE]; snprintf(tmp_event, sizeof(tmp_event), "set topic to %s", topic); diff --git a/src/groupchat.c b/src/groupchat.c index 80a5988..ff89a42 100644 --- a/src/groupchat.c +++ b/src/groupchat.c @@ -129,7 +129,8 @@ int init_groupchat_win(ToxWindow *prompt, Tox *m, int groupnum, const char *grou groupchats[i].chatwin = add_window(m, self); groupchats[i].active = true; groupchats[i].peer_names = malloc(sizeof(uint8_t) * TOX_MAX_NAME_LENGTH); - groupchats[i].peer_name_lengths = malloc(sizeof(uint32_t)); + groupchats[i].peer_name_lengths = malloc(sizeof(uint16_t)); + groupchats[i].groupnumber = groupnum; if (groupchats[i].peer_names == NULL || groupchats[i].peer_name_lengths == NULL) exit_toxic_err("failed in init_groupchat_win", FATALERR_MEMORY); @@ -184,6 +185,33 @@ void close_groupchat(ToxWindow *self, Tox *m, int groupnum, const char *partmess kill_groupchat_window(self); } +/* Note: the arguments to these functions are validated in the caller functions */ +void set_nick_all_groups(Tox *m, const char *nick, uint16_t length) +{ + char timefrmt[TIME_STR_SIZE]; + get_time_str(timefrmt, sizeof(timefrmt)); + + int i; + + for (i = 0; i < max_groupchat_index; ++i) { + if (groupchats[i].active) { + ToxWindow *self = get_window_ptr(groupchats[i].chatwin); + tox_group_set_name(m, groupchats[i].groupnumber, (uint8_t *) nick, length); + line_info_add(self, timefrmt, NULL, nick, NAME_CHANGE, 0, MAGENTA, "You are now known as "); + } + } +} + +void set_status_all_groups(Tox *m, uint8_t status) +{ + int i; + + for (i = 0; i < max_groupchat_index; ++i) { + if (groupchats[i].active) + tox_group_set_status(m, groupchats[i].groupnumber, status); + } +} + /* destroys and re-creates groupchat window with or without the peerlist */ void redraw_groupchat_win(ToxWindow *self) { @@ -328,20 +356,20 @@ static void groupchat_onGroupTopicChange(ToxWindow *self, Tox *m, int groupnum, line_info_add(self, timefrmt, nick, NULL, NAME_CHANGE, 0, 0, " set the group topic to: %s", topic); char tmp_event[MAX_STR_SIZE]; - snprintf(tmp_event, sizeof(tmp_event), "set topic to %s", topic); + snprintf(tmp_event, sizeof(tmp_event), " set the group topic to %s", topic); write_to_log(tmp_event, nick, ctx->log, true); } /* Copies peer names/lengths */ -static void copy_peernames(int gnum, uint8_t peerlist[][TOX_MAX_NAME_LENGTH], uint32_t lengths[], int npeers) +static void copy_peernames(int gnum, uint8_t peerlist[][TOX_MAX_NAME_LENGTH], uint16_t lengths[], int npeers) { free(groupchats[gnum].peer_names); free(groupchats[gnum].peer_name_lengths); int N = TOX_MAX_NAME_LENGTH; - groupchats[gnum].peer_names = calloc(1, sizeof(uint8_t) * npeers * N); - groupchats[gnum].peer_name_lengths = calloc(1, sizeof(uint32_t) * npeers); + groupchats[gnum].peer_names = calloc(1, sizeof(uint8_t) * MAX(1, npeers) * N); + groupchats[gnum].peer_name_lengths = calloc(1, sizeof(uint32_t) * MAX(1, npeers)); if (groupchats[gnum].peer_names == NULL || groupchats[gnum].peer_name_lengths == NULL) exit_toxic_err("failed in copy_peernames", FATALERR_MEMORY); @@ -373,14 +401,14 @@ static void groupchat_onGroupNamelistChange(ToxWindow *self, Tox *m, int groupnu return; int num_peers = tox_group_get_number_peers(m, groupnum); - groupchats[groupnum].num_peers = num_peers; uint8_t tmp_peerlist[num_peers][TOX_MAX_NAME_LENGTH]; - uint32_t tmp_peerlens[num_peers]; + uint16_t tmp_peerlens[num_peers]; if (tox_group_get_names(m, groupnum, tmp_peerlist, tmp_peerlens, num_peers) == -1) - return; + num_peers = 0; + groupchats[groupnum].num_peers = num_peers; copy_peernames(groupnum, tmp_peerlist, tmp_peerlens, num_peers); } @@ -422,7 +450,7 @@ static void groupchat_onGroupPeerExit(ToxWindow *self, Tox *m, int groupnum, uin char timefrmt[TIME_STR_SIZE]; get_time_str(timefrmt, sizeof(timefrmt)); - line_info_add(self, timefrmt, name, NULL, CONNECTION, 0, GREEN, "has left the room (%s)", partmessage); + line_info_add(self, timefrmt, name, NULL, CONNECTION, 0, RED, "has left the room (%s)", partmessage); char log_str[TOXIC_MAX_NAME_LENGTH + MAX_STR_SIZE]; snprintf(log_str, sizeof(log_str), "%s has left the room (%s)", name, partmessage); @@ -436,20 +464,25 @@ static void groupchat_onGroupSelfJoin(ToxWindow *self, Tox *m, int groupnum) if (groupnum != self->num) return; - char groupname[TOX_MAX_GROUP_NAME_LENGTH]; - int len = tox_group_get_group_name(m, groupnum, (uint8_t *) groupname); + char tmp_groupname[TOX_MAX_GROUP_NAME_LENGTH]; + int glen = tox_group_get_group_name(m, groupnum, (uint8_t *) tmp_groupname); - if (len > 0) - set_window_title(self, groupname, len); + char groupname[TOX_MAX_GROUP_NAME_LENGTH]; + copy_tox_str(groupname, sizeof(groupname), tmp_groupname, glen); + + if (glen > 0) + set_window_title(self, groupname, glen); + + char tmp_topic[TOX_MAX_GROUP_TOPIC_LENGTH]; + int tlen = tox_group_get_topic(m, groupnum, (uint8_t *) tmp_topic); char topic[TOX_MAX_GROUP_TOPIC_LENGTH]; - tox_group_get_topic(m, groupnum, (uint8_t *) topic); + copy_tox_str(topic, sizeof(topic), tmp_topic, tlen); char timefrmt[TIME_STR_SIZE]; get_time_str(timefrmt, sizeof(timefrmt)); - line_info_add(self, timefrmt, NULL, NULL, SYS_MSG, 0, 0, "Connected."); - line_info_add(self, timefrmt, NULL, NULL, SYS_MSG, 0, 0, "Topic set to: %s", topic); + line_info_add(self, timefrmt, NULL, NULL, SYS_MSG, 0, MAGENTA, "-!- Topic set to: %s", topic); } static void groupchat_onGroupSelfTimeout(ToxWindow *self, Tox *m, int groupnum) @@ -507,7 +540,7 @@ static void groupchat_onGroupNickChange(ToxWindow *self, Tox *m, int groupnum, u char timefrmt[TIME_STR_SIZE]; get_time_str(timefrmt, sizeof(timefrmt)); - line_info_add(self, timefrmt, oldnick, (char *) newnick, NAME_CHANGE, 0, MAGENTA, "is now known as"); + line_info_add(self, timefrmt, oldnick, newnick, NAME_CHANGE, 0, MAGENTA, " is now known as "); } @@ -631,7 +664,12 @@ static void groupchat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr) if (line[0] == '/') { if (strncmp(line, "/close", 6) == 0) { - close_groupchat(self, m, self->num, line + 6, ctx->len - 6); + int offset = 6; + + if (line[offset] != '\0') + ++offset; + + close_groupchat(self, m, self->num, line + offset, ctx->len - offset); return; } else if (strncmp(line, "/me ", strlen("/me ")) == 0) { send_group_action(self, m, self->num, line + strlen("/me ")); @@ -693,7 +731,18 @@ static void groupchat_onDraw(ToxWindow *self, Tox *m) memcpy(tmpnck, &groupchats[self->num].peer_names[peer * TOX_MAX_NAME_LENGTH], maxlen); tmpnck[maxlen] = '\0'; + /* TODO: Make this not poll */ + uint8_t status = tox_group_get_status(m, self->num, i); + int colour = WHITE; + + if (status == TOX_GS_AWAY) + colour = YELLOW; + else if (status == TOX_GS_BUSY) + colour = RED; + + wattron(ctx->sidebar, COLOR_PAIR(colour)); wprintw(ctx->sidebar, "%s\n", tmpnck); + wattroff(ctx->sidebar, COLOR_PAIR(colour)); } } @@ -736,14 +785,6 @@ static void groupchat_onInit(ToxWindow *self, Tox *m) execute(ctx->history, self, m, "/log", GLOBAL_COMMAND_MODE); - char selfname[TOX_MAX_NAME_LENGTH]; - uint16_t len = tox_get_self_name(m, (uint8_t *) selfname); - selfname[len] = '\0'; - tox_group_set_name(m, self->num, (uint8_t *) selfname, len); - - uint8_t status = tox_get_self_user_status(m); - tox_group_set_status(m, self->num, status); - scrollok(ctx->history, 0); wmove(self->window, y2 - CURS_Y_OFFSET, 0); } diff --git a/src/groupchat.h b/src/groupchat.h index 1118e58..0305358 100644 --- a/src/groupchat.h +++ b/src/groupchat.h @@ -59,12 +59,13 @@ struct GAudio { #endif /* AUDIO */ typedef struct { + int groupnumber; int chatwin; bool active; int num_peers; int side_pos; /* current position of the sidebar - used for scrolling up and down */ uint8_t *peer_names; - uint32_t *peer_name_lengths; + uint16_t *peer_name_lengths; #ifdef AUDIO struct GAudio audio; #endif @@ -72,6 +73,8 @@ typedef struct { void close_groupchat(ToxWindow *self, Tox *m, int groupnum, const char *partmessage, int length); int init_groupchat_win(ToxWindow *prompt, Tox *m, int groupnum, const char *groupname, int length); +void set_nick_all_groups(Tox *m, const char *nick, uint16_t length); +void set_status_all_groups(Tox *m, uint8_t status); /* destroys and re-creates groupchat window with or without the peerlist */ void redraw_groupchat_win(ToxWindow *self); diff --git a/src/misc_tools.c b/src/misc_tools.c index 62cdd2c..6c87602 100644 --- a/src/misc_tools.c +++ b/src/misc_tools.c @@ -295,13 +295,19 @@ int get_group_nick_truncate(Tox *m, char *buf, int peernum, int groupnum) } /* copies data to msg buffer. - returns length of msg, which will be no larger than size-1 */ + returns length of msg. + returns 0 and nulls msg if length is too big for buffer size */ uint16_t copy_tox_str(char *msg, size_t size, const char *data, uint16_t length) { - int len = MIN(length, size - 1); - memcpy(msg, data, len); - msg[len] = '\0'; - return len; + if (length > size - 1) { + length = 0; + msg[0] = '\0'; + return length; + } + + memcpy(msg, data, length); + msg[length] = '\0'; + return length; } /* returns index of the first instance of ch in s starting at idx. diff --git a/src/misc_tools.h b/src/misc_tools.h index 20fd17e..970faaa 100644 --- a/src/misc_tools.h +++ b/src/misc_tools.h @@ -108,7 +108,8 @@ int get_nick_truncate(Tox *m, char *buf, int friendnum); int get_group_nick_truncate(Tox *m, char *buf, int peernum, int groupnum); /* copies data to msg buffer. - returns length of msg, which will be no larger than size-1 */ + returns length of msg. + returns 0 and nulls msg if length is too big for buffer size */ uint16_t copy_tox_str(char *msg, size_t size, const char *data, uint16_t length); /* returns index of the first instance of ch in s starting at idx. @@ -128,7 +129,7 @@ bool file_exists(const char *path); /* returns file size or -1 on error */ off_t file_size(const char *path); -/* compares the first size bytes of fp and signature. +/* compares the first size bytes of fp and signature. Returns 0 if they are the same, 1 if they differ, and -1 on error. On success this function will seek back to the beginning of fp */ diff --git a/src/prompt.c b/src/prompt.c index 99c2a4a..66f8838 100644 --- a/src/prompt.c +++ b/src/prompt.c @@ -49,9 +49,9 @@ extern struct Winthread Winthread; FriendRequests FrndRequests; #ifdef AUDIO -#define AC_NUM_GLOB_COMMANDS 18 +#define AC_NUM_GLOB_COMMANDS 19 #else -#define AC_NUM_GLOB_COMMANDS 16 +#define AC_NUM_GLOB_COMMANDS 17 #endif /* AUDIO */ /* Array of global command names used for tab completion. */ @@ -65,6 +65,7 @@ static const char glob_cmd_list[AC_NUM_GLOB_COMMANDS][MAX_CMDNAME_SIZE] = { { "/exit" }, { "/group" }, { "/help" }, + { "/join" }, { "/log" }, { "/myid" }, { "/nick" }, @@ -81,7 +82,7 @@ static const char glob_cmd_list[AC_NUM_GLOB_COMMANDS][MAX_CMDNAME_SIZE] = { #endif /* AUDIO */ }; -void kill_prompt_window(ToxWindow *self) +void kill_prompt_window(ToxWindow *self) { ChatContext *ctx = self->chatwin; StatusBar *statusbar = self->stb; @@ -116,7 +117,7 @@ void prompt_update_statusmessage(ToxWindow *prompt, Tox *m, const char *statusms snprintf(statusbar->statusmsg, sizeof(statusbar->statusmsg), "%s", statusmsg); int len = strlen(statusbar->statusmsg); statusbar->statusmsg_len = len; - tox_set_status_message(m, (uint8_t *) statusmsg, (uint64_t) len); + tox_set_status_message(m, (uint8_t *) statusmsg, (uint64_t) len); } /* Updates own status in prompt statusbar */ @@ -350,7 +351,7 @@ static void prompt_onConnectionChange(ToxWindow *self, Tox *m, int32_t friendnum write_to_log(msg, nick, ctx->log, true); if (self->active_box != -1) - box_notify2(self, user_log_in, NT_WNDALERT_2 | NT_NOTIFWND | NT_RESTOL, self->active_box, + box_notify2(self, user_log_in, NT_WNDALERT_2 | NT_NOTIFWND | NT_RESTOL, self->active_box, "%s has come online", nick ); else box_notify(self, user_log_in, NT_WNDALERT_2 | NT_NOTIFWND | NT_RESTOL, &self->active_box, @@ -361,7 +362,7 @@ static void prompt_onConnectionChange(ToxWindow *self, Tox *m, int32_t friendnum write_to_log(msg, nick, ctx->log, true); if (self->active_box != -1) - box_notify2(self, user_log_out, NT_WNDALERT_2 | NT_NOTIFWND | NT_RESTOL, self->active_box, + box_notify2(self, user_log_out, NT_WNDALERT_2 | NT_NOTIFWND | NT_RESTOL, self->active_box, "%s has gone offline", nick ); else box_notify(self, user_log_out, NT_WNDALERT_2 | NT_NOTIFWND | NT_RESTOL, &self->active_box, @@ -501,6 +502,6 @@ ToxWindow new_prompt(void) ret.help = help; ret.active_box = -1; - + return ret; } diff --git a/src/windows.c b/src/windows.c index 21c9215..bd25d27 100644 --- a/src/windows.c +++ b/src/windows.c @@ -229,7 +229,7 @@ void on_group_peer_exit(Tox *m, int groupnumber, uint32_t peernumber, const uint char msg[MAX_STR_SIZE + 1]; if (length == 0 || !partmsg) { - strcpy(msg, "Quit."); + strcpy(msg, "Quit"); length = 5; } else { length = copy_tox_str(msg, sizeof(msg), (const char *) partmsg, length); @@ -260,10 +260,12 @@ void on_group_topic_change(Tox *m, int groupnumber, uint32_t peernumber, const u void on_group_nick_change(Tox *m, int groupnumber, uint32_t peernumber, const uint8_t *newname, uint16_t length, void *userdata) { + fprintf(stderr, "newname before: %s. len: %d\n", newname, length); char name[TOXIC_MAX_NAME_LENGTH + 1]; length = copy_tox_str(name, sizeof(name), (const char *) newname, length); filter_str(name, length); + fprintf(stderr, "newname before: %s. len: %d\n", name, length); int i; for (i = 0; i < MAX_WINDOWS_NUM; ++i) { From 89637e7d2f65ec75d4f2b06109a3ee2b69746ea4 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Mon, 12 Jan 2015 01:09:56 -0500 Subject: [PATCH 04/45] implement group join rejection callback --- src/groupchat.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++--- src/groupchat.h | 1 + src/toxic.c | 1 + src/toxic.h | 1 + src/windows.c | 10 ++++++++ src/windows.h | 1 + 6 files changed, 72 insertions(+), 3 deletions(-) diff --git a/src/groupchat.c b/src/groupchat.c index ff89a42..703a31e 100644 --- a/src/groupchat.c +++ b/src/groupchat.c @@ -196,8 +196,14 @@ void set_nick_all_groups(Tox *m, const char *nick, uint16_t length) for (i = 0; i < max_groupchat_index; ++i) { if (groupchats[i].active) { ToxWindow *self = get_window_ptr(groupchats[i].chatwin); - tox_group_set_name(m, groupchats[i].groupnumber, (uint8_t *) nick, length); - line_info_add(self, timefrmt, NULL, nick, NAME_CHANGE, 0, MAGENTA, "You are now known as "); + int ret = tox_group_set_name(m, groupchats[i].groupnumber, (uint8_t *) nick, length); + + if (ret == -1 && groupchats[i].is_connected) + line_info_add(self, timefrmt, NULL, 0, SYS_MSG, 0, 0, "Invalid nick"); + else if (ret == -2) + line_info_add(self, timefrmt, NULL, 0, SYS_MSG, 0, RED, "-!- That nick is already in use"); + else + line_info_add(self, timefrmt, NULL, nick, NAME_CHANGE, 0, MAGENTA, "You are now known as "); } } } @@ -482,6 +488,15 @@ static void groupchat_onGroupSelfJoin(ToxWindow *self, Tox *m, int groupnum) char timefrmt[TIME_STR_SIZE]; get_time_str(timefrmt, sizeof(timefrmt)); + int i; + + for (i = 0; i < max_groupchat_index; ++i) { + if (groupchats[i].active && groupchats[i].groupnumber == groupnum) { + groupchats[i].is_connected = true; + break; + } + } + line_info_add(self, timefrmt, NULL, NULL, SYS_MSG, 0, MAGENTA, "-!- Topic set to: %s", topic); } @@ -490,7 +505,46 @@ static void groupchat_onGroupSelfTimeout(ToxWindow *self, Tox *m, int groupnum) if (groupnum != self->num) return; - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Disconnected from group. Attempting to reconnect..."); + int i; + + for (i = 0; i < max_groupchat_index; ++i) { + if (groupchats[i].active && groupchats[i].groupnumber == groupnum) { + groupchats[i].is_connected = false; + break; + } + } + + char timefrmt[TIME_STR_SIZE]; + get_time_str(timefrmt, sizeof(timefrmt)); + + line_info_add(self, timefrmt, NULL, NULL, SYS_MSG, 0, RED, "-!- Disconnected from group"); +} + +static void groupchat_onGroupRejected(ToxWindow *self, Tox *m, int groupnum, uint8_t type) +{ + if (groupnum != self->num) + return; + + const char *msg; + + switch (type) { + case TOX_GJ_NICK_TAKEN: + msg = "That nick is already in use. Please change your nick with the '/nick' command."; + break; + case TOX_GJ_GROUP_FULL: + msg = "Group is full."; + break; + case TOX_GJ_INVITES_DISABLED: + msg = "Invites for this group have been disabled."; + break; + default: + return; + } + + char timefrmt[TIME_STR_SIZE]; + get_time_str(timefrmt, sizeof(timefrmt)); + + line_info_add(self, timefrmt, NULL, NULL, SYS_MSG, 0, RED, "-!- %s", msg); } static void groupchat_onGroupOpCertificate(ToxWindow *self, Tox *m, int groupnum, uint32_t src_peernum, @@ -929,6 +983,7 @@ ToxWindow new_group_chat(Tox *m, int groupnum, const char *groupname, int length ret.onGroupNickChange = &groupchat_onGroupNickChange; ret.onGroupSelfJoin = &groupchat_onGroupSelfJoin; ret.onGroupSelfTimeout = &groupchat_onGroupSelfTimeout; + ret.onGroupRejected = &groupchat_onGroupRejected; #ifdef AUDIO ret.onWriteDevice = &groupchat_onWriteDevice; diff --git a/src/groupchat.h b/src/groupchat.h index 0305358..9b235b3 100644 --- a/src/groupchat.h +++ b/src/groupchat.h @@ -62,6 +62,7 @@ typedef struct { int groupnumber; int chatwin; bool active; + bool is_connected; int num_peers; int side_pos; /* current position of the sidebar - used for scrolling up and down */ uint8_t *peer_names; diff --git a/src/toxic.c b/src/toxic.c index f2a0936..edeea94 100644 --- a/src/toxic.c +++ b/src/toxic.c @@ -321,6 +321,7 @@ static Tox *init_tox(void) tox_callback_group_topic_change(m, on_group_topic_change, NULL); tox_callback_group_self_join(m, on_group_self_join, NULL); tox_callback_group_self_timeout(m, on_group_self_timeout, NULL); + tox_callback_group_rejected(m, on_group_rejected, NULL); tox_set_name(m, (uint8_t *) "Toxic User", strlen("Toxic User")); diff --git a/src/toxic.h b/src/toxic.h index 5527060..b0da87e 100644 --- a/src/toxic.h +++ b/src/toxic.h @@ -122,6 +122,7 @@ void on_group_nick_change(Tox *m, int groupnumber, uint32_t peernumber, const ui void on_group_op_certificate(Tox *m, int groupnumber, uint32_t src_peernum, uint32_t tgt_peernum, uint8_t cert_type, void *userdata); void on_group_self_join(Tox *m, int groupnumber, void *userdata); void on_group_self_timeout(Tox *m, int groupnumber, void *userdata); +void on_group_rejected(Tox *m, int groupnumber, uint8_t type, void *userdata); #ifdef AUDIO void write_device_callback_group(Tox *m, int groupnum, int peernum, const int16_t *pcm, unsigned int samples, diff --git a/src/windows.c b/src/windows.c index bd25d27..2c5911f 100644 --- a/src/windows.c +++ b/src/windows.c @@ -305,6 +305,16 @@ void on_group_self_timeout(Tox *m, int groupnumber, void *userdata) } } +void on_group_rejected(Tox *m, int groupnumber, uint8_t type, void *userdata) +{ + int i; + + for (i = 0; i < MAX_WINDOWS_NUM; ++i) { + if (windows[i].onGroupRejected != NULL) + windows[i].onGroupRejected(&windows[i], m, groupnumber, type); + } +} + void on_file_sendrequest(Tox *m, int32_t friendnumber, uint8_t filenumber, uint64_t filesize, const uint8_t *filename, uint16_t filename_length, void *userdata) { diff --git a/src/windows.h b/src/windows.h index a368b6c..53f7cd5 100644 --- a/src/windows.h +++ b/src/windows.h @@ -134,6 +134,7 @@ struct ToxWindow { void(*onGroupTopicChange)(ToxWindow *, Tox *, int, uint32_t, const char *, uint16_t); void(*onGroupSelfJoin)(ToxWindow *, Tox *, int); void(*onGroupSelfTimeout)(ToxWindow *, Tox *, int); + void(*onGroupRejected)(ToxWindow *, Tox *, int, uint8_t); #ifdef AUDIO From 7ee858110c319d124df199adc95dce3655782233 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Mon, 12 Jan 2015 15:03:23 -0500 Subject: [PATCH 05/45] improve command parsing so you don't need quotes & add group ignoring --- src/execute.c | 61 ++++++++++++++++++++++++++++++++-- src/global_commands.c | 13 +------- src/group_commands.c | 76 ++++++++++++++++++++++++++++++++++--------- src/group_commands.h | 2 ++ src/groupchat.c | 25 +++++++++++--- src/groupchat.h | 1 + src/help.c | 8 +++-- src/misc_tools.c | 3 +- 8 files changed, 150 insertions(+), 39 deletions(-) diff --git a/src/execute.c b/src/execute.c index ea64117..c2c2803 100644 --- a/src/execute.c +++ b/src/execute.c @@ -83,6 +83,8 @@ static struct cmd_func chat_commands[] = { static struct cmd_func group_commands[] = { { "/topic", cmd_set_topic }, { "/chatid", cmd_chatid }, + { "/ignore", cmd_ignore }, + { "/unignore", cmd_unignore }, #ifdef AUDIO { "/mute", cmd_mute }, { "/sense", cmd_sense }, @@ -90,10 +92,65 @@ static struct cmd_func group_commands[] = { { NULL, NULL }, }; -/* Parses input command and puts args into arg array. - Returns number of arguments on success, -1 on failure. */ +#define SPECIAL_COMMANDS 9 +static const char special_commands[SPECIAL_COMMANDS][MAX_CMDNAME_SIZE] = { + "/ban", + "/deop", + "/group", + "/ignore", + "/nick", + "/note", + "/op", + "/topic", + "/unignore" +}; + +/* return true if input command is in the special_commands array. False otherwise.*/ +static bool is_special_command(const char *input) +{ + int s = char_find(0, input, ' '); + + if (s == strlen(input)) + return false; + + int i; + + for (i = 0; i < SPECIAL_COMMANDS; ++i) { + if (strncmp(input, special_commands[i], s) == 0) + return true; + } + + return false; +} + +/* Parses commands in the special_commands array which take exactly one argument that may contain spaces. + * Unlike parse_command, this function does not split the input string at spaces. + * Returns number of arguments on success, returns -1 on failure + */ +static int parse_special_command(WINDOW *w, ToxWindow *self, const char *input, char (*args)[MAX_STR_SIZE]) +{ + int len = strlen(input); + int s = char_find(0, input, ' '); + + if (s + 1 >= len) + return -1; + + memcpy(args[0], input, s); + args[0][s++] = '\0'; /* increment to remove space after /command */ + memcpy(args[1], input + s, len - s); + args[1][len - s] = '\0'; + + return 2; +} + +/* Parses input command and puts args (split by spaces) into args array. + * Returns number of arguments on success, -1 on failure. + */ static int parse_command(WINDOW *w, ToxWindow *self, const char *input, char (*args)[MAX_STR_SIZE]) { + if (is_special_command(input)) + return parse_special_command(w, self, input, args); + char *cmd = strdup(input); if (cmd == NULL) diff --git a/src/global_commands.c b/src/global_commands.c index c78e5ce..d812649 100644 --- a/src/global_commands.c +++ b/src/global_commands.c @@ -524,18 +524,7 @@ void cmd_note(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA return; } - if (argv[1][0] != '\"') { - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Note must be enclosed in quotes."); - return; - } - - /* remove opening and closing quotes */ - char msg[MAX_STR_SIZE]; - snprintf(msg, sizeof(msg), "%s", &argv[1][1]); - int len = strlen(msg) - 1; - msg[len] = '\0'; - - prompt_update_statusmessage(prompt, m, msg); + prompt_update_statusmessage(prompt, m, argv[1]); } void cmd_prompt_help(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) diff --git a/src/group_commands.c b/src/group_commands.c index 8f54c2a..f4a6c17 100644 --- a/src/group_commands.c +++ b/src/group_commands.c @@ -27,17 +27,17 @@ #include "line_info.h" #include "misc_tools.h" #include "log.h" +#include "groupchat.h" void cmd_set_topic(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) { - char topic[MAX_STR_SIZE]; - if (argc < 1) { - int tlen = tox_group_get_topic(m, self->num, (uint8_t *) topic); + char cur_topic[MAX_STR_SIZE]; + int tlen = tox_group_get_topic(m, self->num, (uint8_t *) cur_topic); if (tlen > 0) { - topic[tlen] = '\0'; - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Topic is set to: %s", topic); + cur_topic[tlen] = '\0'; + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Topic is set to: %s", cur_topic); } else { line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Topic is not set"); } @@ -45,17 +45,9 @@ void cmd_set_topic(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*arg return; } - if (argv[1][0] != '\"') { - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Topic must be enclosed in quotes."); - return; - } + const char *topic = argv[1]; - /* remove opening and closing quotes */ - snprintf(topic, sizeof(topic), "%s", &argv[1][1]); - int len = strlen(topic) - 1; - topic[len] = '\0'; - - if (tox_group_set_topic(m, self->num, (uint8_t *) topic, len) != 0) { + if (tox_group_set_topic(m, self->num, (uint8_t *) topic, strlen(topic)) != 0) { line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set topic."); return; } @@ -67,7 +59,7 @@ void cmd_set_topic(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*arg int sn_len = tox_group_get_self_name(m, self->num, (uint8_t *) selfnick); selfnick[sn_len] = '\0'; - line_info_add(self, timefrmt, selfnick, NULL, NAME_CHANGE, 0, 0, " set the group topic to: %s", topic); + line_info_add(self, timefrmt, NULL, NULL, SYS_MSG, 1, MAGENTA, "-!- You set the topic to: %s", topic); char tmp_event[MAX_STR_SIZE]; snprintf(tmp_event, sizeof(tmp_event), "set topic to %s", topic); @@ -90,3 +82,55 @@ void cmd_chatid(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[ line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s", chatid); } + +void cmd_ignore(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) +{ + if (argc < 1) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Who do you want to ignore?"); + return; + } + + const char *nick = argv[1]; + int peernum = group_get_nick_peernumber(self->num, nick); + + if (peernum == -1) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Peer '%s' does not exist", nick); + return; + } + + if (tox_group_toggle_ignore(m, self->num, peernum, 1) == -1) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to ignore %s", nick); + return; + } + + char timefrmt[TIME_STR_SIZE]; + get_time_str(timefrmt, sizeof(timefrmt)); + + line_info_add(self, timefrmt, NULL, NULL, SYS_MSG, 1, BLUE, "-!- Ignoring %s", nick); +} + +void cmd_unignore(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) +{ + if (argc < 1) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Who do you want to unignore?"); + return; + } + + const char *nick = argv[1]; + int peernum = group_get_nick_peernumber(self->num, nick); + + if (peernum == -1) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Peer '%s' does not exist", nick); + return; + } + + if (tox_group_toggle_ignore(m, self->num, peernum, 0) == -1) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to unignore %s", nick); + return; + } + + char timefrmt[TIME_STR_SIZE]; + get_time_str(timefrmt, sizeof(timefrmt)); + + line_info_add(self, timefrmt, NULL, NULL, SYS_MSG, 1, BLUE, "-!- You are no longer ignoring %s", nick); +} diff --git a/src/group_commands.h b/src/group_commands.h index 17c3eeb..dc41f40 100644 --- a/src/group_commands.h +++ b/src/group_commands.h @@ -28,5 +28,7 @@ void cmd_set_topic(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_chatid(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); +void cmd_unignore(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); +void cmd_ignore(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); #endif /* GROUP_COMMANDS_H */ diff --git a/src/groupchat.c b/src/groupchat.c index 703a31e..4ed95d2 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 24 +#define AC_NUM_GROUP_COMMANDS 26 #else -#define AC_NUM_GROUP_COMMANDS 20 +#define AC_NUM_GROUP_COMMANDS 22 #endif /* AUDIO */ /* groupchat command names used for tab completion. */ @@ -88,6 +88,8 @@ static const char group_cmd_list[AC_NUM_GROUP_COMMANDS][MAX_CMDNAME_SIZE] = { { "/exit" }, { "/group" }, { "/help" }, + { "/ignore" }, + { "/unignore" }, { "/join" }, { "/log" }, { "/myid" }, @@ -218,6 +220,18 @@ void set_status_all_groups(Tox *m, uint8_t status) } } +int group_get_nick_peernumber(int groupnum, const char *nick) +{ + int i; + + for (i = 0; i < groupchats[groupnum].num_peers; ++i) { + if (strcasecmp(nick, (char *) &groupchats[groupnum].peer_names[i * TOX_MAX_NAME_LENGTH]) == 0) + return i; + } + + return -1; +} + /* destroys and re-creates groupchat window with or without the peerlist */ void redraw_groupchat_win(ToxWindow *self) { @@ -359,7 +373,7 @@ static void groupchat_onGroupTopicChange(ToxWindow *self, Tox *m, int groupnum, char nick[TOX_MAX_NAME_LENGTH]; get_group_nick_truncate(m, nick, peernum, groupnum); - line_info_add(self, timefrmt, nick, NULL, NAME_CHANGE, 0, 0, " set the group topic to: %s", topic); + line_info_add(self, timefrmt, NULL, NULL, SYS_MSG, 1, MAGENTA, "-!- %s set the topic to: %s", nick, topic); char tmp_event[MAX_STR_SIZE]; snprintf(tmp_event, sizeof(tmp_event), " set the group topic to %s", topic); @@ -537,6 +551,9 @@ static void groupchat_onGroupRejected(ToxWindow *self, Tox *m, int groupnum, uin case TOX_GJ_INVITES_DISABLED: msg = "Invites for this group have been disabled."; break; + case TOX_GJ_INVITE_FAILED: + msg = "Invite failed. Please try again.\n"; + break; default: return; } @@ -677,7 +694,7 @@ static void groupchat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr) int diff; /* TODO: make this not suck */ - if (ctx->line[0] != L'/' || wcscmp(ctx->line, L"/me") == 0) { + if (ctx->line[0] != L'/' || wcschr(ctx->line, L' ') != NULL) { diff = complete_line(self, groupchats[self->num].peer_names, groupchats[self->num].num_peers, TOX_MAX_NAME_LENGTH); } else if (wcsncmp(ctx->line, L"/avatar \"", wcslen(L"/avatar \"")) == 0) { diff --git a/src/groupchat.h b/src/groupchat.h index 9b235b3..2af61d6 100644 --- a/src/groupchat.h +++ b/src/groupchat.h @@ -76,6 +76,7 @@ void close_groupchat(ToxWindow *self, Tox *m, int groupnum, const char *partmess int init_groupchat_win(ToxWindow *prompt, Tox *m, int groupnum, const char *groupname, int length); void set_nick_all_groups(Tox *m, const char *nick, uint16_t length); void set_status_all_groups(Tox *m, uint8_t status); +int group_get_nick_peernumber(int groupnum, const char *nick); /* destroys and re-creates groupchat window with or without the peerlist */ void redraw_groupchat_win(ToxWindow *self); diff --git a/src/help.c b/src/help.c index 3087c35..e05028e 100644 --- a/src/help.c +++ b/src/help.c @@ -243,7 +243,9 @@ static void help_draw_group(ToxWindow *self) wattroff(win, A_BOLD | COLOR_PAIR(RED)); wprintw(win, " /topic : Set group topic (show current topic if no msg)\n"); - wprintw(win, " /chatid : Print the group chat id to share with others.\n\n"); + wprintw(win, " /chatid : Print the group chat id to share with others.\n"); + wprintw(win, " /ignore : Ignore peer\n"); + wprintw(win, " /unignore : Unignore peer \n\n"); #ifdef AUDIO wattron(win, A_BOLD); @@ -310,9 +312,9 @@ void help_onKey(ToxWindow *self, wint_t key) case 'r': #ifdef AUDIO - help_init_window(self, 11, 80); + help_init_window(self, 13, 80); #else - help_init_window(self, 7, 80); + help_init_window(self, 9, 80); #endif self->help->type = HELP_GROUP; break; diff --git a/src/misc_tools.c b/src/misc_tools.c index 6c87602..4d8373e 100644 --- a/src/misc_tools.c +++ b/src/misc_tools.c @@ -300,9 +300,8 @@ int get_group_nick_truncate(Tox *m, char *buf, int peernum, int groupnum) uint16_t copy_tox_str(char *msg, size_t size, const char *data, uint16_t length) { if (length > size - 1) { - length = 0; msg[0] = '\0'; - return length; + return 0; } memcpy(msg, data, length); From 0348f81ba83bfed4c537772d66592e77b09bde05 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Sun, 18 Jan 2015 22:32:59 -0500 Subject: [PATCH 06/45] remove old group audio code --- src/groupchat.c | 135 +----------------------------------------------- src/toxic.h | 5 -- src/windows.c | 15 ------ src/windows.h | 1 - 4 files changed, 2 insertions(+), 154 deletions(-) diff --git a/src/groupchat.c b/src/groupchat.c index 4ed95d2..57cd3b2 100644 --- a/src/groupchat.c +++ b/src/groupchat.c @@ -112,11 +112,6 @@ static const char group_cmd_list[AC_NUM_GROUP_COMMANDS][MAX_CMDNAME_SIZE] = { ToxWindow new_group_chat(Tox *m, int groupnum, const char *groupname, int length); -#ifdef AUDIO -static int group_audio_open_out_device(int groupnum); -static int group_audio_close_out_device(int groupnum); -#endif /* AUDIO */ - int init_groupchat_win(ToxWindow *prompt, Tox *m, int groupnum, const char *groupname, int length) { if (groupnum > MAX_GROUPCHAT_NUM) @@ -168,10 +163,6 @@ void close_groupchat(ToxWindow *self, Tox *m, int groupnum, const char *partmess { tox_group_delete(m, groupnum, (const uint8_t *) partmessage, (uint16_t) length); -#ifdef AUDIO - group_audio_close_out_device(groupnum); -#endif - free(groupchats[groupnum].peer_names); free(groupchats[groupnum].peer_name_lengths); memset(&groupchats[groupnum], 0, sizeof(GroupChat)); @@ -511,7 +502,7 @@ static void groupchat_onGroupSelfJoin(ToxWindow *self, Tox *m, int groupnum) } } - line_info_add(self, timefrmt, NULL, NULL, SYS_MSG, 0, MAGENTA, "-!- Topic set to: %s", topic); + line_info_add(self, timefrmt, NULL, NULL, SYS_MSG, 1, MAGENTA, "-!- Topic set to: %s", topic); } static void groupchat_onGroupSelfTimeout(ToxWindow *self, Tox *m, int groupnum) @@ -552,7 +543,7 @@ static void groupchat_onGroupRejected(ToxWindow *self, Tox *m, int groupnum, uin msg = "Invites for this group have been disabled."; break; case TOX_GJ_INVITE_FAILED: - msg = "Invite failed. Please try again.\n"; + msg = "Invite failed."; break; default: return; @@ -860,124 +851,6 @@ static void groupchat_onInit(ToxWindow *self, Tox *m) wmove(self->window, y2 - CURS_Y_OFFSET, 0); } - -#ifdef AUDIO -static int group_audio_open_out_device(int groupnum) -{ - char dname[MAX_STR_SIZE]; - get_primary_device_name(output, dname, sizeof(dname)); - dname[MAX_STR_SIZE - 1] = '\0'; - - groupchats[groupnum].audio.dvhandle = alcOpenDevice(dname); - - if (groupchats[groupnum].audio.dvhandle == NULL) - return -1; - - groupchats[groupnum].audio.dvctx = alcCreateContext(groupchats[groupnum].audio.dvhandle, NULL); - alcMakeContextCurrent(groupchats[groupnum].audio.dvctx); - alGenBuffers(OPENAL_BUFS, groupchats[groupnum].audio.buffers); - alGenSources((uint32_t) 1, &groupchats[groupnum].audio.source); - alSourcei(groupchats[groupnum].audio.source, AL_LOOPING, AL_FALSE); - - if (alcGetError(groupchats[groupnum].audio.dvhandle) != AL_NO_ERROR) { - group_audio_close_out_device(groupnum); - groupchats[groupnum].audio.dvhandle = NULL; - groupchats[groupnum].audio.dvctx = NULL; - return -1; - } - - alSourceQueueBuffers(groupchats[groupnum].audio.source, OPENAL_BUFS, groupchats[groupnum].audio.buffers); - alSourcePlay(groupchats[groupnum].audio.source); - - return 0; -} - -static int group_audio_close_out_device(int groupnum) -{ - if (!groupchats[groupnum].audio.dvhandle) - return -1; - - if (!groupchats[groupnum].audio.dvctx) - return -1; - - if (alcGetCurrentContext() != groupchats[groupnum].audio.dvctx) - alcMakeContextCurrent(groupchats[groupnum].audio.dvctx); - - alDeleteSources((uint32_t) 1, &groupchats[groupnum].audio.source); - alDeleteBuffers(OPENAL_BUFS, groupchats[groupnum].audio.buffers); - - alcMakeContextCurrent(NULL); - alcDestroyContext(groupchats[groupnum].audio.dvctx); - - if (!alcCloseDevice(groupchats[groupnum].audio.dvhandle)) - return -1; - - return 0; -} - -static int group_audio_write(int peernum, int groupnum, const int16_t *pcm, unsigned int samples, uint8_t channels, - unsigned int sample_rate) -{ - if (!pcm) - return -1; - - if (channels == 0 || channels > 2) - return -2; - - ALuint bufid; - ALint processed = 0, queued = 0; - - alGetSourcei(groupchats[groupnum].audio.source, AL_BUFFERS_PROCESSED, &processed); - alGetSourcei(groupchats[groupnum].audio.source, AL_BUFFERS_QUEUED, &queued); - fprintf(stderr, "source: %d, queued: %d, processed: %d\n", groupchats[groupnum].audio.source, queued, processed); - - if (processed) { - ALuint bufids[processed]; - alSourceUnqueueBuffers(groupchats[groupnum].audio.source, processed, bufids); - alDeleteBuffers(processed - 1, bufids + 1); - bufid = bufids[0]; - } else if (queued < 16) { - alGenBuffers(1, &bufid); - } else { - return -3; - } - - int length = samples * channels * sizeof(int16_t); - - alBufferData(bufid, (channels == 1) ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16, pcm, length, sample_rate); - alSourceQueueBuffers(groupchats[groupnum].audio.source, 1, &bufid); - - ALint state; - alGetSourcei(groupchats[groupnum].audio.source, AL_SOURCE_STATE, &state); - - if (state != AL_PLAYING) - alSourcePlay(groupchats[groupnum].audio.source); - - return 0; -} - -static void groupchat_onWriteDevice(ToxWindow *self, Tox *m, int groupnum, int peernum, const int16_t *pcm, - unsigned int samples, uint8_t channels, unsigned int sample_rate) -{ - return; - - if (groupnum != self->num) - return; - - if (peernum < 0) - return; - - if (groupchats[groupnum].audio.dvhandle == NULL) - fprintf(stderr, "dvhandle is null)\n"); - - if (groupchats[groupnum].audio.dvctx == NULL) - fprintf(stderr, "ctx is null\n"); - - int ret = group_audio_write(peernum, groupnum, pcm, samples, channels, sample_rate); - fprintf(stderr, "write: %d\n", ret); -} -#endif /* AUDIO */ - ToxWindow new_group_chat(Tox *m, int groupnum, const char *groupname, int length) { ToxWindow ret; @@ -1002,10 +875,6 @@ ToxWindow new_group_chat(Tox *m, int groupnum, const char *groupname, int length ret.onGroupSelfTimeout = &groupchat_onGroupSelfTimeout; ret.onGroupRejected = &groupchat_onGroupRejected; -#ifdef AUDIO - ret.onWriteDevice = &groupchat_onWriteDevice; -#endif - if (groupname && length) set_window_title(&ret, groupname, length); else diff --git a/src/toxic.h b/src/toxic.h index b0da87e..eaed4e3 100644 --- a/src/toxic.h +++ b/src/toxic.h @@ -124,9 +124,4 @@ void on_group_self_join(Tox *m, int groupnumber, void *userdata); void on_group_self_timeout(Tox *m, int groupnumber, void *userdata); void on_group_rejected(Tox *m, int groupnumber, uint8_t type, void *userdata); -#ifdef AUDIO -void write_device_callback_group(Tox *m, int groupnum, int peernum, const int16_t *pcm, unsigned int samples, - uint8_t channels, unsigned int sample_rate, void *arg); -#endif /* AUDIO */ - #endif /* #define TOXIC_H */ diff --git a/src/windows.c b/src/windows.c index 2c5911f..f6c809e 100644 --- a/src/windows.c +++ b/src/windows.c @@ -260,12 +260,10 @@ void on_group_topic_change(Tox *m, int groupnumber, uint32_t peernumber, const u void on_group_nick_change(Tox *m, int groupnumber, uint32_t peernumber, const uint8_t *newname, uint16_t length, void *userdata) { - fprintf(stderr, "newname before: %s. len: %d\n", newname, length); char name[TOXIC_MAX_NAME_LENGTH + 1]; length = copy_tox_str(name, sizeof(name), (const char *) newname, length); filter_str(name, length); - fprintf(stderr, "newname before: %s. len: %d\n", name, length); int i; for (i = 0; i < MAX_WINDOWS_NUM; ++i) { @@ -360,19 +358,6 @@ void on_read_receipt(Tox *m, int32_t friendnumber, uint32_t receipt, void *userd } } -#ifdef AUDIO -void write_device_callback_group(Tox *m, int groupnum, int peernumber, const int16_t *pcm, unsigned int samples, - uint8_t channels, unsigned int sample_rate, void *arg) -{ - int i; - - for (i = 0; i < MAX_WINDOWS_NUM; ++i) { - if (windows[i].onWriteDevice != NULL) - windows[i].onWriteDevice(&windows[i], m, groupnum, peernumber, pcm, samples, channels, samples); - } -} -#endif /* AUDIO */ - /* CALLBACKS END */ int add_window(Tox *m, ToxWindow w) diff --git a/src/windows.h b/src/windows.h index 53f7cd5..fbaa84d 100644 --- a/src/windows.h +++ b/src/windows.h @@ -149,7 +149,6 @@ struct ToxWindow { void(*onEnd)(ToxWindow *, ToxAv *, int); void(*onRequestTimeout)(ToxWindow *, ToxAv *, int); void(*onPeerTimeout)(ToxWindow *, ToxAv *, int); - void(*onWriteDevice)(ToxWindow *, Tox *, int, int, const int16_t *, unsigned int, uint8_t, unsigned int); int call_idx; /* If in a call will have this index set, otherwise it's -1. * Don't modify outside av callbacks. */ From 6f45085d866ff43319881face1b6109d1e79b950 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Tue, 20 Jan 2015 00:52:00 -0500 Subject: [PATCH 07/45] update DHTnodes for new test network --- misc/DHTnodes | 23 +---------------------- 1 file changed, 1 insertion(+), 22 deletions(-) diff --git a/misc/DHTnodes b/misc/DHTnodes index 2b0ec3c..1e867a9 100644 --- a/misc/DHTnodes +++ b/misc/DHTnodes @@ -1,22 +1 @@ -192.254.75.98 33445 951C88B7E75C867418ACDB5D273821372BB5BD652740BCDF623A4FA293E75D2F -31.7.57.236 443 2A4B50D1D525DA2E669592A20C327B5FAD6C7E5962DC69296F9FEC77C4436E4E -107.161.17.51 33445 7BE3951B97CA4B9ECDDA768E8C52BA19E9E2690AB584787BF4C90E04DBB75111 -144.76.60.215 33445 04119E835DF3E78BACF0F84235B300546AF8B936F035185E2A8E9E0A67C8924F -23.226.230.47 33445 A09162D68618E742FFBCA1C2C70385E6679604B2D80EA6E84AD0996A1AC8A074 -178.62.125.224 33445 10B20C49ACBD968D7C80F2E8438F92EA51F189F4E70CFBBB2C2C8C799E97F03E -37.187.46.132 33445 5EB67C51D3FF5A9D528D242B669036ED2A30F8A60E674C45E7D43010CB2E1331 -178.21.112.187 33445 4B2C19E924972CB9B57732FB172F8A8604DE13EEDA2A6234E348983344B23057 -128.199.237.51 33445 67D80D1E00DE2A5294C9CCF9116C72CEC05FB8C2C6DBCEE0B5EB796DA52E2564 -195.154.119.113 33445 E398A69646B8CEACA9F0B84F553726C1C49270558C57DF5F3C368F05A7D71354 -178.62.250.138 33445 788236D34978D1D5BD822F0A5BEBD2C53C64CC31CD3149350EE27D4D9A2F9B6B -178.62.150.106 33445 58D2DE4B169502669941E50780C1630FAA48A0B7026D6F4066C320D47AC6401E -192.210.149.121 33445 F404ABAA1C99A9D37D61AB54898F56793E1DEF8BD46B1038B9D822E8460FAB67 -54.199.139.199 33445 7F9C31FE850E97CEFD4C4591DF93FC757C7C12549DDD55F8EEAECC34FE76C029 -104.219.184.206 443 8CD087E31C67568103E8C2A28653337E90E6B8EDA0D765D57C6B5172B4F1F04C -76.191.23.96 33445 93574A3FAB7D612FEA29FD8D67D3DD10DFD07A075A5D62E8AF3DD9F5D0932E11 -46.38.239.179 33445 F5A1A38EFB6BD3C2C8AF8B10D85F0F89E931704D349F1D0720C3C4059AF2440A -144.76.93.230 33445 2C308B4518862740AD9A121598BCA7713AFB25858B747313A4D073E2F6AC506C -78.225.128.39 33445 7A2306BFBA665E5480AE59B31E116BE9C04DCEFE04D9FE25082316FA34B4DA0C -195.154.109.148 33445 391C96CB67AE893D4782B8E4495EB9D89CF1031F48460C06075AA8CE76D50A21 -192.3.173.88 33445 3E1FFDEB667BFF549F619EC6737834762124F50A89C8D0DBF1DDF64A2DD6CD1B -130.133.110.14 33445 461FA3776EF0FA655F1A05477DF1B3B614F7D6B124F7DB1DD4FE3C08B03B640F +192.254.75.104 33445 6058FF1DA1E013AD4F829CBE8E5DDFD30A4DE55901B0997832E3E8A64E19026C From 38e55d55b345d756f2ff85fa36edf298f8f4c489 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Tue, 20 Jan 2015 18:06:26 -0500 Subject: [PATCH 08/45] fix formatting bug --- src/groupchat.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/groupchat.c b/src/groupchat.c index 57cd3b2..47785ee 100644 --- a/src/groupchat.c +++ b/src/groupchat.c @@ -612,7 +612,7 @@ static void send_group_message(ToxWindow *self, Tox *m, int groupnum, const char if (tox_group_message_send(m, self->num, (uint8_t *) msg, strlen(msg)) == -1) { const char *errmsg = " * Failed to send message."; - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, RED, errmsg); + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, RED, "%s", errmsg); return; } @@ -623,7 +623,7 @@ static void send_group_message(ToxWindow *self, Tox *m, int groupnum, const char char timefrmt[TIME_STR_SIZE]; get_time_str(timefrmt, sizeof(timefrmt)); - line_info_add(self, timefrmt, selfname, NULL, OUT_MSG_READ, 0, 0, msg); + line_info_add(self, timefrmt, selfname, NULL, OUT_MSG_READ, 0, 0, "%s", msg); write_to_log(msg, selfname, ctx->log, false); } @@ -638,7 +638,7 @@ static void send_group_action(ToxWindow *self, Tox *m, int groupnum, char *actio if (tox_group_action_send(m, groupnum, (uint8_t *) action, strlen(action)) == -1) { const char *errmsg = " * Failed to send action."; - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, RED, errmsg); + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, RED, "%s", errmsg); return; } @@ -649,7 +649,7 @@ static void send_group_action(ToxWindow *self, Tox *m, int groupnum, char *actio char timefrmt[TIME_STR_SIZE]; get_time_str(timefrmt, sizeof(timefrmt)); - line_info_add(self, timefrmt, selfname, NULL, OUT_ACTION_READ, 0, 0, action); + line_info_add(self, timefrmt, selfname, NULL, OUT_ACTION_READ, 0, 0, "%s", action); write_to_log(action, selfname, ctx->log, true); } @@ -733,8 +733,8 @@ static void groupchat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr) close_groupchat(self, m, self->num, line + offset, ctx->len - offset); return; - } else if (strncmp(line, "/me ", strlen("/me ")) == 0) { - send_group_action(self, m, self->num, line + strlen("/me ")); + } else if (strncmp(line, "/me ", 4) == 0) { + send_group_action(self, m, self->num, line + 4); } else { execute(ctx->history, self, m, line, GROUPCHAT_COMMAND_MODE); } From ff69cdd2537348316b167cebd3f4a8ed52dc6ec6 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Fri, 23 Jan 2015 00:52:09 -0500 Subject: [PATCH 09/45] add friend group invites --- src/chat.c | 32 ++++++++++++++++++++++++++++++-- src/chat_commands.c | 23 +++++++++++++++++++++++ src/chat_commands.h | 1 + src/execute.c | 1 + src/friendlist.c | 20 ++++++++++++++++++++ src/friendlist.h | 6 ++++++ src/global_commands.c | 29 ++++++++++++++++++++++++++--- src/groupchat.c | 12 ++++++------ src/misc_tools.c | 6 +++++- src/toxic.c | 1 + src/toxic.h | 1 + src/windows.c | 10 ++++++++++ src/windows.h | 1 + 13 files changed, 131 insertions(+), 12 deletions(-) diff --git a/src/chat.c b/src/chat.c index a47aefc..4d3481a 100644 --- a/src/chat.c +++ b/src/chat.c @@ -64,9 +64,9 @@ static void kill_infobox(ToxWindow *self); #endif /* AUDIO */ #ifdef AUDIO -#define AC_NUM_CHAT_COMMANDS 26 +#define AC_NUM_CHAT_COMMANDS 27 #else -#define AC_NUM_CHAT_COMMANDS 19 +#define AC_NUM_CHAT_COMMANDS 20 #endif /* AUDIO */ /* Array of chat command names used for tab completion. */ @@ -81,6 +81,7 @@ static const char chat_cmd_list[AC_NUM_CHAT_COMMANDS][MAX_CMDNAME_SIZE] = { { "/exit" }, { "/group" }, { "/help" }, + { "/invite" }, { "/join" }, { "/log" }, { "/myid" }, @@ -560,6 +561,32 @@ static void chat_onFileData(ToxWindow *self, Tox *m, int32_t num, uint8_t filenu Friends.list[num].file_receiver[filenum].bytes_recv += length; } +static void chat_onGroupInvite(ToxWindow *self, Tox *m, int32_t friendnumber, const char *invite_data, + uint16_t length) +{ + if (self->num != friendnumber) + return; + + if (length != TOX_GROUP_INVITE_DATA_SIZE) + return; + + memcpy(Friends.list[friendnumber].group_invite.data, invite_data, length); + Friends.list[friendnumber].group_invite.length = length; + + sound_notify(self, generic_message, NT_WNDALERT_2, NULL); + + char name[TOX_MAX_NAME_LENGTH]; + get_nick_truncate(m, name, friendnumber); + + if (self->active_box != -1) + box_silent_notify2(self, NT_WNDALERT_2 | NT_NOFOCUS, self->active_box, "invites you to join group chat"); + else + box_silent_notify(self, NT_WNDALERT_2 | NT_NOFOCUS, &self->active_box, name, "invites you to join group chat"); + + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s has invited you to a group chat.", name); + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Type \"/join\" to join the chat."); +} + /* Av Stuff */ #ifdef AUDIO @@ -1113,6 +1140,7 @@ ToxWindow new_chat(Tox *m, int32_t friendnum) ret.onFileControl = &chat_onFileControl; ret.onFileData = &chat_onFileData; ret.onReadReceipt = &chat_onReadReceipt; + ret.onGroupInvite = &chat_onGroupInvite; #ifdef AUDIO ret.onInvite = &chat_onInvite; diff --git a/src/chat_commands.c b/src/chat_commands.c index 48de478..9ca5109 100644 --- a/src/chat_commands.c +++ b/src/chat_commands.c @@ -66,6 +66,7 @@ void cmd_cancelfile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*ar get_file_name(name, sizeof(name), filepath); line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "File transfer for '%s' canceled.", name); chat_close_file_receiver(m, filenum, self->num, TOX_FILECONTROL_KILL); + return; } else if (strcasecmp(inoutstr, "out") == 0) { /* cancel an outgoing file transfer */ int i; @@ -94,6 +95,28 @@ void cmd_cancelfile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*ar } } +void cmd_groupinvite(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) +{ + if (argc < 1) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group number required."); + return; + } + + int groupnum = atoi(argv[1]); + + if (groupnum == 0 && strcmp(argv[1], "0")) { /* atoi returns 0 value on invalid input */ + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid group number."); + return; + } + + if (tox_group_invite_friend(m, groupnum, self->num) == -1) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to invite contact to group."); + return; + } + + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invited contact to Group %d.", groupnum); +} + void cmd_savefile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) { if (argc < 1) { diff --git a/src/chat_commands.h b/src/chat_commands.h index 9c87ede..afe314e 100644 --- a/src/chat_commands.h +++ b/src/chat_commands.h @@ -26,6 +26,7 @@ #include "windows.h" #include "toxic.h" +void cmd_groupinvite(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_cancelfile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_savefile(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_sendfile(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]); diff --git a/src/execute.c b/src/execute.c index c2c2803..d53767b 100644 --- a/src/execute.c +++ b/src/execute.c @@ -67,6 +67,7 @@ static struct cmd_func global_commands[] = { static struct cmd_func chat_commands[] = { { "/cancel", cmd_cancelfile }, + { "/invite", cmd_groupinvite }, { "/savefile", cmd_savefile }, { "/sendfile", cmd_sendfile }, #ifdef AUDIO diff --git a/src/friendlist.c b/src/friendlist.c index ba925f0..1e95a0e 100644 --- a/src/friendlist.c +++ b/src/friendlist.c @@ -476,6 +476,25 @@ static void friendlist_onFileSendRequest(ToxWindow *self, Tox *m, int32_t num, u } } +static void friendlist_onGroupInvite(ToxWindow *self, Tox *m, int32_t num, const char *data, + uint16_t length) +{ + if (num >= Friends.max_idx) + return; + + if (Friends.list[num].chatwin == -1) { + if (get_num_active_windows() < MAX_WINDOWS_NUM) { + Friends.list[num].chatwin = add_window(m, new_chat(m, Friends.list[num].num)); + } else { + char nick[TOX_MAX_NAME_LENGTH]; + get_nick_truncate(m, nick, num); + line_info_add(prompt, NULL, NULL, NULL, SYS_MSG, 0, RED, + "* Group chat invite from %s failed: too many windows are open.", nick); + sound_notify(prompt, error, NT_WNDALERT_1, NULL); + } + } +} + /* move friendlist/blocklist cursor up and down */ static void select_friend(ToxWindow *self, wint_t key, int *selected, int num) { @@ -1046,6 +1065,7 @@ ToxWindow new_friendlist(void) ret.onStatusChange = &friendlist_onStatusChange; ret.onStatusMessageChange = &friendlist_onStatusMessageChange; ret.onFileSendRequest = &friendlist_onFileSendRequest; + ret.onGroupInvite = &friendlist_onGroupInvite; #ifdef AUDIO ret.onInvite = &friendlist_onAv; diff --git a/src/friendlist.h b/src/friendlist.h index 599d4a7..ae4e965 100644 --- a/src/friendlist.h +++ b/src/friendlist.h @@ -48,6 +48,11 @@ struct LastOnline { char hour_min_str[TIME_STR_SIZE]; /* holds 12/24-hour time string e.g. "10:43 PM" */ }; +struct GroupInvite { + uint8_t data[TOX_GROUP_INVITE_DATA_SIZE]; + uint16_t length; +}; + typedef struct { char name[TOXIC_MAX_NAME_LENGTH + 1]; int namelength; @@ -61,6 +66,7 @@ typedef struct { uint8_t is_typing; bool logging_on; /* saves preference for friend irrespective of global settings */ uint8_t status; + struct GroupInvite group_invite; struct LastOnline last_online; struct FileReceiver file_receiver[MAX_FILES]; uint8_t active_file_receivers; diff --git a/src/global_commands.c b/src/global_commands.c index d812649..d38c351 100644 --- a/src/global_commands.c +++ b/src/global_commands.c @@ -362,6 +362,23 @@ void cmd_groupchat(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*arg } } +static void join_invite(ToxWindow *self, Tox *m) +{ + int groupnumber = tox_group_accept_invite(m, Friends.list[self->num].group_invite.data, + Friends.list[self->num].group_invite.length); + + if (groupnumber == -1) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group chat instance failed to initialize."); + return; + } + + if (init_groupchat_win(prompt, m, groupnumber, NULL, 0) == -1) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group chat window failed to initialize."); + tox_group_delete(m, groupnumber, NULL, 0); + return; + } +} + void cmd_join(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) { if (get_num_active_windows() >= MAX_WINDOWS_NUM) { @@ -369,9 +386,15 @@ void cmd_join(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA return; } + /* If no input check for a group invite */ if (argc < 1) { - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group chat ID is required."); - return; + if (!self->is_chat || Friends.list[self->num].group_invite.length == 0) { + const char *msg = "You must either be invited to a group or input the group ID of the group you wish to join."; + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s", msg); + return; + } + + return join_invite(self, m); } const char *chat_id = argv[1]; @@ -409,7 +432,7 @@ void cmd_join(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA if (init_groupchat_win(prompt, m, groupnum, NULL, 0) == -1) { line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group chat window failed to initialize."); - tox_group_delete(m, self->num, NULL, 0); + tox_group_delete(m, groupnum, NULL, 0); return; } } diff --git a/src/groupchat.c b/src/groupchat.c index 47785ee..cdaf18c 100644 --- a/src/groupchat.c +++ b/src/groupchat.c @@ -189,7 +189,7 @@ void set_nick_all_groups(Tox *m, const char *nick, uint16_t length) for (i = 0; i < max_groupchat_index; ++i) { if (groupchats[i].active) { ToxWindow *self = get_window_ptr(groupchats[i].chatwin); - int ret = tox_group_set_name(m, groupchats[i].groupnumber, (uint8_t *) nick, length); + int ret = tox_group_set_self_name(m, groupchats[i].groupnumber, (uint8_t *) nick, length); if (ret == -1 && groupchats[i].is_connected) line_info_add(self, timefrmt, NULL, 0, SYS_MSG, 0, 0, "Invalid nick"); @@ -875,11 +875,6 @@ ToxWindow new_group_chat(Tox *m, int groupnum, const char *groupname, int length ret.onGroupSelfTimeout = &groupchat_onGroupSelfTimeout; ret.onGroupRejected = &groupchat_onGroupRejected; - if (groupname && length) - set_window_title(&ret, groupname, length); - else - snprintf(ret.name, sizeof(ret.name), "Group %d", groupnum); - ChatContext *chatwin = calloc(1, sizeof(ChatContext)); Help *help = calloc(1, sizeof(Help)); @@ -893,5 +888,10 @@ ToxWindow new_group_chat(Tox *m, int groupnum, const char *groupname, int length ret.show_peerlist = true; ret.active_box = -1; + if (groupname && length) + set_window_title(&ret, groupname, length); + else + snprintf(ret.name, sizeof(ret.name), "Group %d", groupnum); + return ret; } diff --git a/src/misc_tools.c b/src/misc_tools.c index 4d8373e..ee9ca0f 100644 --- a/src/misc_tools.c +++ b/src/misc_tools.c @@ -400,7 +400,11 @@ int check_file_signature(const char *signature, size_t size, FILE *fp) void set_window_title(ToxWindow *self, const char *title, int len) { char cpy[TOXIC_MAX_NAME_LENGTH + 1]; - snprintf(cpy, sizeof(cpy), "%s", title); + + if (self->is_groupchat) /* keep groupnumber in title */ + snprintf(cpy, sizeof(cpy), "%d %s", self->num, title); + else + snprintf(cpy, sizeof(cpy), "%s", title); if (len > MAX_WINDOW_NAME_LENGTH) { strcpy(&cpy[MAX_WINDOW_NAME_LENGTH - 3], "..."); diff --git a/src/toxic.c b/src/toxic.c index edeea94..b2a6291 100644 --- a/src/toxic.c +++ b/src/toxic.c @@ -310,6 +310,7 @@ static Tox *init_tox(void) tox_callback_file_control(m, on_file_control, NULL); tox_callback_file_data(m, on_file_data, NULL); tox_callback_read_receipt(m, on_read_receipt, NULL); + tox_callback_group_invite(m, on_group_invite, NULL); tox_callback_group_message(m, on_group_message, NULL); tox_callback_group_action(m, on_group_action, NULL); tox_callback_group_private_message(m, on_group_private_message, NULL); diff --git a/src/toxic.h b/src/toxic.h index eaed4e3..551ef29 100644 --- a/src/toxic.h +++ b/src/toxic.h @@ -111,6 +111,7 @@ void on_file_data(Tox *m, int32_t friendnumber, uint8_t filenumber, const uint8_ void on_typing_change(Tox *m, int32_t friendnumber, uint8_t is_typing, void *userdata); void on_read_receipt(Tox *m, int32_t, uint32_t, void *userdata); +void on_group_invite(Tox *m, int32_t friendnumber, const uint8_t *invite_data, uint16_t length, void *userdata); void on_group_message(Tox *m, int groupnumber, uint32_t peernumber, const uint8_t *message, uint16_t length, void *userdata); void on_group_action(Tox *m, int groupnumber, uint32_t peernumber, const uint8_t *action, uint16_t length, void *userdata); void on_group_private_message(Tox *m, int groupnumber, uint32_t peernumber, const uint8_t *message, uint16_t length, void *userdata); diff --git a/src/windows.c b/src/windows.c index f6c809e..fe5b135 100644 --- a/src/windows.c +++ b/src/windows.c @@ -161,6 +161,16 @@ void on_friendadded(Tox *m, int32_t friendnumber, bool sort) store_data(m, DATA_FILE); } +void on_group_invite(Tox *m, int32_t friendnumber, const uint8_t *invite_data, uint16_t length, void *userdata) +{ + int i; + + for (i = 0; i < MAX_WINDOWS_NUM; ++i) { + if (windows[i].onGroupInvite != NULL) + windows[i].onGroupInvite(&windows[i], m, friendnumber, (char *) invite_data, length); + } +} + void on_group_message(Tox *m, int groupnumber, uint32_t peernumber, const uint8_t *message, uint16_t length, void *userdata) { diff --git a/src/windows.h b/src/windows.h index fbaa84d..2e1394b 100644 --- a/src/windows.h +++ b/src/windows.h @@ -123,6 +123,7 @@ struct ToxWindow { void(*onTypingChange)(ToxWindow *, Tox *, int32_t, uint8_t); void(*onReadReceipt)(ToxWindow *, Tox *, int32_t, uint32_t); + void(*onGroupInvite)(ToxWindow *, Tox *, int32_t, const char *, uint16_t); void(*onGroupMessage)(ToxWindow *, Tox *, int, int, const char *, uint16_t); void(*onGroupAction)(ToxWindow *, Tox *, int, int, const char *, uint16_t); void(*onGroupPrivateMessage)(ToxWindow *, Tox *, int, uint32_t, const char *, uint16_t); From 5c98c1c51e70882fb7aeb0aa28131f369a2ddcf1 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Tue, 27 Jan 2015 18:00:25 -0500 Subject: [PATCH 10/45] group invite API change --- src/chat.c | 5 +++-- src/friendlist.h | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/chat.c b/src/chat.c index 4d3481a..e8a3ade 100644 --- a/src/chat.c +++ b/src/chat.c @@ -567,9 +567,10 @@ static void chat_onGroupInvite(ToxWindow *self, Tox *m, int32_t friendnumber, co if (self->num != friendnumber) return; - if (length != TOX_GROUP_INVITE_DATA_SIZE) - return; + if (Friends.list[friendnumber].group_invite.data) + free(Friends.list[friendnumber].group_invite.data); + Friends.list[friendnumber].group_invite.data = malloc(length * sizeof(uint8_t)); memcpy(Friends.list[friendnumber].group_invite.data, invite_data, length); Friends.list[friendnumber].group_invite.length = length; diff --git a/src/friendlist.h b/src/friendlist.h index ae4e965..d1e7f58 100644 --- a/src/friendlist.h +++ b/src/friendlist.h @@ -49,7 +49,7 @@ struct LastOnline { }; struct GroupInvite { - uint8_t data[TOX_GROUP_INVITE_DATA_SIZE]; + uint8_t *data; uint16_t length; }; From c3179b3b2282e32323c0e3ba3343ba9e9ded854d Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Thu, 19 Feb 2015 21:24:52 -0500 Subject: [PATCH 11/45] fix memory leak --- src/friendlist.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/friendlist.c b/src/friendlist.c index 1e95a0e..4ea76d3 100644 --- a/src/friendlist.c +++ b/src/friendlist.c @@ -112,6 +112,13 @@ static void realloc_blocklist(int n) void kill_friendlist(void) { + size_t i; + + for (i = 0; i < Friends.max_idx; ++i) { + if (Friends.list[i].group_invite.data != NULL) + free(Friends.list[i].group_invite.data); + } + realloc_blocklist(0); realloc_friends(0); } From a89e6b2cdc71853e4f36399f152f6e5a96407ee4 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Thu, 19 Feb 2015 21:36:21 -0500 Subject: [PATCH 12/45] merge mistake --- misc/DHTnodes | 5 ----- 1 file changed, 5 deletions(-) diff --git a/misc/DHTnodes b/misc/DHTnodes index 7accc7d..1e867a9 100644 --- a/misc/DHTnodes +++ b/misc/DHTnodes @@ -1,6 +1 @@ 192.254.75.104 33445 6058FF1DA1E013AD4F829CBE8E5DDFD30A4DE55901B0997832E3E8A64E19026C -130.133.110.14 33445 461FA3776EF0FA655F1A05477DF1B3B614F7D6B124F7DB1DD4FE3C08B03B640F -104.167.101.29 33445 5918AC3C06955962A75AD7DF4F80A5D7C34F7DB9E1498D2E0495DE35B3FE8A57 -198.98.51.198 33445 1D5A5F2F5D6233058BF0259B09622FB40B482E4FA0931EB8FD3AB8E7BF7DAF6F -80.232.246.79 33445 0B8DCEAA7BDDC44BB11173F987CAE3566A2D7057D8DD3CC642BD472B9391002A - From b31bd93e7d1a7330c79d83dc3e61f5e88d04fa50 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Thu, 26 Feb 2015 19:59:55 -0500 Subject: [PATCH 13/45] api function name change --- src/group_commands.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/group_commands.c b/src/group_commands.c index f4a6c17..f2892d6 100644 --- a/src/group_commands.c +++ b/src/group_commands.c @@ -70,7 +70,7 @@ void cmd_chatid(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[ { char chatid[TOX_GROUP_CHAT_ID_SIZE * 2 + 1] = {0}; char chat_public_key[TOX_GROUP_CHAT_ID_SIZE]; - tox_group_get_invite_key(m, self->num, (uint8_t *) chat_public_key); + tox_group_get_chat_id(m, self->num, (uint8_t *) chat_public_key); size_t i; From 830ddb21b599da848e111ce0428edb855275cfa6 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Fri, 27 Feb 2015 19:03:53 -0500 Subject: [PATCH 14/45] add support for group persistence --- src/global_commands.c | 6 +++--- src/groupchat.c | 6 +++++- src/groupchat.h | 2 +- src/toxic.c | 13 +++++++++++++ 4 files changed, 22 insertions(+), 5 deletions(-) diff --git a/src/global_commands.c b/src/global_commands.c index f7299a1..6a43e85 100644 --- a/src/global_commands.c +++ b/src/global_commands.c @@ -355,7 +355,7 @@ void cmd_groupchat(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*arg return; } - if (init_groupchat_win(prompt, m, groupnum, name, len) == -1) { + if (init_groupchat_win(m, groupnum, name, len) == -1) { line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group chat window failed to initialize."); tox_group_delete(m, groupnum, NULL, 0); return; @@ -372,7 +372,7 @@ static void join_invite(ToxWindow *self, Tox *m) return; } - if (init_groupchat_win(prompt, m, groupnumber, NULL, 0) == -1) { + if (init_groupchat_win(m, groupnumber, NULL, 0) == -1) { line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group chat window failed to initialize."); tox_group_delete(m, groupnumber, NULL, 0); return; @@ -430,7 +430,7 @@ void cmd_join(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA return; } - if (init_groupchat_win(prompt, m, groupnum, NULL, 0) == -1) { + if (init_groupchat_win(m, groupnum, NULL, 0) == -1) { line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group chat window failed to initialize."); tox_group_delete(m, groupnum, NULL, 0); return; diff --git a/src/groupchat.c b/src/groupchat.c index 05c202b..1a638b2 100644 --- a/src/groupchat.c +++ b/src/groupchat.c @@ -112,7 +112,7 @@ static const char group_cmd_list[AC_NUM_GROUP_COMMANDS][MAX_CMDNAME_SIZE] = { ToxWindow new_group_chat(Tox *m, int groupnum, const char *groupname, int length); -int init_groupchat_win(ToxWindow *prompt, Tox *m, int groupnum, const char *groupname, int length) +int init_groupchat_win(Tox *m, int groupnum, const char *groupname, int length) { if (groupnum > MAX_GROUPCHAT_NUM) return -1; @@ -137,6 +137,7 @@ int init_groupchat_win(ToxWindow *prompt, Tox *m, int groupnum, const char *grou if (i == max_groupchat_index) ++max_groupchat_index; + store_data(m, DATA_FILE); return 0; } } @@ -159,6 +160,9 @@ static void kill_groupchat_window(ToxWindow *self) del_window(self); } +/* Closes groupchat window and cleans up. + * If delete_group is true the group will be permanently deleted. + */ void close_groupchat(ToxWindow *self, Tox *m, int groupnum, const char *partmessage, int length) { tox_group_delete(m, groupnum, (const uint8_t *) partmessage, (uint16_t) length); diff --git a/src/groupchat.h b/src/groupchat.h index 2af61d6..98d2e09 100644 --- a/src/groupchat.h +++ b/src/groupchat.h @@ -73,7 +73,7 @@ typedef struct { } GroupChat; void close_groupchat(ToxWindow *self, Tox *m, int groupnum, const char *partmessage, int length); -int init_groupchat_win(ToxWindow *prompt, Tox *m, int groupnum, const char *groupname, int length); +int init_groupchat_win(Tox *m, int groupnum, const char *groupname, int length); void set_nick_all_groups(Tox *m, const char *nick, uint16_t length); void set_status_all_groups(Tox *m, uint8_t status); int group_get_nick_peernumber(int groupnum, const char *nick); diff --git a/src/toxic.c b/src/toxic.c index 5f3dbeb..0318958 100644 --- a/src/toxic.c +++ b/src/toxic.c @@ -47,6 +47,7 @@ #include "toxic.h" #include "windows.h" #include "friendlist.h" +#include "groupchat.h" #include "prompt.h" #include "misc_tools.h" #include "file_senders.h" @@ -481,6 +482,17 @@ static void load_friendlist(Tox *m) sort_friendlist_index(); } +static void load_groups(Tox *m) +{ + uint32_t i; + uint32_t numgroups = tox_group_count_groups(m); + + for (i = 0; i < numgroups; ++i) { + if (init_groupchat_win(m, i, NULL, 0) == -1) + tox_group_delete(m, i, NULL, 0); + } +} + /* return length of password on success, 0 on failure */ static int password_prompt(char *buf, int size) { @@ -1109,6 +1121,7 @@ int main(int argc, char *argv[]) if (settings_err == -1) queue_init_message("Failed to load user settings"); + load_groups(m); print_init_messages(prompt); cleanup_init_messages(); From 4cc08050363e628a5497ab80be1c1859029fb457 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Sat, 28 Feb 2015 14:37:28 -0500 Subject: [PATCH 15/45] fix small bug --- src/groupchat.c | 6 ++---- src/windows.c | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/groupchat.c b/src/groupchat.c index 1a638b2..2895485 100644 --- a/src/groupchat.c +++ b/src/groupchat.c @@ -160,12 +160,10 @@ static void kill_groupchat_window(ToxWindow *self) del_window(self); } -/* Closes groupchat window and cleans up. - * If delete_group is true the group will be permanently deleted. - */ +/* Closes groupchat window and cleans up. */ void close_groupchat(ToxWindow *self, Tox *m, int groupnum, const char *partmessage, int length) { - tox_group_delete(m, groupnum, (const uint8_t *) partmessage, (uint16_t) length); + tox_group_delete(m, groupnum, (uint8_t *) partmessage, (uint16_t) length); free(groupchats[groupnum].peer_names); free(groupchats[groupnum].peer_name_lengths); diff --git a/src/windows.c b/src/windows.c index fe5b135..d36f02a 100644 --- a/src/windows.c +++ b/src/windows.c @@ -661,7 +661,7 @@ void kill_all_windows(Tox *m) if (windows[i].is_chat) kill_chat_window(&windows[i], m); else if (windows[i].is_groupchat) - close_groupchat(&windows[i], m, i, "Quit.", 5); + close_groupchat(&windows[i], m, windows[i].num, "Quit.", 5); } kill_prompt_window(prompt); From 5859763f04c63fa567c010ddce6d57237e266861 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Wed, 4 Mar 2015 00:08:30 -0500 Subject: [PATCH 16/45] load saved group names --- src/groupchat.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/groupchat.c b/src/groupchat.c index 2895485..4c0b886 100644 --- a/src/groupchat.c +++ b/src/groupchat.c @@ -110,6 +110,7 @@ static const char group_cmd_list[AC_NUM_GROUP_COMMANDS][MAX_CMDNAME_SIZE] = { #endif /* AUDIO */ }; +static void groupchat_set_group_name(ToxWindow *self, Tox *m, int groupnum); ToxWindow new_group_chat(Tox *m, int groupnum, const char *groupname, int length); int init_groupchat_win(Tox *m, int groupnum, const char *groupname, int length) @@ -119,6 +120,10 @@ int init_groupchat_win(Tox *m, int groupnum, const char *groupname, int length) ToxWindow self = new_group_chat(m, groupnum, groupname, length); + /* In case we're loading a saved group */ + if (length <= 0) + groupchat_set_group_name(&self, m, groupnum); + int i; for (i = 0; i <= max_groupchat_index; ++i) { @@ -472,11 +477,8 @@ static void groupchat_onGroupPeerExit(ToxWindow *self, Tox *m, int groupnum, uin sound_notify(self, silent, NT_WNDALERT_2, NULL); } -static void groupchat_onGroupSelfJoin(ToxWindow *self, Tox *m, int groupnum) +static void groupchat_set_group_name(ToxWindow *self, Tox *m, int groupnum) { - if (groupnum != self->num) - return; - char tmp_groupname[TOX_MAX_GROUP_NAME_LENGTH]; int glen = tox_group_get_group_name(m, groupnum, (uint8_t *) tmp_groupname); @@ -485,6 +487,14 @@ static void groupchat_onGroupSelfJoin(ToxWindow *self, Tox *m, int groupnum) if (glen > 0) set_window_title(self, groupname, glen); +} + +static void groupchat_onGroupSelfJoin(ToxWindow *self, Tox *m, int groupnum) +{ + if (groupnum != self->num) + return; + + groupchat_set_group_name(self, m, groupnum); char tmp_topic[TOX_MAX_GROUP_TOPIC_LENGTH]; int tlen = tox_group_get_topic(m, groupnum, (uint8_t *) tmp_topic); @@ -890,7 +900,7 @@ ToxWindow new_group_chat(Tox *m, int groupnum, const char *groupname, int length ret.show_peerlist = true; ret.active_box = -1; - if (groupname && length) + if (groupname && length > 0) set_window_title(&ret, groupname, length); else snprintf(ret.name, sizeof(ret.name), "Group %d", groupnum); From 2bcce234a8f1041838b2353378672718fd097d2d Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Sat, 7 Mar 2015 00:05:54 -0500 Subject: [PATCH 17/45] add group rejoin command --- src/execute.c | 3 +- src/group_commands.c | 88 +++++++++++++++++++++++++------------------- src/group_commands.h | 5 ++- src/groupchat.c | 13 ++++--- src/help.c | 7 ++-- 5 files changed, 66 insertions(+), 50 deletions(-) diff --git a/src/execute.c b/src/execute.c index d53767b..0596904 100644 --- a/src/execute.c +++ b/src/execute.c @@ -82,9 +82,10 @@ static struct cmd_func chat_commands[] = { }; static struct cmd_func group_commands[] = { - { "/topic", cmd_set_topic }, { "/chatid", cmd_chatid }, { "/ignore", cmd_ignore }, + { "/rejoin", cmd_rejoin }, + { "/topic", cmd_set_topic }, { "/unignore", cmd_unignore }, #ifdef AUDIO { "/mute", cmd_mute }, diff --git a/src/group_commands.c b/src/group_commands.c index f2892d6..ad43176 100644 --- a/src/group_commands.c +++ b/src/group_commands.c @@ -29,48 +29,15 @@ #include "log.h" #include "groupchat.h" -void cmd_set_topic(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) -{ - if (argc < 1) { - char cur_topic[MAX_STR_SIZE]; - int tlen = tox_group_get_topic(m, self->num, (uint8_t *) cur_topic); - - if (tlen > 0) { - cur_topic[tlen] = '\0'; - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Topic is set to: %s", cur_topic); - } else { - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Topic is not set"); - } - - return; - } - - const char *topic = argv[1]; - - if (tox_group_set_topic(m, self->num, (uint8_t *) topic, strlen(topic)) != 0) { - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set topic."); - return; - } - - char timefrmt[TIME_STR_SIZE]; - char selfnick[TOX_MAX_NAME_LENGTH]; - - get_time_str(timefrmt, sizeof(timefrmt)); - int sn_len = tox_group_get_self_name(m, self->num, (uint8_t *) selfnick); - selfnick[sn_len] = '\0'; - - line_info_add(self, timefrmt, NULL, NULL, SYS_MSG, 1, MAGENTA, "-!- You set the topic to: %s", topic); - - char tmp_event[MAX_STR_SIZE]; - snprintf(tmp_event, sizeof(tmp_event), "set topic to %s", topic); - write_to_log(tmp_event, selfnick, self->chatwin->log, true); -} - void cmd_chatid(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) { char chatid[TOX_GROUP_CHAT_ID_SIZE * 2 + 1] = {0}; char chat_public_key[TOX_GROUP_CHAT_ID_SIZE]; - tox_group_get_chat_id(m, self->num, (uint8_t *) chat_public_key); + + if (tox_group_get_chat_id(m, self->num, (uint8_t *) chat_public_key) == -1) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Error retreiving chat id."); + return; + } size_t i; @@ -109,6 +76,51 @@ void cmd_ignore(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[ line_info_add(self, timefrmt, NULL, NULL, SYS_MSG, 1, BLUE, "-!- Ignoring %s", nick); } +void cmd_rejoin(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) +{ + if (tox_group_reconnect(m, self->num) == -1) + return; + + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Reconnecting to group..."); +} + +void cmd_set_topic(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) +{ + if (argc < 1) { + char cur_topic[MAX_STR_SIZE]; + int tlen = tox_group_get_topic(m, self->num, (uint8_t *) cur_topic); + + if (tlen > 0) { + cur_topic[tlen] = '\0'; + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Topic is set to: %s", cur_topic); + } else { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Topic is not set"); + } + + return; + } + + const char *topic = argv[1]; + + if (tox_group_set_topic(m, self->num, (uint8_t *) topic, strlen(topic)) != 0) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set topic."); + return; + } + + char timefrmt[TIME_STR_SIZE]; + char selfnick[TOX_MAX_NAME_LENGTH]; + + get_time_str(timefrmt, sizeof(timefrmt)); + int sn_len = tox_group_get_self_name(m, self->num, (uint8_t *) selfnick); + selfnick[sn_len] = '\0'; + + line_info_add(self, timefrmt, NULL, NULL, SYS_MSG, 1, MAGENTA, "-!- You set the topic to: %s", topic); + + char tmp_event[MAX_STR_SIZE]; + snprintf(tmp_event, sizeof(tmp_event), "set topic to %s", topic); + write_to_log(tmp_event, selfnick, self->chatwin->log, true); +} + void cmd_unignore(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) { if (argc < 1) { diff --git a/src/group_commands.h b/src/group_commands.h index dc41f40..a9dc6c7 100644 --- a/src/group_commands.h +++ b/src/group_commands.h @@ -26,9 +26,10 @@ #include "windows.h" #include "toxic.h" -void cmd_set_topic(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_chatid(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); -void cmd_unignore(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_ignore(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); +void cmd_rejoin(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); +void cmd_set_topic(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); +void cmd_unignore(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); #endif /* GROUP_COMMANDS_H */ diff --git a/src/groupchat.c b/src/groupchat.c index 4c0b886..1e782a9 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 26 +#define AC_NUM_GROUP_COMMANDS 27 #else -#define AC_NUM_GROUP_COMMANDS 22 +#define AC_NUM_GROUP_COMMANDS 23 #endif /* AUDIO */ /* groupchat command names used for tab completion. */ @@ -89,16 +89,17 @@ static const char group_cmd_list[AC_NUM_GROUP_COMMANDS][MAX_CMDNAME_SIZE] = { { "/group" }, { "/help" }, { "/ignore" }, - { "/unignore" }, { "/join" }, { "/log" }, { "/myid" }, { "/nick" }, { "/note" }, { "/quit" }, + { "/rejoin" }, { "/requests" }, { "/status" }, { "/topic" }, + { "/unignore" }, #ifdef AUDIO @@ -546,16 +547,16 @@ static void groupchat_onGroupRejected(ToxWindow *self, Tox *m, int groupnum, uin switch (type) { case TOX_GJ_NICK_TAKEN: - msg = "That nick is already in use. Please change your nick with the '/nick' command."; + msg = "Nick already in use. Change your nick and use the 'rejoin' command."; break; case TOX_GJ_GROUP_FULL: - msg = "Group is full."; + msg = "Group is full. Try again with the 'rejoin' command."; break; case TOX_GJ_INVITES_DISABLED: msg = "Invites for this group have been disabled."; break; case TOX_GJ_INVITE_FAILED: - msg = "Invite failed."; + msg = "Invite failed. Try again with the 'rejoin' command."; break; default: return; diff --git a/src/help.c b/src/help.c index e05028e..f817c5e 100644 --- a/src/help.c +++ b/src/help.c @@ -242,9 +242,10 @@ static void help_draw_group(ToxWindow *self) wprintw(win, "Group commands:\n"); wattroff(win, A_BOLD | COLOR_PAIR(RED)); - wprintw(win, " /topic : Set group topic (show current topic if no msg)\n"); wprintw(win, " /chatid : Print the group chat id to share with others.\n"); wprintw(win, " /ignore : Ignore peer\n"); + wprintw(win, " /rejoin : Rejoin the group (only works if not connected)\n"); + wprintw(win, " /topic : Set group topic (show current topic if no msg)\n"); wprintw(win, " /unignore : Unignore peer \n\n"); #ifdef AUDIO @@ -312,9 +313,9 @@ void help_onKey(ToxWindow *self, wint_t key) case 'r': #ifdef AUDIO - help_init_window(self, 13, 80); + help_init_window(self, 14, 80); #else - help_init_window(self, 9, 80); + help_init_window(self, 10, 80); #endif self->help->type = HELP_GROUP; break; From f8ff5df2f37f6208e0bfd70b250afcecf3404721 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Fri, 13 Mar 2015 16:32:35 -0400 Subject: [PATCH 18/45] fix race conditions --- src/groupchat.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/groupchat.c b/src/groupchat.c index 1e782a9..fe23739 100644 --- a/src/groupchat.c +++ b/src/groupchat.c @@ -783,7 +783,9 @@ static void groupchat_onDraw(ToxWindow *self, Tox *m) mvwvline(ctx->sidebar, 0, 0, ACS_VLINE, y2 - CHATBOX_HEIGHT); mvwaddch(ctx->sidebar, y2 - CHATBOX_HEIGHT, 0, ACS_BTEE); + pthread_mutex_lock(&Winthread.lock); int num_peers = groupchats[self->num].num_peers; + pthread_mutex_unlock(&Winthread.lock); wmove(ctx->sidebar, 0, 1); wattron(ctx->sidebar, A_BOLD); @@ -803,11 +805,16 @@ static void groupchat_onDraw(ToxWindow *self, Tox *m) /* truncate nick to fit in side panel without modifying list */ char tmpnck[TOX_MAX_NAME_LENGTH]; int maxlen = SIDEBAR_WIDTH - 2; + pthread_mutex_lock(&Winthread.lock); memcpy(tmpnck, &groupchats[self->num].peer_names[peer * TOX_MAX_NAME_LENGTH], maxlen); + pthread_mutex_unlock(&Winthread.lock); tmpnck[maxlen] = '\0'; /* TODO: Make this not poll */ + pthread_mutex_lock(&Winthread.lock); uint8_t status = tox_group_get_status(m, self->num, i); + pthread_mutex_unlock(&Winthread.lock); + int colour = WHITE; if (status == TOX_GS_AWAY) From 02a0cac85a995edf76bfde18f027b1d115b6bfe1 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Fri, 13 Mar 2015 20:38:44 -0400 Subject: [PATCH 19/45] . --- src/windows.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/windows.c b/src/windows.c index d36f02a..4b58cad 100644 --- a/src/windows.c +++ b/src/windows.c @@ -661,7 +661,7 @@ void kill_all_windows(Tox *m) if (windows[i].is_chat) kill_chat_window(&windows[i], m); else if (windows[i].is_groupchat) - close_groupchat(&windows[i], m, windows[i].num, "Quit.", 5); + close_groupchat(&windows[i], m, windows[i].num, "Quit", 4); } kill_prompt_window(prompt); From 6cc8fdf2150a0acab14b281c23e6a9ac1bc7f3e4 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Thu, 19 Mar 2015 17:39:11 -0400 Subject: [PATCH 20/45] don't delete groups on client exit --- src/groupchat.c | 12 ++++++++---- src/groupchat.h | 2 +- src/windows.c | 2 +- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/groupchat.c b/src/groupchat.c index fe23739..f5b5ae3 100644 --- a/src/groupchat.c +++ b/src/groupchat.c @@ -167,10 +167,8 @@ static void kill_groupchat_window(ToxWindow *self) } /* Closes groupchat window and cleans up. */ -void close_groupchat(ToxWindow *self, Tox *m, int groupnum, const char *partmessage, int length) +void close_groupchat(ToxWindow *self, Tox *m, int groupnum) { - tox_group_delete(m, groupnum, (uint8_t *) partmessage, (uint16_t) length); - free(groupchats[groupnum].peer_names); free(groupchats[groupnum].peer_name_lengths); memset(&groupchats[groupnum], 0, sizeof(GroupChat)); @@ -186,6 +184,12 @@ void close_groupchat(ToxWindow *self, Tox *m, int groupnum, const char *partmess kill_groupchat_window(self); } +static void exit_groupchat(ToxWindow *self, Tox *m, int groupnum, const char *partmessage, int length) +{ + tox_group_delete(m, groupnum, (uint8_t *) partmessage, (uint16_t) length); + close_groupchat(self, m, groupnum); +} + /* Note: the arguments to these functions are validated in the caller functions */ void set_nick_all_groups(Tox *m, const char *nick, uint16_t length) { @@ -744,7 +748,7 @@ static void groupchat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr) if (line[offset] != '\0') ++offset; - close_groupchat(self, m, self->num, line + offset, ctx->len - offset); + exit_groupchat(self, m, self->num, line + offset, ctx->len - offset); return; } else if (strncmp(line, "/me ", 4) == 0) { send_group_action(self, m, self->num, line + 4); diff --git a/src/groupchat.h b/src/groupchat.h index 98d2e09..faafbeb 100644 --- a/src/groupchat.h +++ b/src/groupchat.h @@ -72,7 +72,7 @@ typedef struct { #endif } GroupChat; -void close_groupchat(ToxWindow *self, Tox *m, int groupnum, const char *partmessage, int length); +void close_groupchat(ToxWindow *self, Tox *m, int groupnum); int init_groupchat_win(Tox *m, int groupnum, const char *groupname, int length); void set_nick_all_groups(Tox *m, const char *nick, uint16_t length); void set_status_all_groups(Tox *m, uint8_t status); diff --git a/src/windows.c b/src/windows.c index 4b58cad..4f03e75 100644 --- a/src/windows.c +++ b/src/windows.c @@ -661,7 +661,7 @@ void kill_all_windows(Tox *m) if (windows[i].is_chat) kill_chat_window(&windows[i], m); else if (windows[i].is_groupchat) - close_groupchat(&windows[i], m, windows[i].num, "Quit", 4); + close_groupchat(&windows[i], m, windows[i].num); } kill_prompt_window(prompt); From 05c05868c606e72ff27c3f909aabc7f85b57adf5 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Sun, 22 Mar 2015 00:56:14 -0400 Subject: [PATCH 21/45] implement group private messaging --- doc/toxic.conf.5 | 9 +++-- doc/toxic.conf.5.asc | 3 ++ misc/toxic.conf.example | 5 ++- src/execute.c | 22 ++++++++---- src/groupchat.c | 78 ++++++++++++++++++++++++++++++++++------- src/help.c | 7 ++-- src/line_info.c | 12 ++++++- src/line_info.h | 2 ++ src/settings.c | 24 ++++++++----- src/settings.h | 2 ++ 10 files changed, 129 insertions(+), 35 deletions(-) diff --git a/doc/toxic.conf.5 b/doc/toxic.conf.5 index 7adb194..6b4ad6b 100644 --- a/doc/toxic.conf.5 +++ b/doc/toxic.conf.5 @@ -2,12 +2,12 @@ .\" Title: toxic.conf .\" Author: [see the "AUTHORS" section] .\" Generator: DocBook XSL Stylesheets v1.78.1 -.\" Date: 2015-02-19 +.\" Date: 2015-02-26 .\" Manual: Toxic Manual .\" Source: toxic __VERSION__ .\" Language: English .\" -.TH "TOXIC\&.CONF" "5" "2015\-02\-19" "toxic __VERSION__" "Toxic Manual" +.TH "TOXIC\&.CONF" "5" "2015\-02\-26" "toxic __VERSION__" "Toxic Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -138,6 +138,11 @@ Indicator for alert messages\&. Indicator for normal messages\&. .RE .PP +\fBline_special\fR +.RS 4 +Indicator for special messages\&. +.RE +.PP \fBmplex_away\fR .RS 4 Set user status when attaching and detaching from GNU screen or tmux\&. true or false diff --git a/doc/toxic.conf.5.asc b/doc/toxic.conf.5.asc index bfeb4fe..b276023 100644 --- a/doc/toxic.conf.5.asc +++ b/doc/toxic.conf.5.asc @@ -88,6 +88,9 @@ OPTIONS *line_normal*;; Indicator for normal messages. + *line_special*;; + Indicator for special messages. + *mplex_away*;; Set user status when attaching and detaching from GNU screen or tmux. true or false diff --git a/misc/toxic.conf.example b/misc/toxic.conf.example index a4bf7fd..f4c0d9d 100644 --- a/misc/toxic.conf.example +++ b/misc/toxic.conf.example @@ -44,6 +44,9 @@ ui = { // Indicator for normal messages. line_normal="---"; + // Indicator for special messages (currently only used for private group messages) + line_special=">>>"; + // true to change status based on screen/tmux attach/detach, false to disable mplex_away=true; @@ -57,7 +60,7 @@ audio = { // preferred audio output device; numbers correspond to /lsdev out output_device=0; - + // default VAD treshold; float (recommended values are around 40) VAD_treshold=40.0; }; diff --git a/src/execute.c b/src/execute.c index 0596904..dd24f28 100644 --- a/src/execute.c +++ b/src/execute.c @@ -94,8 +94,8 @@ static struct cmd_func group_commands[] = { { NULL, NULL }, }; -#define SPECIAL_COMMANDS 9 -static const char special_commands[SPECIAL_COMMANDS][MAX_CMDNAME_SIZE] = { +#define NUM_SPECIAL_COMMANDS 9 +static const char special_commands[NUM_SPECIAL_COMMANDS][MAX_CMDNAME_SIZE] = { "/ban", "/deop", "/group", @@ -117,7 +117,7 @@ static bool is_special_command(const char *input) int i; - for (i = 0; i < SPECIAL_COMMANDS; ++i) { + for (i = 0; i < NUM_SPECIAL_COMMANDS; ++i) { if (strncmp(input, special_commands[i], s) == 0) return true; } @@ -127,7 +127,9 @@ static bool is_special_command(const char *input) /* Parses commands in the special_commands array which take exactly one argument that may contain spaces. * Unlike parse_command, this function does not split the input string at spaces. - * Returns number of arguments on success, returns -1 on failure + * + * Returns number of arguments on success + * Returns -1 on failure */ static int parse_special_command(WINDOW *w, ToxWindow *self, const char *input, char (*args)[MAX_STR_SIZE]) { @@ -146,7 +148,9 @@ static int parse_special_command(WINDOW *w, ToxWindow *self, const char *input, } /* Parses input command and puts args (split by spaces) into args array. - * Returns number of arguments on success, -1 on failure. + * + * Returns number of arguments on success + * Returns -1 on failure. */ static int parse_command(WINDOW *w, ToxWindow *self, const char *input, char (*args)[MAX_STR_SIZE]) { @@ -194,7 +198,11 @@ static int parse_command(WINDOW *w, ToxWindow *self, const char *input, char (*a return num_args; } -/* Matches command to respective function. Returns 0 on match, 1 on no match */ +/* Matches command to respective function. + * + * Returns 0 on match, + * Returns -1 on no match + */ static int do_command(WINDOW *w, ToxWindow *self, Tox *m, int num_args, struct cmd_func *commands, char (*args)[MAX_STR_SIZE]) { @@ -207,7 +215,7 @@ static int do_command(WINDOW *w, ToxWindow *self, Tox *m, int num_args, struct c } } - return 1; + return -1; } void execute(WINDOW *w, ToxWindow *self, Tox *m, const char *input, int mode) diff --git a/src/groupchat.c b/src/groupchat.c index f5b5ae3..f97fb97 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 27 +#define AC_NUM_GROUP_COMMANDS 28 #else -#define AC_NUM_GROUP_COMMANDS 23 +#define AC_NUM_GROUP_COMMANDS 24 #endif /* AUDIO */ /* groupchat command names used for tab completion. */ @@ -100,6 +100,7 @@ static const char group_cmd_list[AC_NUM_GROUP_COMMANDS][MAX_CMDNAME_SIZE] = { { "/status" }, { "/topic" }, { "/unignore" }, + { "/whisper" }, #ifdef AUDIO @@ -345,7 +346,7 @@ static void groupchat_onGroupAction(ToxWindow *self, Tox *m, int groupnum, int p } static void groupchat_onGroupPrivateMessage(ToxWindow *self, Tox *m, int groupnum, uint32_t peernum, - const char *action, uint16_t len) + const char *msg, uint16_t len) { if (self->num != groupnum) return; @@ -358,8 +359,8 @@ static void groupchat_onGroupPrivateMessage(ToxWindow *self, Tox *m, int groupnu char timefrmt[TIME_STR_SIZE]; get_time_str(timefrmt, sizeof(timefrmt)); - line_info_add(self, timefrmt, nick, NULL, IN_MSG, 0, RED, "%s", action); - write_to_log(action, nick, ctx->log, false); + line_info_add(self, timefrmt, nick, NULL, IN_PRVT_MSG, 0, MAGENTA, "%s", msg); + write_to_log(msg, nick, ctx->log, false); sound_notify(self, silent, NT_WNDALERT_1, NULL); } @@ -627,9 +628,13 @@ static void send_group_message(ToxWindow *self, Tox *m, int groupnum, const char { ChatContext *ctx = self->chatwin; + if (msg == NULL) { + wprintw(ctx->history, "Invalid syntax.\n"); + return; + } + if (tox_group_message_send(m, self->num, (uint8_t *) msg, strlen(msg)) == -1) { - const char *errmsg = " * Failed to send message."; - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, RED, "%s", errmsg); + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, RED, " * Failed to send message"); return; } @@ -644,7 +649,7 @@ static void send_group_message(ToxWindow *self, Tox *m, int groupnum, const char write_to_log(msg, selfname, ctx->log, false); } -static void send_group_action(ToxWindow *self, Tox *m, int groupnum, char *action) +static void send_group_action(ToxWindow *self, Tox *m, int groupnum, const char *action) { ChatContext *ctx = self->chatwin; @@ -654,8 +659,7 @@ static void send_group_action(ToxWindow *self, Tox *m, int groupnum, char *actio } if (tox_group_action_send(m, groupnum, (uint8_t *) action, strlen(action)) == -1) { - const char *errmsg = " * Failed to send action."; - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, RED, "%s", errmsg); + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, RED, " * Failed to send action"); return; } @@ -670,6 +674,54 @@ static void send_group_action(ToxWindow *self, Tox *m, int groupnum, char *actio write_to_log(action, selfname, ctx->log, true); } +static void send_group_prvt_message(ToxWindow *self, Tox *m, int groupnum, const char *data) +{ + ChatContext *ctx = self->chatwin; + + if (data == NULL) { + wprintw(ctx->history, "Invalid syntax.\n"); + return; + } + + size_t i; + int peernum = -1, len = 0; + const char *msg = NULL; + + for (i = 0; i < groupchats[groupnum].num_peers; ++i) { + if (memcmp((char *) &groupchats[groupnum].peer_names[i * TOX_MAX_NAME_LENGTH], data, + groupchats[groupnum].peer_name_lengths[i]) == 0) { + len = strlen(data) - groupchats[groupnum].peer_name_lengths[i] - 1; + + if (len <= 0) + return; + + msg = data + groupchats[groupnum].peer_name_lengths[i] + 1; + peernum = i; + break; + } + } + + if (peernum == -1) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid peer name"); + return; + } + + if (tox_group_private_message_send(m, groupnum, peernum, (uint8_t *) msg, len) == -1) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, RED, " * Failed to send private message"); + return; + } + + char selfname[TOX_MAX_NAME_LENGTH]; + uint16_t slen = tox_group_get_self_name(m, groupnum, (uint8_t *) selfname); + selfname[slen] = '\0'; + + char timefrmt[TIME_STR_SIZE]; + get_time_str(timefrmt, sizeof(timefrmt)); + + line_info_add(self, timefrmt, selfname, NULL, OUT_PRVT_MSG, 0, 0, "%s", msg); + write_to_log(msg, selfname, ctx->log, false); +} + static void groupchat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr) { ChatContext *ctx = self->chatwin; @@ -742,7 +794,7 @@ static void groupchat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr) add_line_to_hist(ctx); if (line[0] == '/') { - if (strncmp(line, "/close", 6) == 0) { + if (strncmp(line, "/close", strlen("/close")) == 0) { int offset = 6; if (line[offset] != '\0') @@ -750,8 +802,10 @@ static void groupchat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr) exit_groupchat(self, m, self->num, line + offset, ctx->len - offset); return; - } else if (strncmp(line, "/me ", 4) == 0) { + } else if (strncmp(line, "/me ", strlen("/me ")) == 0) { send_group_action(self, m, self->num, line + 4); + } else if (strncmp(line, "/whisper ", strlen("/whisper ")) == 0) { + send_group_prvt_message(self, m, self->num, line + 9); } else { execute(ctx->history, self, m, line, GROUPCHAT_COMMAND_MODE); } diff --git a/src/help.c b/src/help.c index f817c5e..afb43d1 100644 --- a/src/help.c +++ b/src/help.c @@ -246,7 +246,8 @@ static void help_draw_group(ToxWindow *self) wprintw(win, " /ignore : Ignore peer\n"); wprintw(win, " /rejoin : Rejoin the group (only works if not connected)\n"); wprintw(win, " /topic : Set group topic (show current topic if no msg)\n"); - wprintw(win, " /unignore : Unignore peer \n\n"); + wprintw(win, " /unignore : Unignore peer \n"); + wprintw(win, " /whisper : Send private message to nick\n\n"); #ifdef AUDIO wattron(win, A_BOLD); @@ -313,9 +314,9 @@ void help_onKey(ToxWindow *self, wint_t key) case 'r': #ifdef AUDIO - help_init_window(self, 14, 80); + help_init_window(self, 15, 80); #else - help_init_window(self, 10, 80); + help_init_window(self, 11, 80); #endif self->help->type = HELP_GROUP; break; diff --git a/src/line_info.c b/src/line_info.c index 06b05e4..460ad78 100644 --- a/src/line_info.c +++ b/src/line_info.c @@ -164,6 +164,11 @@ void line_info_add(ToxWindow *self, const char *timestr, const char *name1, cons len += strlen(user_settings->line_normal) + 3; break; + case IN_PRVT_MSG: + case OUT_PRVT_MSG: + len += strlen(user_settings->line_special) + 3; + break; + case CONNECTION: len += strlen(user_settings->line_join) + 2; break; @@ -301,6 +306,8 @@ void line_info_print(ToxWindow *self) case OUT_MSG: case OUT_MSG_READ: case IN_MSG: + case IN_PRVT_MSG: + case OUT_PRVT_MSG: wattron(win, COLOR_PAIR(BLUE)); wprintw(win, "%s ", line->timestr); wattroff(win, COLOR_PAIR(BLUE)); @@ -313,7 +320,10 @@ void line_info_print(ToxWindow *self) nameclr = CYAN; wattron(win, COLOR_PAIR(nameclr)); - wprintw(win, "%s %s: ", user_settings->line_normal, line->name1); + wprintw(win, "%s %s: ",(type != OUT_PRVT_MSG && type != IN_PRVT_MSG) ? + user_settings->line_normal : + user_settings->line_special, + line->name1); wattroff(win, COLOR_PAIR(nameclr)); if (line->msg[0] == '>') diff --git a/src/line_info.h b/src/line_info.h index 0e5c9a1..0d65cb9 100644 --- a/src/line_info.h +++ b/src/line_info.h @@ -39,6 +39,8 @@ enum { IN_ACTION, OUT_ACTION, OUT_ACTION_READ, /* same as OUT_MSG_READ but for actions */ + IN_PRVT_MSG, /* PRVT should only be used for groups */ + OUT_PRVT_MSG, PROMPT, CONNECTION, DISCONNECTION, diff --git a/src/settings.c b/src/settings.c index 3775e5b..9df7c60 100644 --- a/src/settings.c +++ b/src/settings.c @@ -62,6 +62,7 @@ static struct ui_strings { const char* line_quit; const char* line_alert; const char* line_normal; + const char* line_special; const char* mplex_away; const char* mplex_away_note; @@ -82,11 +83,12 @@ static struct ui_strings { "line_quit", "line_alert", "line_normal", + "line_special", "mplex_away", "mplex_away_note", }; -static void ui_defaults(struct user_settings* settings) +static void ui_defaults(struct user_settings* settings) { settings->timestamps = TIMESTAMPS_ON; snprintf(settings->timestamp_format, sizeof(settings->timestamp_format), "%s", TIMESTAMP_DEFAULT); @@ -104,6 +106,7 @@ static void ui_defaults(struct user_settings* settings) snprintf(settings->line_quit, LINE_HINT_MAX + 1, "%s", LINE_QUIT); snprintf(settings->line_alert, LINE_HINT_MAX + 1, "%s", LINE_ALERT); snprintf(settings->line_normal, LINE_HINT_MAX + 1, "%s", LINE_NORMAL); + snprintf(settings->line_special, LINE_HINT_MAX + 1, "%s", LINE_SPECIAL); settings->mplex_away = MPLEX_ON; snprintf (settings->mplex_away_note, @@ -225,11 +228,11 @@ static int key_parse(const char** bind){ int len = strlen(*bind); if (len > 5) { - if(strncasecmp(*bind, "ctrl+", 5) == 0) + if(strncasecmp(*bind, "ctrl+", 5) == 0) return toupper(bind[0][5]) - 'A' + 1; } - if (strncasecmp(*bind, "tab", 3) == 0) + if (strncasecmp(*bind, "tab", 3) == 0) return T_KEY_TAB; if (strncasecmp(*bind, "page", 4) == 0) @@ -321,6 +324,9 @@ int settings_load(struct user_settings *s, const char *patharg) if ( config_setting_lookup_string(setting, ui_strings.line_normal, &str) ) { snprintf(s->line_normal, sizeof(s->line_normal), "%s", str); } + if ( config_setting_lookup_string(setting, ui_strings.line_special, &str) ) { + snprintf(s->line_special, sizeof(s->line_special), "%s", str); + } config_setting_lookup_bool (setting, ui_strings.mplex_away, &s->mplex_away); @@ -346,7 +352,7 @@ int settings_load(struct user_settings *s, const char *patharg) snprintf(s->chatlogs_path, sizeof(s->chatlogs_path), "%s", str); int len = strlen(s->chatlogs_path); - if (len >= sizeof(s->chatlogs_path) - 2) + if (len >= sizeof(s->chatlogs_path) - 2) s->chatlogs_path[0] = '\0'; else if (s->chatlogs_path[len - 1] != '/') strcat(&s->chatlogs_path[len - 1], "/"); @@ -356,7 +362,7 @@ int settings_load(struct user_settings *s, const char *patharg) snprintf(s->avatar_path, sizeof(s->avatar_path), "%s", str); int len = strlen(str); - if (len >= sizeof(s->avatar_path)) + if (len >= sizeof(s->avatar_path)) s->avatar_path[0] = '\0'; } } @@ -423,25 +429,25 @@ int settings_load(struct user_settings *s, const char *patharg) if (str && strcasecmp(str, NO_SOUND) != 0) set_sound(call_incoming, PACKAGE_DATADIR "/sounds/ToxicIncomingCall.wav"); } - + if ( !config_setting_lookup_string(setting, sound_strings.call_outgoing, &str) || !set_sound(call_outgoing, str) ) { if (str && strcasecmp(str, NO_SOUND) != 0) set_sound(call_outgoing, PACKAGE_DATADIR "/sounds/ToxicOutgoingCall.wav"); } - + if ( !config_setting_lookup_string(setting, sound_strings.generic_message, &str) || !set_sound(generic_message, str) ) { if (str && strcasecmp(str, NO_SOUND) != 0) set_sound(generic_message, PACKAGE_DATADIR "/sounds/ToxicRecvMessage.wav"); } - + if ( !config_setting_lookup_string(setting, sound_strings.transfer_pending, &str) || !set_sound(transfer_pending, str) ) { if (str && strcasecmp(str, NO_SOUND) != 0) set_sound(transfer_pending, PACKAGE_DATADIR "/sounds/ToxicTransferStart.wav"); } - + if ( !config_setting_lookup_string(setting, sound_strings.transfer_completed, &str) || !set_sound(transfer_completed, str) ) { if (str && strcasecmp(str, NO_SOUND) != 0) diff --git a/src/settings.h b/src/settings.h index 5403f0e..2e02a01 100644 --- a/src/settings.h +++ b/src/settings.h @@ -49,6 +49,7 @@ struct user_settings { char line_quit[LINE_HINT_MAX + 1]; char line_alert[LINE_HINT_MAX + 1]; char line_normal[LINE_HINT_MAX + 1]; + char line_special[LINE_HINT_MAX + 1]; char download_path[PATH_MAX]; char chatlogs_path[PATH_MAX]; @@ -104,6 +105,7 @@ enum { #define LINE_QUIT "<--" #define LINE_ALERT "-!-" #define LINE_NORMAL "---" +#define LINE_SPECIAL ">>>" #define TIMESTAMP_DEFAULT "%H:%M:%S" #define LOG_TIMESTAMP_DEFAULT "%Y/%m/%d [%H:%M:%S]" #define MPLEX_AWAY_NOTE "Detached from screen" From 59b90b132896122577aa5fde5d1db698465b02d3 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Sun, 22 Mar 2015 01:37:07 -0400 Subject: [PATCH 22/45] better format for private messages --- src/groupchat.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/groupchat.c b/src/groupchat.c index f97fb97..f410b39 100644 --- a/src/groupchat.c +++ b/src/groupchat.c @@ -686,6 +686,7 @@ static void send_group_prvt_message(ToxWindow *self, Tox *m, int groupnum, const size_t i; int peernum = -1, len = 0; const char *msg = NULL; + char *nick = NULL; for (i = 0; i < groupchats[groupnum].num_peers; ++i) { if (memcmp((char *) &groupchats[groupnum].peer_names[i * TOX_MAX_NAME_LENGTH], data, @@ -696,6 +697,7 @@ static void send_group_prvt_message(ToxWindow *self, Tox *m, int groupnum, const return; msg = data + groupchats[groupnum].peer_name_lengths[i] + 1; + nick = (char *) &groupchats[groupnum].peer_names[i * TOX_MAX_NAME_LENGTH]; peernum = i; break; } @@ -711,15 +713,17 @@ static void send_group_prvt_message(ToxWindow *self, Tox *m, int groupnum, const return; } - char selfname[TOX_MAX_NAME_LENGTH]; - uint16_t slen = tox_group_get_self_name(m, groupnum, (uint8_t *) selfname); - selfname[slen] = '\0'; + /* turn "peername" into ">peername<" to signify private message */ + char pm_nick[TOX_MAX_NAME_LENGTH + 2]; + strcpy(pm_nick, ">"); + strcpy(pm_nick + 1, nick); + strcpy(pm_nick + 1 + groupchats[groupnum].peer_name_lengths[i], "<"); char timefrmt[TIME_STR_SIZE]; get_time_str(timefrmt, sizeof(timefrmt)); - line_info_add(self, timefrmt, selfname, NULL, OUT_PRVT_MSG, 0, 0, "%s", msg); - write_to_log(msg, selfname, ctx->log, false); + line_info_add(self, timefrmt, pm_nick, NULL, OUT_PRVT_MSG, 0, 0, "%s", msg); + write_to_log(msg, pm_nick, ctx->log, false); } static void groupchat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr) From 5caa9bed51f4c5804a40ee400d09384ebffdb0f4 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Sun, 22 Mar 2015 17:01:46 -0400 Subject: [PATCH 23/45] fix nick parsing bug for private messages --- src/groupchat.c | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/src/groupchat.c b/src/groupchat.c index f410b39..b16fed3 100644 --- a/src/groupchat.c +++ b/src/groupchat.c @@ -684,22 +684,18 @@ static void send_group_prvt_message(ToxWindow *self, Tox *m, int groupnum, const } size_t i; - int peernum = -1, len = 0; - const char *msg = NULL; + int peernum = -1, nick_len = 0; char *nick = NULL; + /* need to match the longest nick in case of nicks that are smaller sub-strings */ for (i = 0; i < groupchats[groupnum].num_peers; ++i) { if (memcmp((char *) &groupchats[groupnum].peer_names[i * TOX_MAX_NAME_LENGTH], data, groupchats[groupnum].peer_name_lengths[i]) == 0) { - len = strlen(data) - groupchats[groupnum].peer_name_lengths[i] - 1; - - if (len <= 0) - return; - - msg = data + groupchats[groupnum].peer_name_lengths[i] + 1; - nick = (char *) &groupchats[groupnum].peer_names[i * TOX_MAX_NAME_LENGTH]; - peernum = i; - break; + if (groupchats[groupnum].peer_name_lengths[i] > nick_len) { + nick_len = groupchats[groupnum].peer_name_lengths[i]; + nick = (char *) &groupchats[groupnum].peer_names[i * TOX_MAX_NAME_LENGTH]; + peernum = i; + } } } @@ -708,7 +704,14 @@ static void send_group_prvt_message(ToxWindow *self, Tox *m, int groupnum, const return; } - if (tox_group_private_message_send(m, groupnum, peernum, (uint8_t *) msg, len) == -1) { + int msg_len = strlen(data) - groupchats[groupnum].peer_name_lengths[peernum] - 1; + + if (msg_len <= 0) + return; + + const char *msg = data + groupchats[groupnum].peer_name_lengths[peernum] + 1; + + if (tox_group_private_message_send(m, groupnum, peernum, (uint8_t *) msg, msg_len) == -1) { line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, RED, " * Failed to send private message"); return; } @@ -717,7 +720,7 @@ static void send_group_prvt_message(ToxWindow *self, Tox *m, int groupnum, const char pm_nick[TOX_MAX_NAME_LENGTH + 2]; strcpy(pm_nick, ">"); strcpy(pm_nick + 1, nick); - strcpy(pm_nick + 1 + groupchats[groupnum].peer_name_lengths[i], "<"); + strcpy(pm_nick + 1 + groupchats[groupnum].peer_name_lengths[peernum], "<"); char timefrmt[TIME_STR_SIZE]; get_time_str(timefrmt, sizeof(timefrmt)); From 386c5a8fa5cc3690cac9a0e654d6eb22e10bb5c7 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Sun, 22 Mar 2015 17:07:33 -0400 Subject: [PATCH 24/45] sound/desktop alert on private group message --- src/groupchat.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/groupchat.c b/src/groupchat.c index b16fed3..f024b68 100644 --- a/src/groupchat.c +++ b/src/groupchat.c @@ -361,7 +361,13 @@ static void groupchat_onGroupPrivateMessage(ToxWindow *self, Tox *m, int groupnu line_info_add(self, timefrmt, nick, NULL, IN_PRVT_MSG, 0, MAGENTA, "%s", msg); write_to_log(msg, nick, ctx->log, false); - sound_notify(self, silent, NT_WNDALERT_1, NULL); + + sound_notify(self, generic_message, NT_WNDALERT_0, NULL); + + if (self->active_box != -1) + box_silent_notify2(self, NT_NOFOCUS, self->active_box, "%s %s", nick, msg); + else + box_silent_notify(self, NT_NOFOCUS, &self->active_box, self->name, "%s %s", nick, msg); } static void groupchat_onGroupTopicChange(ToxWindow *self, Tox *m, int groupnum, uint32_t peernum, From 88719c4cccde7b202aece32c0e80f48a46579941 Mon Sep 17 00:00:00 2001 From: Sean Date: Wed, 25 Mar 2015 23:56:40 -0700 Subject: [PATCH 25/45] Update .travis.yml --- .travis.yml | 54 ++++++----------------------------------------------- 1 file changed, 6 insertions(+), 48 deletions(-) diff --git a/.travis.yml b/.travis.yml index 07ec154..df0ae2b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,52 +1,10 @@ -language: c -compiler: - - gcc - - clang - +env: + m+RsGCgemJNMKbinD97PtjC1pUuFzDBrAol3tI6Z3xP1FE2qF0/efbcC5OyNwUWwcaqGRb83d0vWt4hzhxMwrwJC8O6EFLFHgJs0WpslP+++KRN30PUOqRFFqH404InF4pFNULlnwJYFZ8bGft4ThxppbEOeSYcXN4WSgb66RjM= before_script: - # Installing yasm (needed for compiling vpx) and openal - - sudo apt-get -yq install yasm libopenal-dev libconfig-dev libalut-dev libnotify-dev clang llvm-dev - # Installing libsodium, needed for toxcore - - git clone https://github.com/jedisct1/libsodium.git libsodium - - cd libsodium - - git checkout tags/1.0.2 > /dev/null - - ./autogen.sh > /dev/null - - ./configure > /dev/null - - make check -j2 || make check || exit 1 > /dev/null - - sudo make install > /dev/null - - cd .. - # Installing libopus, needed for audio encoding/decoding - - wget http://downloads.xiph.org/releases/opus/opus-1.0.3.tar.gz - - tar xzf opus-1.0.3.tar.gz > /dev/null - - cd opus-1.0.3 - - ./configure > /dev/null - - make -j2 || make || exit 1 > /dev/null - - sudo make install > /dev/null - - cd .. - # Installing vpx - - git clone http://git.chromium.org/webm/libvpx.git libvpx - - cd libvpx - - ./configure --enable-shared > /dev/null - - make -j2 || make || exit 1 > /dev/null - - sudo make install > /dev/null - - cd .. - # Creating libraries links and updating cache - - sudo ldconfig > /dev/null - # Installing toxcore - - git clone https://github.com/irungentoo/toxcore.git toxcore - - cd toxcore - - autoreconf -i - - ./configure --disable-tests --disable-ntox --disable-daemon --enable-av - - make -j2 || make || exit 1 - - sudo make install - - cd .. + - sudo apt-get install curl + script: - - make -j2 || make || exit 1 + - curl https://jenkins.libtoxcore.so/job/toxic_linux_beta/build?token=$TOKEN + notifications: email: false - - irc: - channels: - - "chat.freenode.net#tox-dev" - on_success: always - on_failure: always From e34ac70a726184e56697b22f77f700d8328908a5 Mon Sep 17 00:00:00 2001 From: Sean Date: Thu, 26 Mar 2015 00:12:30 -0700 Subject: [PATCH 26/45] I'm not allowed to do this correctly on the first try. --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index df0ae2b..a218319 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,6 @@ env: - m+RsGCgemJNMKbinD97PtjC1pUuFzDBrAol3tI6Z3xP1FE2qF0/efbcC5OyNwUWwcaqGRb83d0vWt4hzhxMwrwJC8O6EFLFHgJs0WpslP+++KRN30PUOqRFFqH404InF4pFNULlnwJYFZ8bGft4ThxppbEOeSYcXN4WSgb66RjM= + secure: m+RsGCgemJNMKbinD97PtjC1pUuFzDBrAol3tI6Z3xP1FE2qF0/efbcC5OyNwUWwcaqGRb83d0vWt4hzhxMwrwJC8O6EFLFHgJs0WpslP+++KRN30PUOqRFFqH404InF4pFNULlnwJYFZ8bGft4ThxppbEOeSYcXN4WSgb66RjM= + before_script: - sudo apt-get install curl From ee074f334e040047db077f7a7e4d0de06e03cdbb Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Mon, 30 Mar 2015 21:46:25 -0400 Subject: [PATCH 27/45] merge with master (new api) --- Makefile | 2 +- README.md | 2 +- cfg/global_vars.mk | 2 +- doc/toxic.1 | 9 +- doc/toxic.1.asc | 7 +- doc/toxic.conf.5 | 2 +- doc/toxic.conf.5.asc | 2 +- src/audio_call.c | 138 ++++----- src/chat.c | 635 ++++++++++++++++++++---------------------- src/chat_commands.c | 231 ++++++++------- src/dns.c | 30 +- src/file_senders.c | 293 ------------------- src/file_senders.h | 76 ----- src/file_transfers.c | 236 ++++++++++++++++ src/file_transfers.h | 110 ++++++++ src/friendlist.c | 365 ++++++++++++------------ src/friendlist.h | 45 ++- src/global_commands.c | 237 ++++++++-------- src/global_commands.h | 2 +- src/groupchat.c | 16 +- src/input.c | 18 +- src/line_info.c | 10 +- src/message_queue.c | 12 +- src/message_queue.h | 6 +- src/misc_tools.c | 34 ++- src/misc_tools.h | 10 +- src/notify.c | 134 ++++----- src/notify.h | 10 +- src/prompt.c | 81 +++--- src/prompt.h | 5 +- src/settings.c | 12 +- src/settings.h | 2 +- src/term_mplex.c | 20 +- src/toxic.c | 407 ++++++++++++++------------- src/toxic.h | 44 +-- src/toxic_strings.c | 4 +- src/windows.c | 124 +++++---- src/windows.h | 63 +++-- 38 files changed, 1710 insertions(+), 1726 deletions(-) delete mode 100644 src/file_senders.c delete mode 100644 src/file_senders.h create mode 100644 src/file_transfers.c create mode 100644 src/file_transfers.h diff --git a/Makefile b/Makefile index 07fa384..f6f4209 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,7 @@ CFLAGS += '-DPACKAGE_DATADIR="$(abspath $(DATADIR))"' CFLAGS += $(USER_CFLAGS) LDFLAGS = $(USER_LDFLAGS) -OBJ = chat.o chat_commands.o configdir.o dns.o execute.o file_senders.o notify.o +OBJ = chat.o chat_commands.o configdir.o dns.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 diff --git a/README.md b/README.md index d3cc263..dd78dae 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ Toxic is a [Tox](https://tox.im)-based instant messenging client which formerly If you don't like installation methods listed above, you can still download precompiled binaries from [jenkins](https://jenkins.libtoxcore.so): * [Linux 32 bit](https://jenkins.libtoxcore.so/job/toxic_linux_i386/lastSuccessfulBuild/artifact/toxic_linux_i386.tar.xz) [![Build Status](https://jenkins.libtoxcore.so/job/toxic_linux_i386/badge/icon)](https://jenkins.libtoxcore.so/job/toxic_linux_i386/lastSuccessfulBuild/artifact/toxic_linux_i386.tar.xz) * [Linux 64 bit](https://jenkins.libtoxcore.so/job/toxic_linux_amd64/lastSuccessfulBuild/artifact/toxic_linux_amd64.tar.xz) [![Build Status](https://jenkins.libtoxcore.so/job/toxic_linux_amd64/badge/icon)](https://jenkins.libtoxcore.so/job/toxic_linux_amd64/lastSuccessfulBuild/artifact/toxic_linux_amd64.tar.xz) -* [~~Linux ARMv6~~](https://jenkins.libtoxcore.so/job/toxic_linux_armv6/lastSuccessfulBuild/artifact/toxic_linux_armv6.tar.xz) **CURRENTLY DISABLED** [![Build Status](https://jenkins.libtoxcore.so/job/toxic_linux_amd64/badge/icon)](https://jenkins.libtoxcore.so/job/toxic_linux_armv6/lastSuccessfulBuild/artifact/toxic_linux_armv6.tar.xz) +* [~~Linux ARMv6~~](https://jenkins.libtoxcore.so/job/toxic_linux_armv6/lastSuccessfulBuild/artifact/toxic_linux_armv6.tar.xz) **CURRENTLY DISABLED** [![Build Status](https://jenkins.libtoxcore.so/job/toxic_linux_armv6/badge/icon)](https://jenkins.libtoxcore.so/job/toxic_linux_armv6/lastSuccessfulBuild/artifact/toxic_linux_armv6.tar.xz) #### DEBs packages * [toxic-i386.deb](https://jenkins.libtoxcore.so/job/toxic-linux-pkg/lastSuccessfulBuild/artifact/toxic-i386.deb) diff --git a/cfg/global_vars.mk b/cfg/global_vars.mk index 52942fa..d5c7b57 100644 --- a/cfg/global_vars.mk +++ b/cfg/global_vars.mk @@ -1,5 +1,5 @@ # Version -TOXIC_VERSION = 0.5.2 +TOXIC_VERSION = 0.6.0 REV = $(shell git rev-list HEAD --count 2>/dev/null || echo -n "error") ifneq (, $(findstring error, $(REV))) VERSION = $(TOXIC_VERSION) diff --git a/doc/toxic.1 b/doc/toxic.1 index f7e21e4..242072c 100644 --- a/doc/toxic.1 +++ b/doc/toxic.1 @@ -2,12 +2,12 @@ .\" Title: toxic .\" Author: [see the "AUTHORS" section] .\" Generator: DocBook XSL Stylesheets v1.78.1 -.\" Date: 2014-09-19 +.\" Date: 2014-12-27 .\" Manual: Toxic Manual .\" Source: toxic __VERSION__ .\" Language: English .\" -.TH "TOXIC" "1" "2014\-09\-19" "toxic __VERSION__" "Toxic Manual" +.TH "TOXIC" "1" "2014\-12\-27" "toxic __VERSION__" "Toxic Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -115,11 +115,6 @@ Force TCP connection (use this with proxies) .RS 4 Unencrypt a data file\&. A warning will appear if this option is used with a data file that is already unencrypted\&. .RE -.PP -\-x, \-\-nodata -.RS 4 -Ignore data file -.RE .SH "FILES" .PP __DATADIR__/DHTnodes diff --git a/doc/toxic.1.asc b/doc/toxic.1.asc index 93f3a86..0ee3c06 100644 --- a/doc/toxic.1.asc +++ b/doc/toxic.1.asc @@ -31,7 +31,7 @@ OPTIONS Use default locale -e, --encrypt-data:: - Encrypt an unencrypted data file. An error will occur if this option + Encrypt an unencrypted data file. An error will occur if this option is used with an encrypted data file. -f, --file data-file:: @@ -60,12 +60,9 @@ OPTIONS Force TCP connection (use this with proxies) -u, --unencrypt-data:: - Unencrypt a data file. A warning will appear if this option is used + Unencrypt a data file. A warning will appear if this option is used with a data file that is already unencrypted. --x, --nodata:: - Ignore data file - FILES ----- {datadir}/DHTnodes:: diff --git a/doc/toxic.conf.5 b/doc/toxic.conf.5 index 6b4ad6b..0aaa841 100644 --- a/doc/toxic.conf.5 +++ b/doc/toxic.conf.5 @@ -202,7 +202,7 @@ Configuration related to notification sounds\&. Special value "silent" can be us Each value is a string which corresponds to the absolute path of a wav sound file\&. .PP -\fBerror\fR +\fBnotif_error\fR .RS 4 Sound to play when an error occurs\&. .RE diff --git a/doc/toxic.conf.5.asc b/doc/toxic.conf.5.asc index b276023..267918f 100644 --- a/doc/toxic.conf.5.asc +++ b/doc/toxic.conf.5.asc @@ -132,7 +132,7 @@ OPTIONS Each value is a string which corresponds to the absolute path of a wav sound file. - *error*;; + *notif_error*;; Sound to play when an error occurs. *self_log_in*;; diff --git a/src/audio_call.c b/src/audio_call.c index ebe64eb..54b865b 100644 --- a/src/audio_call.c +++ b/src/audio_call.c @@ -59,7 +59,7 @@ static int set_call(Call* call, bool start) { call->in_idx = -1; call->out_idx = -1; - + if ( start ) { call->ttas = true; @@ -79,9 +79,9 @@ struct ASettings { AudioError errors; ToxAv *av; - + ToxAvCSettings cs; - + Call calls[MAX_CALLS]; } ASettins; @@ -105,15 +105,15 @@ static void print_err (ToxWindow *self, const char *error_str) } ToxAv *init_audio(ToxWindow *self, Tox *tox) -{ +{ ASettins.cs = av_DefaultSettings; ASettins.cs.max_video_height = ASettins.cs.max_video_width = 0; - + ASettins.errors = ae_None; - + memset(ASettins.calls, 0, sizeof(ASettins.calls)); - + /* Streaming stuff from core */ ASettins.av = toxav_new(tox, MAX_CALLS); @@ -122,7 +122,7 @@ ToxAv *init_audio(ToxWindow *self, Tox *tox) ASettins.errors |= ae_StartingCoreAudio; return NULL; } - + if ( init_devices(ASettins.av) == de_InternalError ) { line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to init devices"); toxav_kill(ASettins.av); @@ -142,7 +142,7 @@ ToxAv *init_audio(ToxWindow *self, Tox *tox) toxav_register_callstate_callback(ASettins.av, callback_requ_timeout, av_OnRequestTimeout, self); toxav_register_callstate_callback(ASettins.av, callback_peer_timeout, av_OnPeerTimeout, self); //toxav_register_callstate_callback(ASettins.av, callback_media_change, av_OnMediaChange, self); - + toxav_register_audio_callback(ASettins.av, write_device_callback, NULL); return ASettins.av; @@ -156,14 +156,14 @@ void terminate_audio() if ( ASettins.av ) toxav_kill(ASettins.av); - + terminate_devices(); } void read_device_callback (const int16_t* captured, uint32_t size, void* data) { int32_t call_index = *((int32_t*)data); /* TODO: Or pass an array of call_idx's */ - + uint8_t encoded_payload[RTP_PAYLOAD_SIZE]; int32_t payload_size = toxav_prepare_audio_frame(ASettins.av, call_index, encoded_payload, RTP_PAYLOAD_SIZE, captured, size); if ( payload_size <= 0 || toxav_send_audio(ASettins.av, call_index, encoded_payload, payload_size) < 0 ) { @@ -207,15 +207,15 @@ int start_transmission(ToxWindow *self, Call *call) toxav_get_peer_csettings(ASettins.av, self->call_idx, 0, &csettings); if ( open_primary_device(input, &call->in_idx, - csettings.audio_sample_rate, csettings.audio_frame_duration, csettings.audio_channels) != de_None ) + csettings.audio_sample_rate, csettings.audio_frame_duration, csettings.audio_channels) != de_None ) line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to open input device!"); - if ( register_device_callback(self->call_idx, call->in_idx, - read_device_callback, &self->call_idx, true) != de_None) + if ( register_device_callback(self->call_idx, call->in_idx, + read_device_callback, &self->call_idx, true) != de_None) /* Set VAD as true for all; TODO: Make it more dynamic */ line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to register input handler!"); - if ( open_primary_device(output, &call->out_idx, + if ( open_primary_device(output, &call->out_idx, csettings.audio_sample_rate, csettings.audio_frame_duration, csettings.audio_channels) != de_None ) { line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to open output device!"); call->has_output = 0; @@ -225,23 +225,23 @@ int start_transmission(ToxWindow *self, Call *call) } int stop_transmission(Call *call, int32_t call_index) -{ +{ if ( call->ttas ) { toxav_kill_transmission(ASettins.av, call_index); call->ttas = false; - + if ( call->in_idx != -1 ) close_device(input, call->in_idx); - + if ( call->out_idx != -1 ) close_device(output, call->out_idx); - + if (set_call(call, false) == -1) return -1; return 0; } - + return -1; } /* @@ -269,10 +269,10 @@ void callback_recv_ringing ( void* av, int32_t call_index, void* arg ) } void callback_recv_starting ( void* av, int32_t call_index, void* arg ) { - ToxWindow* windows = arg; + ToxWindow* windows = arg; int i; - for (i = 0; i < MAX_WINDOWS_NUM; ++i) - if (windows[i].onStarting != NULL && windows[i].call_idx == call_index) { + for (i = 0; i < MAX_WINDOWS_NUM; ++i) + if (windows[i].onStarting != NULL && windows[i].call_idx == call_index) { windows[i].onStarting(&windows[i], ASettins.av, call_index); if ( 0 != start_transmission(&windows[i], &ASettins.calls[call_index])) {/* YEAH! */ line_info_add(&windows[i], NULL, NULL, NULL, SYS_MSG, 0, 0 , "Error starting transmission!"); @@ -287,10 +287,10 @@ void callback_recv_ending ( void* av, int32_t call_index, void* arg ) } void callback_call_started ( void* av, int32_t call_index, void* arg ) -{ - ToxWindow* windows = arg; +{ + ToxWindow* windows = arg; int i; - for (i = 0; i < MAX_WINDOWS_NUM; ++i) + for (i = 0; i < MAX_WINDOWS_NUM; ++i) if (windows[i].onStart != NULL && windows[i].call_idx == call_index) { windows[i].onStart(&windows[i], ASettins.av, call_index); if ( 0 != start_transmission(&windows[i], &ASettins.calls[call_index]) ) {/* YEAH! */ @@ -357,7 +357,7 @@ void cmd_call(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA goto on_error; } - if (!self->stb->is_online) { + if (!self->stb->connection) { error_str = "Friend is offline."; goto on_error; } @@ -545,12 +545,12 @@ void cmd_change_device(WINDOW *window, ToxWindow *self, Tox *m, int argc, char ( error_str = "Invalid input"; goto on_error; } - + if ( set_primary_device(type, selection) == de_InvalidSelection ) { error_str="Invalid selection!"; goto on_error; } - + return; on_error: print_err (self, error_str); @@ -559,71 +559,71 @@ on_error: void cmd_ccur_device(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) { const char *error_str; - + if ( argc != 2 ) { if ( argc < 1 ) error_str = "Type must be specified!"; else if ( argc < 2 ) error_str = "Must have id!"; else error_str = "Only two arguments allowed!"; - + goto on_error; } - + DeviceType type; - + if ( strcmp(argv[1], "in") == 0 ) /* Input devices */ type = input; - + else if ( strcmp(argv[1], "out") == 0 ) /* Output devices */ type = output; - + else { line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid type: %s", argv[1]); return; } - - + + char *end; long int selection = strtol(argv[2], &end, 10); - + if ( *end ) { error_str = "Invalid input"; goto on_error; } - + if ( selection_valid(type, selection) == de_InvalidSelection ) { error_str="Invalid selection!"; goto on_error; } - + /* If call is active, change device */ if ( self->call_idx > -1) { Call* this_call = &ASettins.calls[self->call_idx]; if (this_call->ttas) { - + ToxAvCSettings csettings; toxav_get_peer_csettings(ASettins.av, self->call_idx, 0, &csettings); - + if (type == output) { pthread_mutex_lock(&this_call->mutex); close_device(output, this_call->out_idx); - this_call->has_output = open_device(output, selection, &this_call->out_idx, - csettings.audio_sample_rate, csettings.audio_frame_duration, csettings.audio_channels) + this_call->has_output = open_device(output, selection, &this_call->out_idx, + csettings.audio_sample_rate, csettings.audio_frame_duration, csettings.audio_channels) == de_None ? 1 : 0; pthread_mutex_unlock(&this_call->mutex); } else { /* TODO: check for failure */ close_device(input, this_call->in_idx); - open_device(input, selection, &this_call->in_idx, csettings.audio_sample_rate, + open_device(input, selection, &this_call->in_idx, csettings.audio_sample_rate, csettings.audio_frame_duration, csettings.audio_channels); /* Set VAD as true for all; TODO: Make it more dynamic */ register_device_callback(self->call_idx, this_call->in_idx, read_device_callback, &self->call_idx, true); } } } - + self->device_selection[type] = selection; - + return; on_error: print_err (self, error_str); @@ -632,33 +632,33 @@ void cmd_ccur_device(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*a void cmd_mute(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) { const char *error_str; - + if ( argc != 1 ) { if ( argc < 1 ) error_str = "Type must be specified!"; else error_str = "Only two arguments allowed!"; - + goto on_error; } - + DeviceType type; - + if ( strcasecmp(argv[1], "in") == 0 ) /* Input devices */ type = input; - + else if ( strcasecmp(argv[1], "out") == 0 ) /* Output devices */ type = output; - + else { line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid type: %s", argv[1]); return; } - - + + /* If call is active, use this_call values */ if ( self->call_idx > -1) { Call* this_call = &ASettins.calls[self->call_idx]; - - pthread_mutex_lock(&this_call->mutex); + + pthread_mutex_lock(&this_call->mutex); if (type == input) { device_mute(type, this_call->in_idx); self->chatwin->infobox.in_is_muted ^= 1; @@ -668,9 +668,9 @@ void cmd_mute(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA } pthread_mutex_unlock(&this_call->mutex); } - + return; - + on_error: print_err (self, error_str); } @@ -678,39 +678,39 @@ void cmd_mute(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA void cmd_sense(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) { const char *error_str; - + if ( argc != 1 ) { if ( argc < 1 ) error_str = "Must have value!"; else error_str = "Only two arguments allowed!"; - + goto on_error; } - + char *end; float value = strtof(argv[1], &end); - + if ( *end ) { error_str = "Invalid input"; goto on_error; } - + /* Call must be active */ if ( self->call_idx > -1) { device_set_VAD_treshold(ASettins.calls[self->call_idx].in_idx, value); self->chatwin->infobox.vad_lvl = value; - } - + } + return; - + on_error: print_err (self, error_str); } void stop_current_call(ToxWindow* self) -{ +{ ToxAvCallState callstate; - if ( ASettins.av != NULL && self->call_idx != -1 && + if ( ASettins.av != NULL && self->call_idx != -1 && ( callstate = toxav_get_call_state(ASettins.av, self->call_idx) ) != av_CallNonExistent) { switch (callstate) { diff --git a/src/chat.c b/src/chat.c index a5821a2..ed5dc60 100644 --- a/src/chat.c +++ b/src/chat.c @@ -29,11 +29,13 @@ #include #include #include +#include #include "toxic.h" #include "windows.h" #include "execute.h" #include "misc_tools.h" +#include "file_transfers.h" #include "friendlist.h" #include "toxic_strings.h" #include "log.h" @@ -49,10 +51,7 @@ #include "audio_call.h" #endif /* AUDIO */ - extern char *DATA_FILE; - -extern FileSender file_senders[MAX_FILES]; extern FriendsList Friends; extern struct Winthread Winthread; @@ -105,25 +104,23 @@ static const char chat_cmd_list[AC_NUM_CHAT_COMMANDS][MAX_CMDNAME_SIZE] = { #endif /* AUDIO */ }; -static void set_self_typingstatus(ToxWindow *self, Tox *m, uint8_t is_typing) +static void set_self_typingstatus(ToxWindow *self, Tox *m, bool is_typing) { if (user_settings->show_typing_self == SHOW_TYPING_OFF) return; ChatContext *ctx = self->chatwin; - tox_set_user_is_typing(m, self->num, is_typing); + tox_self_set_typing(m, self->num, is_typing, NULL); ctx->self_is_typing = is_typing; } -static void close_all_file_receivers(Tox *m, int friendnum); - void kill_chat_window(ToxWindow *self, Tox *m) { ChatContext *ctx = self->chatwin; StatusBar *statusbar = self->stb; - close_all_file_receivers(m, self->num); + kill_all_file_transfers_friend(m, self->num); log_disable(ctx->log); line_info_cleanup(ctx->hst); cqueue_cleanup(ctx->cqueue); @@ -145,19 +142,11 @@ void kill_chat_window(ToxWindow *self, Tox *m) del_window(self); } -static void chat_onMessage(ToxWindow *self, Tox *m, int32_t num, const char *msg, uint16_t len) +static void recv_message_helper(ToxWindow *self, Tox *m, uint32_t num, const char *msg, size_t len, + const char *nick, const char *timefrmt) { - if (self->num != num) - return; - ChatContext *ctx = self->chatwin; - char nick[TOX_MAX_NAME_LENGTH]; - get_nick_truncate(m, nick, num); - - char timefrmt[TIME_STR_SIZE]; - get_time_str(timefrmt, sizeof(timefrmt)); - line_info_add(self, timefrmt, nick, NULL, IN_MSG, 0, 0, "%s", msg); write_to_log(msg, nick, ctx->log, false); @@ -165,13 +154,44 @@ static void chat_onMessage(ToxWindow *self, Tox *m, int32_t num, const char *msg box_notify2(self, generic_message, NT_WNDALERT_1 | NT_NOFOCUS, self->active_box, "%s", msg); else box_notify(self, generic_message, NT_WNDALERT_1 | NT_NOFOCUS, &self->active_box, nick, "%s", msg); - } -static void chat_resume_file_transfers(Tox *m, int fnum); -static void chat_stop_file_senders(int fnum); +static void recv_action_helper(ToxWindow *self, Tox *m, uint32_t num, const char *action, size_t len, + const char *nick, const char *timefrmt) +{ + ChatContext *ctx = self->chatwin; -static void chat_onConnectionChange(ToxWindow *self, Tox *m, int32_t num, uint8_t status) + line_info_add(self, timefrmt, nick, NULL, IN_ACTION, 0, 0, "%s", action); + write_to_log(action, nick, ctx->log, true); + + if (self->active_box != -1) + box_notify2(self, generic_message, NT_WNDALERT_1 | NT_NOFOCUS, self->active_box, "* %s %s", nick, action ); + else + box_notify(self, generic_message, NT_WNDALERT_1 | NT_NOFOCUS, &self->active_box, self->name, "* %s %s", nick, action ); +} + +static void chat_onMessage(ToxWindow *self, Tox *m, uint32_t num, TOX_MESSAGE_TYPE type, const char *msg, size_t len) +{ + if (self->num != num) + return; + + char nick[TOX_MAX_NAME_LENGTH]; + get_nick_truncate(m, nick, num); + + char timefrmt[TIME_STR_SIZE]; + get_time_str(timefrmt, sizeof(timefrmt)); + + if (type == TOX_MESSAGE_TYPE_NORMAL) + return recv_message_helper(self, m, num, msg, len, nick, timefrmt); + + if (type == TOX_MESSAGE_TYPE_ACTION) + return recv_action_helper(self, m, num, msg, len, nick, timefrmt); +} + +static void chat_resume_file_transfers(Tox *m, uint32_t fnum); +static void chat_stop_file_senders(Tox *m, uint32_t friendnum); + +static void chat_onConnectionChange(ToxWindow *self, Tox *m, uint32_t num, TOX_CONNECTION connection_status) { if (self->num != num) return; @@ -186,23 +206,23 @@ static void chat_onConnectionChange(ToxWindow *self, Tox *m, int32_t num, uint8_ char nick[TOX_MAX_NAME_LENGTH]; get_nick_truncate(m, nick, num); - if (status == 1) { /* Friend goes online */ - statusbar->is_online = true; + statusbar->connection = connection_status; + + if (connection_status != TOX_CONNECTION_NONE) { Friends.list[num].is_typing = user_settings->show_typing_other == SHOW_TYPING_ON - ? tox_get_is_typing(m, num) : 0; + ? tox_friend_get_typing(m, num, NULL) : false; chat_resume_file_transfers(m, num); msg = "has come online"; line_info_add(self, timefrmt, nick, NULL, CONNECTION, 0, GREEN, msg); write_to_log(msg, nick, ctx->log, true); - } else { /* Friend goes offline */ - statusbar->is_online = false; - Friends.list[num].is_typing = 0; + } else { + Friends.list[num].is_typing = false; if (self->chatwin->self_is_typing) set_self_typingstatus(self, m, 0); - chat_stop_file_senders(num); + chat_stop_file_senders(m, num); msg = "has gone offline"; line_info_add(self, timefrmt, nick, NULL, DISCONNECTION, 0, RED, msg); @@ -210,7 +230,7 @@ static void chat_onConnectionChange(ToxWindow *self, Tox *m, int32_t num, uint8_ } } -static void chat_onTypingChange(ToxWindow *self, Tox *m, int32_t num, uint8_t is_typing) +static void chat_onTypingChange(ToxWindow *self, Tox *m, uint32_t num, bool is_typing) { if (self->num != num) return; @@ -218,29 +238,7 @@ static void chat_onTypingChange(ToxWindow *self, Tox *m, int32_t num, uint8_t is Friends.list[num].is_typing = is_typing; } -static void chat_onAction(ToxWindow *self, Tox *m, int32_t num, const char *action, uint16_t len) -{ - if (self->num != num) - return; - - ChatContext *ctx = self->chatwin; - - char nick[TOX_MAX_NAME_LENGTH]; - get_nick_truncate(m, nick, num); - - char timefrmt[TIME_STR_SIZE]; - get_time_str(timefrmt, sizeof(timefrmt)); - - line_info_add(self, timefrmt, nick, NULL, IN_ACTION, 0, 0, "%s", action); - write_to_log(action, nick, ctx->log, true); - - if (self->active_box != -1) - box_notify2(self, generic_message, NT_WNDALERT_1 | NT_NOFOCUS, self->active_box, "* %s %s", nick, action ); - else - box_notify(self, generic_message, NT_WNDALERT_1 | NT_NOFOCUS, &self->active_box, self->name, "* %s %s", nick, action ); -} - -static void chat_onNickChange(ToxWindow *self, Tox *m, int32_t num, const char *nick, uint16_t len) +static void chat_onNickChange(ToxWindow *self, Tox *m, uint32_t num, const char *nick, size_t length) { if (self->num != num) return; @@ -248,13 +246,13 @@ static void chat_onNickChange(ToxWindow *self, Tox *m, int32_t num, const char * StatusBar *statusbar = self->stb; snprintf(statusbar->nick, sizeof(statusbar->nick), "%s", nick); - len = strlen(statusbar->nick); - statusbar->nick_len = len; + length = strlen(statusbar->nick); + statusbar->nick_len = length; - set_window_title(self, statusbar->nick, len); + set_window_title(self, statusbar->nick, length); } -static void chat_onStatusChange(ToxWindow *self, Tox *m, int32_t num, uint8_t status) +static void chat_onStatusChange(ToxWindow *self, Tox *m, uint32_t num, TOX_USER_STATUS status) { if (self->num != num) return; @@ -263,7 +261,7 @@ static void chat_onStatusChange(ToxWindow *self, Tox *m, int32_t num, uint8_t st statusbar->status = status; } -static void chat_onStatusMessageChange(ToxWindow *self, int32_t num, const char *status, uint16_t len) +static void chat_onStatusMessageChange(ToxWindow *self, uint32_t num, const char *status, size_t length) { if (self->num != num) return; @@ -274,83 +272,237 @@ static void chat_onStatusMessageChange(ToxWindow *self, int32_t num, const char statusbar->statusmsg_len = strlen(statusbar->statusmsg); } -static void chat_onReadReceipt(ToxWindow *self, Tox *m, int32_t num, uint32_t receipt) +static void chat_onReadReceipt(ToxWindow *self, Tox *m, uint32_t num, uint32_t receipt) { cqueue_remove(self, m, receipt); } -static void chat_onFileSendRequest(ToxWindow *self, Tox *m, int32_t num, uint8_t filenum, - uint64_t filesize, const char *pathname, uint16_t path_len) +/* Stops active file senders for this friend. Call when a friend goes offline */ +static void chat_stop_file_senders(Tox *m, uint32_t friendnum) { - if (self->num != num) + // TODO: core purges file transfers when a friend goes offline. Ideally we want to repair/resume + kill_all_file_transfers_friend(m, friendnum); +} + +/* Tries to resume broken file transfers. Call when a friend comes online */ +static void chat_resume_file_transfers(Tox *m, uint32_t fnum) +{ + // TODO +} + +static void chat_onFileChunkRequest(ToxWindow *self, Tox *m, uint32_t friendnum, uint32_t filenum, uint64_t position, + size_t length) +{ + if (friendnum != self->num) return; - /* holds the filename appended to the user specified path */ - char filename_path[MAX_STR_SIZE] = {0}; + struct FileTransfer *ft = get_file_transfer_struct(friendnum, filenum); + + if (ft == NULL) + return; + + if (ft->state != FILE_TRANSFER_STARTED) + return; + + char msg[MAX_STR_SIZE]; + + if (length == 0) { + snprintf(msg, sizeof(msg), "File '%s' successfully sent.", ft->file_name); + print_progress_bar(self, ft->bps, 100.0, ft->line_id); + close_file_transfer(self, m, ft, -1, msg, transfer_completed); + return; + } + + if (ft->file == NULL) { + snprintf(msg, sizeof(msg), "File transfer for '%s' failed: Null file pointer.", ft->file_name); + close_file_transfer(self, m, ft, TOX_FILE_CONTROL_CANCEL, msg, notif_error); + return; + } + + if (ft->position != position) { + if (fseek(ft->file, position, SEEK_SET) == -1) { + snprintf(msg, sizeof(msg), "File transfer for '%s' failed: Seek fail.", ft->file_name); + close_file_transfer(self, m, ft, TOX_FILE_CONTROL_CANCEL, msg, notif_error); + return; + } + + ft->position = position; + } + + uint8_t send_data[length]; + size_t send_length = fread(send_data, 1, sizeof(send_data), ft->file); + + if (send_length != length) { + snprintf(msg, sizeof(msg), "File transfer for '%s' failed: Read fail.", ft->file_name); + close_file_transfer(self, m, ft, TOX_FILE_CONTROL_CANCEL, msg, notif_error); + return; + } + + TOX_ERR_FILE_SEND_CHUNK err; + tox_file_send_chunk(m, friendnum, filenum, position, send_data, send_length, &err); + + if (err != TOX_ERR_FILE_SEND_CHUNK_OK) + fprintf(stderr, "tox_file_send_chunk failed (error %d)\n", err); + + ft->position += send_length; + ft->bps += send_length; +} + +static void chat_onFileRecvChunk(ToxWindow *self, Tox *m, uint32_t friendnum, uint32_t filenum, uint64_t position, + const char *data, size_t length) +{ + if (friendnum != self->num) + return; + + struct FileTransfer *ft = get_file_transfer_struct(friendnum, filenum); + + if (ft == NULL) + return; + + if (ft->state != FILE_TRANSFER_STARTED) + return; + + char msg[MAX_STR_SIZE]; + + if (length == 0) { + snprintf(msg, sizeof(msg), "File '%s' successfully received.", ft->file_name); + print_progress_bar(self, ft->bps, 100.0, ft->line_id); + close_file_transfer(self, m, ft, -1, msg, transfer_completed); + return; + } + + if (ft->file == NULL) { + snprintf(msg, sizeof(msg), "File transfer for '%s' failed: Invalid file pointer.", ft->file_name); + close_file_transfer(self, m, ft, TOX_FILE_CONTROL_CANCEL, msg, notif_error); + return; + } + + if (fwrite(data, length, 1, ft->file) != 1) { + snprintf(msg, sizeof(msg), "File transfer for '%s' failed: Write fail.", ft->file_name); + close_file_transfer(self, m, ft, TOX_FILE_CONTROL_CANCEL, msg, notif_error); + return; + } + + ft->bps += length; + ft->position += length; +} + +static void chat_onFileControl(ToxWindow *self, Tox *m, uint32_t friendnum, uint32_t filenum, TOX_FILE_CONTROL control) +{ + if (self->num != friendnum) + return; + + struct FileTransfer *ft = get_file_transfer_struct(friendnum, filenum); + + if (ft == NULL) + return; + + char msg[MAX_STR_SIZE]; + + switch (control) { + case TOX_FILE_CONTROL_RESUME: + /* transfer is accepted */ + if (ft->state == FILE_TRANSFER_PENDING) { + ft->state = FILE_TRANSFER_STARTED; + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "File transfer [%d] for '%s' accepted.", + ft->index, ft->file_name); + char progline[MAX_STR_SIZE]; + prep_prog_line(progline); + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s", progline); + sound_notify(self, silent, NT_NOFOCUS | NT_BEEP | NT_WNDALERT_2, NULL); + ft->line_id = self->chatwin->hst->line_end->id + 2; + + break; + } + + /* transfer is resumed */ + if (ft->state == FILE_TRANSFER_PAUSED) { + ft->state = FILE_TRANSFER_STARTED; + } + + break; + + case TOX_FILE_CONTROL_PAUSE: + break; + + case TOX_FILE_CONTROL_CANCEL: + snprintf(msg, sizeof(msg), "File transfer for '%s' was aborted.", ft->file_name); + close_file_transfer(self, m, ft, -1, msg, notif_error); + break; + } +} + +static void chat_onFileRecv(ToxWindow *self, Tox *m, uint32_t friendnum, uint32_t filenum, uint64_t file_size, + const char *filename, size_t name_length) +{ + if (self->num != friendnum) + return; + + struct FileTransfer *ft = get_new_file_receiver(friendnum); + + if (!ft) { + tox_file_control(m, friendnum, filenum, TOX_FILE_CONTROL_CANCEL, NULL); + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "File transfer failed: Too many concurrent file transfers."); + return; + } - /* holds the lone filename */ - char filename_nopath[MAX_STR_SIZE]; - get_file_name(filename_nopath, sizeof(filename_nopath), pathname); char sizestr[32]; - bytes_convert_str(sizestr, sizeof(sizestr), filesize); - int len = strlen(filename_nopath); - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "File transfer request for '%s' (%s)", - filename_nopath, sizestr); + bytes_convert_str(sizestr, sizeof(sizestr), file_size); + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "File transfer request for '%s' (%s)", filename, sizestr); - if (filenum >= MAX_FILES) { - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Too many pending file requests; discarding."); + char file_path[MAX_STR_SIZE]; + size_t path_len = name_length; + + /* use specified download path in config if possible */ + if (!string_is_empty(user_settings->download_path)) { + snprintf(file_path, sizeof(file_path), "%s%s", user_settings->download_path, filename); + path_len += strlen(user_settings->download_path); + } else { + snprintf(file_path, sizeof(file_path), "%s", filename); + } + + if (path_len >= sizeof(ft->file_path) || name_length >= sizeof(ft->file_name)) { + tox_file_control(m, friendnum, filenum, TOX_FILE_CONTROL_CANCEL, NULL); + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "File transfer faield: File path too long."); return; } - /* use specified path in config if possible */ - if (user_settings->download_path[0]) { - snprintf(filename_path, sizeof(filename_path), "%s%s", user_settings->download_path, filename_nopath); - len += strlen(user_settings->download_path); - } - - if (len >= sizeof(Friends.list[num].file_receiver[filenum].filename)) { - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "File name too long; discarding."); - return; - } - - char filename[MAX_STR_SIZE]; - - if (filename_path[0]) - strcpy(filename, filename_path); - else - strcpy(filename, filename_nopath); - /* Append a number to duplicate file names */ FILE *filecheck = NULL; int count = 1; - while ((filecheck = fopen(filename, "r"))) { + while ((filecheck = fopen(file_path, "r"))) { fclose(filecheck); - filename[len] = '\0'; + file_path[path_len] = '\0'; char d[9]; - sprintf(d, "(%d)", count++); - int d_len = strlen(d); + sprintf(d, "(%d)", count); + ++count; + size_t d_len = strlen(d); - if (len + d_len >= sizeof(filename)) { - len -= d_len; - filename[len] = '\0'; + if (path_len + d_len >= sizeof(file_path)) { + path_len -= d_len; + file_path[path_len] = '\0'; } - strcat(filename, d); - filename[len + d_len] = '\0'; + strcat(file_path, d); + file_path[path_len + d_len] = '\0'; if (count > 999) { - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Error saving file to disk."); + tox_file_control(m, friendnum, filenum, TOX_FILE_CONTROL_CANCEL, NULL); + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "File transfer failed: invalid file path."); return; } } - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Type '/savefile %d' to accept the file transfer.", filenum); + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Type '/savefile %d' to accept the file transfer.", ft->index); - Friends.list[num].file_receiver[filenum].pending = true; - Friends.list[num].file_receiver[filenum].size = filesize; - Friends.list[num].file_receiver[filenum].filenum = filenum; - strcpy(Friends.list[num].file_receiver[filenum].filename, filename); + ft->state = FILE_TRANSFER_PENDING; + ft->direction = FILE_TRANSFER_RECV; + ft->file_size = file_size; + ft->friendnum = friendnum; + ft->filenum = filenum; + snprintf(ft->file_path, sizeof(ft->file_path), "%s", file_path); + snprintf(ft->file_name, sizeof(ft->file_name), "%s", filename); if (self->active_box != -1) box_notify2(self, transfer_pending, NT_WNDALERT_0 | NT_NOFOCUS, self->active_box, @@ -360,208 +512,6 @@ static void chat_onFileSendRequest(ToxWindow *self, Tox *m, int32_t num, uint8_t "Incoming file: %s", filename ); } -/* Stops active file senders for this friend. Call when a friend goes offline */ -static void chat_stop_file_senders(int fnum) -{ - int i; - - for (i = 0; i < MAX_FILES; ++i) { - if (file_senders[i].active && file_senders[i].friendnum == fnum) - file_senders[i].noconnection = true; - } -} - -/* Tries to resume broken file transfers. Call when a friend comes online */ -static void chat_resume_file_transfers(Tox *m, int fnum) -{ - if (Friends.list[fnum].active_file_receivers == 0) - return; - - int i; - - for (i = 0; i < MAX_FILES; ++i) { - if (Friends.list[fnum].file_receiver[i].active) { - uint8_t bytes_recv[sizeof(uint64_t)]; - memcpy(bytes_recv, &Friends.list[fnum].file_receiver[i].bytes_recv, sizeof(uint64_t)); - net_to_host(bytes_recv, sizeof(uint64_t)); - int filenum = Friends.list[fnum].file_receiver[i].filenum; - tox_file_send_control(m, fnum, 1, filenum, TOX_FILECONTROL_RESUME_BROKEN, bytes_recv, sizeof(uint64_t)); - } - } -} - -/* set CTRL to -1 if we don't want to send a control signal. - set msg to NULL if we don't want to display a message */ -void chat_close_file_receiver(Tox *m, int filenum, int friendnum, int CTRL) -{ - if (CTRL > 0) - tox_file_send_control(m, friendnum, 1, filenum, CTRL, 0, 0); - - FILE *file = Friends.list[friendnum].file_receiver[filenum].file; - - if (file != NULL) - fclose(file); - - memset(&Friends.list[friendnum].file_receiver[filenum], 0, sizeof(struct FileReceiver)); - --Friends.list[friendnum].active_file_receivers; -} - -static void close_all_file_receivers(Tox *m, int friendnum) -{ - int i; - - for (i = 0; i < MAX_FILES; ++i) { - if (Friends.list[friendnum].file_receiver[i].active) - chat_close_file_receiver(m, i, friendnum, TOX_FILECONTROL_KILL); - } -} - -static void chat_onFileControl(ToxWindow *self, Tox *m, int32_t num, uint8_t receive_send, - uint8_t filenum, uint8_t control_type, const char *data, uint16_t length) -{ - if (self->num != num) - return; - - const char *filename; - char msg[MAX_STR_SIZE] = {0}; - int send_idx = 0; /* file sender index */ - - if (receive_send == 0) { - if (!Friends.list[num].file_receiver[filenum].active) - return; - - filename = Friends.list[num].file_receiver[filenum].filename; - } else { - int i; - - for (i = 0; i < MAX_FILES; ++i) { - send_idx = i; - - if (file_senders[i].active && file_senders[i].filenum == filenum) - break; - } - - if (!file_senders[send_idx].active) - return; - - filename = file_senders[send_idx].filename; - } - - switch (control_type) { - case TOX_FILECONTROL_ACCEPT: - if (receive_send != 1) - break; - - /* transfer is accepted */ - if (!file_senders[send_idx].started) { - file_senders[send_idx].started = true; - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "File transfer [%d] for '%s' accepted.", - filenum, filename); - char progline[MAX_STR_SIZE]; - prep_prog_line(progline); - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s", progline); - file_senders[send_idx].line_id = self->chatwin->hst->line_end->id + 2; - sound_notify(self, silent, NT_NOFOCUS | NT_BEEP | NT_WNDALERT_2, NULL); - } else { /* active transfer is unpaused by receiver */ - file_senders[send_idx].paused = false; - file_senders[send_idx].timestamp = get_unix_time(); - } - - break; - - case TOX_FILECONTROL_PAUSE: - if (receive_send == 1) - file_senders[send_idx].paused = true; - - break; - - case TOX_FILECONTROL_KILL: - snprintf(msg, sizeof(msg), "File transfer for '%s' failed.", filename); - - if (self->active_box != -1) - box_notify2(self, error, NT_NOFOCUS | NT_WNDALERT_2, - self->active_box, "File transfer for '%s' failed!", filename ); - else - box_notify(self, error, NT_NOFOCUS | NT_WNDALERT_2, &self->active_box, - self->name, "File transfer for '%s' failed!", filename ); - - if (receive_send == 0) - chat_close_file_receiver(m, filenum, num, -1); - else - close_file_sender(self, m, send_idx, NULL, -1, filenum, num); - - break; - - case TOX_FILECONTROL_FINISHED: - if (receive_send == 0) { - print_progress_bar(self, filenum, num, 100.0); - - char filename_nopath[MAX_STR_SIZE]; - get_file_name(filename_nopath, sizeof(filename_nopath), filename); - snprintf(msg, sizeof(msg), "File transfer for '%s' complete.", filename_nopath); - chat_close_file_receiver(m, filenum, num, TOX_FILECONTROL_FINISHED); - } else { - snprintf(msg, sizeof(msg), "File '%s' successfuly sent.", filename); - close_file_sender(self, m, send_idx, NULL, TOX_FILECONTROL_FINISHED, filenum, num); - } - - if (self->active_box != -1) - box_notify2(self, transfer_completed, NT_NOFOCUS | NT_WNDALERT_2, self->active_box, "%s", msg); - else - box_notify(self, transfer_completed, NT_NOFOCUS | NT_WNDALERT_2, &self->active_box, - self->name, "%s", msg); - - break; - - case TOX_FILECONTROL_RESUME_BROKEN: - if (receive_send == 0) - break; - - FILE *fp = file_senders[send_idx].file; - - if (fp == NULL) - break; - - uint8_t tmp[sizeof(uint64_t)]; - memcpy(tmp, &data, sizeof(uint64_t)); - net_to_host(tmp, sizeof(uint64_t)); - uint64_t datapos; - memcpy(&datapos, tmp, sizeof(uint64_t)); - - if (fseek(fp, datapos, SEEK_SET) == -1) { - snprintf(msg, sizeof(msg), "File transfer for '%s' failed to resume", filename); - close_file_sender(self, m, send_idx, NULL, TOX_FILECONTROL_FINISHED, filenum, num); - break; - } - - tox_file_send_control(m, num, 0, filenum, TOX_FILECONTROL_ACCEPT, 0, 0); - file_senders[send_idx].noconnection = false; - break; - } - - if (msg[0]) - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s", msg); -} - -static void chat_onFileData(ToxWindow *self, Tox *m, int32_t num, uint8_t filenum, const char *data, - uint16_t length) -{ - if (self->num != num) - return; - - FILE *fp = Friends.list[num].file_receiver[filenum].file; - - if (fp) { - if (fwrite(data, length, 1, fp) != 1) { - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, RED, " * Error writing to file."); - chat_close_file_receiver(m, filenum, num, TOX_FILECONTROL_KILL); - } - } - - Friends.list[num].file_receiver[filenum].bps += length; - Friends.list[num].file_receiver[filenum].bytes_recv += length; -} - static void chat_onGroupInvite(ToxWindow *self, Tox *m, int32_t friendnumber, const char *invite_data, uint16_t length) { @@ -838,7 +788,9 @@ static void send_action(ToxWindow *self, ChatContext *ctx, Tox *m, char *action) return; char selfname[TOX_MAX_NAME_LENGTH]; - uint16_t len = tox_get_self_name(m, (uint8_t *) selfname); + tox_self_get_name(m, (uint8_t *) selfname); + + size_t len = tox_self_get_name_size(m); selfname[len] = '\0'; char timefrmt[TIME_STR_SIZE]; @@ -869,7 +821,7 @@ static void chat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr) if (ltr) { /* char is printable */ input_new_char(self, key, x, y, x2, y2); - if (ctx->line[0] != '/' && !ctx->self_is_typing && statusbar->is_online) + if (ctx->line[0] != '/' && !ctx->self_is_typing && statusbar->connection != TOX_CONNECTION_NONE) set_self_typingstatus(self, m, 1); return; @@ -905,7 +857,7 @@ static void chat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr) ctx->start = wlen < x2 ? 0 : wlen - x2 + 1; } } else { - sound_notify(self, error, 0, NULL); + sound_notify(self, notif_error, 0, NULL); } } else if (key == '\n') { @@ -930,7 +882,9 @@ static void chat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr) } } else if (!string_is_empty(line)) { char selfname[TOX_MAX_NAME_LENGTH]; - uint16_t len = tox_get_self_name(m, (uint8_t *) selfname); + tox_self_get_name(m, (uint8_t *) selfname); + + size_t len = tox_self_get_name_size(m); selfname[len] = '\0'; char timefrmt[TIME_STR_SIZE]; @@ -970,26 +924,20 @@ static void chat_onDraw(ToxWindow *self, Tox *m) wmove(statusbar->topline, 0, 0); /* Draw name, status and note in statusbar */ - if (statusbar->is_online) { - int colour = WHITE; - uint8_t status = statusbar->status; + if (statusbar->connection != TOX_CONNECTION_NONE) { + int colour = MAGENTA; + TOX_USER_STATUS status = statusbar->status; switch (status) { - case TOX_USERSTATUS_NONE: + case TOX_USER_STATUS_NONE: colour = GREEN; break; - - case TOX_USERSTATUS_AWAY: + case TOX_USER_STATUS_AWAY: colour = YELLOW; break; - - case TOX_USERSTATUS_BUSY: + case TOX_USER_STATUS_BUSY: colour = RED; break; - - case TOX_USERSTATUS_INVALID: - colour = MAGENTA; - break; } wattron(statusbar->topline, COLOR_PAIR(colour) | A_BOLD); @@ -1014,10 +962,11 @@ static void chat_onDraw(ToxWindow *self, Tox *m) /* Reset statusbar->statusmsg on window resize */ if (x2 != self->x) { - char statusmsg[TOX_MAX_STATUSMESSAGE_LENGTH] = {'\0'}; + char statusmsg[TOX_MAX_STATUS_MESSAGE_LENGTH] = {'\0'}; pthread_mutex_lock(&Winthread.lock); - int s_len = tox_get_status_message(m, self->num, (uint8_t *) statusmsg, TOX_MAX_STATUSMESSAGE_LENGTH); + tox_friend_get_status_message(m, self->num, (uint8_t *) statusmsg, NULL); + size_t s_len = tox_friend_get_status_message_size(m, self->num, NULL); pthread_mutex_unlock(&Winthread.lock); filter_str(statusmsg, s_len); @@ -1028,7 +977,7 @@ static void chat_onDraw(ToxWindow *self, Tox *m) self->x = x2; /* Truncate note if it doesn't fit in statusbar */ - uint16_t maxlen = x2 - getcurx(statusbar->topline) - (KEY_IDENT_DIGITS * 2) - 6; + size_t maxlen = x2 - getcurx(statusbar->topline) - (KEY_IDENT_DIGITS * 2) - 6; if (statusbar->statusmsg_len > maxlen) { statusbar->statusmsg[maxlen - 3] = '\0'; @@ -1043,7 +992,7 @@ static void chat_onDraw(ToxWindow *self, Tox *m) wmove(statusbar->topline, 0, x2 - (KEY_IDENT_DIGITS * 2) - 3); wprintw(statusbar->topline, "{"); - int i; + size_t i; for (i = 0; i < KEY_IDENT_DIGITS; ++i) wprintw(statusbar->topline, "%02X", Friends.list[self->num].pub_key[i] & 0xff); @@ -1069,6 +1018,10 @@ static void chat_onDraw(ToxWindow *self, Tox *m) if (self->help->active) help_onDraw(self); + + pthread_mutex_lock(&Winthread.lock); + refresh_file_transfer_progress(self, m, self->num); + pthread_mutex_unlock(&Winthread.lock); } static void chat_onInit(ToxWindow *self, Tox *m) @@ -1081,11 +1034,13 @@ static void chat_onInit(ToxWindow *self, Tox *m) /* Init statusbar info */ StatusBar *statusbar = self->stb; - statusbar->status = tox_get_user_status(m, self->num); - statusbar->is_online = tox_get_friend_connection_status(m, self->num) == 1; + statusbar->status = tox_friend_get_status(m, self->num, NULL); + statusbar->connection = tox_friend_get_connection_status(m, self->num, NULL); - char statusmsg[TOX_MAX_STATUSMESSAGE_LENGTH] = {'\0'}; - uint16_t s_len = tox_get_status_message(m, self->num, (uint8_t *) statusmsg, TOX_MAX_STATUSMESSAGE_LENGTH); + char statusmsg[TOX_MAX_STATUS_MESSAGE_LENGTH]; + tox_friend_get_status_message(m, self->num, (uint8_t *) statusmsg, NULL); + + size_t s_len = tox_friend_get_status_message_size(m, self->num, NULL); statusmsg[s_len] = '\0'; filter_str(statusmsg, s_len); @@ -1093,7 +1048,7 @@ static void chat_onInit(ToxWindow *self, Tox *m) statusbar->statusmsg_len = strlen(statusbar->statusmsg); char nick[TOX_MAX_NAME_LENGTH + 1]; - int n_len = get_nick_truncate(m, nick, self->num); + size_t n_len = get_nick_truncate(m, nick, self->num); snprintf(statusbar->nick, sizeof(statusbar->nick), "%s", nick); statusbar->nick_len = n_len; @@ -1113,8 +1068,8 @@ static void chat_onInit(ToxWindow *self, Tox *m) line_info_init(ctx->hst); - char myid[TOX_FRIEND_ADDRESS_SIZE]; - tox_get_address(m, (uint8_t *) myid); + char myid[TOX_ADDRESS_SIZE]; + tox_self_get_address(m, (uint8_t *) myid); log_enable(nick, myid, Friends.list[self->num].pub_key, ctx->log, LOG_CHAT); load_chat_history(self, ctx->log); @@ -1128,7 +1083,7 @@ static void chat_onInit(ToxWindow *self, Tox *m) wmove(self->window, y2 - CURS_Y_OFFSET, 0); } -ToxWindow new_chat(Tox *m, int32_t friendnum) +ToxWindow new_chat(Tox *m, uint32_t friendnum) { ToxWindow ret; memset(&ret, 0, sizeof(ret)); @@ -1145,10 +1100,10 @@ ToxWindow new_chat(Tox *m, int32_t friendnum) ret.onNickChange = &chat_onNickChange; ret.onStatusChange = &chat_onStatusChange; ret.onStatusMessageChange = &chat_onStatusMessageChange; - ret.onAction = &chat_onAction; - ret.onFileSendRequest = &chat_onFileSendRequest; + ret.onFileChunkRequest = &chat_onFileChunkRequest; + ret.onFileRecvChunk = &chat_onFileRecvChunk; ret.onFileControl = &chat_onFileControl; - ret.onFileData = &chat_onFileData; + ret.onFileRecv = &chat_onFileRecv; ret.onReadReceipt = &chat_onReadReceipt; ret.onGroupInvite = &chat_onGroupInvite; @@ -1173,7 +1128,7 @@ ToxWindow new_chat(Tox *m, int32_t friendnum) ret.active_box = -1; char nick[TOX_MAX_NAME_LENGTH]; - int n_len = get_nick_truncate(m, nick, friendnum); + size_t n_len = get_nick_truncate(m, nick, friendnum); set_window_title(&ret, nick, n_len); ChatContext *chatwin = calloc(1, sizeof(ChatContext)); diff --git a/src/chat_commands.c b/src/chat_commands.c index 9ca5109..54dadf8 100644 --- a/src/chat_commands.c +++ b/src/chat_commands.c @@ -31,15 +31,11 @@ #include "line_info.h" #include "groupchat.h" #include "chat.h" -#include "file_senders.h" +#include "file_transfers.h" extern ToxWindow *prompt; extern FriendsList Friends; -extern FileSender file_senders[MAX_FILES]; -extern uint8_t max_file_senders_index; -extern uint8_t num_active_file_senders; - void cmd_cancelfile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) { if (argc < 2) { @@ -47,52 +43,39 @@ void cmd_cancelfile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*ar return; } + char msg[MAX_STR_SIZE]; const char *inoutstr = argv[1]; - int filenum = atoi(argv[2]); + int idx = atoi(argv[2]); - if (filenum >= MAX_FILES || filenum < 0) { + if (idx >= MAX_FILES || idx < 0) { line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid file ID."); return; } - if (strcasecmp(inoutstr, "in") == 0) { /* cancel an incoming file transfer */ - if (!Friends.list[self->num].file_receiver[filenum].active) { - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid file ID."); - return; - } + struct FileTransfer *ft = NULL; - const char *filepath = Friends.list[self->num].file_receiver[filenum].filename; - char name[MAX_STR_SIZE]; - get_file_name(name, sizeof(name), filepath); - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "File transfer for '%s' canceled.", name); - chat_close_file_receiver(m, filenum, self->num, TOX_FILECONTROL_KILL); - - return; - } else if (strcasecmp(inoutstr, "out") == 0) { /* cancel an outgoing file transfer */ - int i; - bool match = false; - - for (i = 0; i < MAX_FILES; ++i) { - if (file_senders[i].active && file_senders[i].filenum == filenum) { - match = true; - break; - } - } - - if (!match) { - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid file ID."); - return; - } - - const char *filename = file_senders[i].filename; - char msg[MAX_STR_SIZE]; - snprintf(msg, sizeof(msg), "File transfer for '%s' canceled.", filename); - close_file_sender(self, m, i, msg, TOX_FILECONTROL_KILL, filenum, self->num); - return; + /* cancel an incoming file transfer */ + if (strcasecmp(inoutstr, "in") == 0) { + ft = get_file_transfer_struct_index(self->num, idx, FILE_TRANSFER_RECV); + } else if (strcasecmp(inoutstr, "out") == 0) { + ft = get_file_transfer_struct_index(self->num, idx, FILE_TRANSFER_SEND); } else { line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Type must be 'in' or 'out'."); return; } + + if (!ft) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid file ID."); + return; + } + + if (ft->state == FILE_TRANSFER_INACTIVE) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid file ID."); + return; + } + + snprintf(msg, sizeof(msg), "File transfer for '%s' aborted.", ft->file_name); + close_file_transfer(self, m, ft, TOX_FILE_CONTROL_CANCEL, msg, silent); } void cmd_groupinvite(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) @@ -124,50 +107,76 @@ void cmd_savefile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv return; } - uint8_t filenum = atoi(argv[1]); + int idx = atoi(argv[1]); - if ((filenum == 0 && strcmp(argv[1], "0")) || filenum >= MAX_FILES) { + if ((idx == 0 && strcmp(argv[1], "0")) || idx >= MAX_FILES) { line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "No pending file transfers with that ID."); return; } - if (!Friends.list[self->num].file_receiver[filenum].pending) { + struct FileTransfer *ft = get_file_transfer_struct_index(self->num, idx, FILE_TRANSFER_RECV); + + if (!ft) { line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "No pending file transfers with that ID."); return; } - const char *filename = Friends.list[self->num].file_receiver[filenum].filename; - - if (tox_file_send_control(m, self->num, 1, filenum, TOX_FILECONTROL_ACCEPT, 0, 0) == 0) { - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Saving file [%d] as: '%s'", filenum, filename); - - /* prep progress bar line */ - char progline[MAX_STR_SIZE]; - prep_prog_line(progline); - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s", progline); - Friends.list[self->num].file_receiver[filenum].line_id = self->chatwin->hst->line_end->id + 2; - - if ((Friends.list[self->num].file_receiver[filenum].file = fopen(filename, "a")) == NULL) { - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, RED, "* Error writing to file."); - tox_file_send_control(m, self->num, 1, filenum, TOX_FILECONTROL_KILL, 0, 0); - } else { - Friends.list[self->num].file_receiver[filenum].active = true; - ++Friends.list[self->num].active_file_receivers; - } - } else { - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "File transfer failed."); + if (ft->state != FILE_TRANSFER_PENDING) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "No pending file transfers with that ID."); + return; } - Friends.list[self->num].file_receiver[filenum].pending = false; + if ((ft->file = fopen(ft->file_path, "a")) == NULL) { + const char *msg = "File transfer failed: Invalid file path."; + close_file_transfer(self, m, ft, TOX_FILE_CONTROL_CANCEL, msg, notif_error); + return; + } + + TOX_ERR_FILE_CONTROL err; + tox_file_control(m, self->num, ft->filenum, TOX_FILE_CONTROL_RESUME, &err); + + if (err != TOX_ERR_FILE_CONTROL_OK) + goto on_recv_error; + + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Saving file [%d] as: '%s'", idx, ft->file_path); + + /* prep progress bar line */ + char progline[MAX_STR_SIZE]; + prep_prog_line(progline); + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s", progline); + + ft->line_id = self->chatwin->hst->line_end->id + 2; + ft->state = FILE_TRANSFER_STARTED; + + return; + +on_recv_error: + switch (err) { + case TOX_ERR_FILE_CONTROL_FRIEND_NOT_FOUND: + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "File transfer failed: Friend not found."); + return; + + case TOX_ERR_FILE_CONTROL_FRIEND_NOT_CONNECTED: + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "File transfer failed: Friend is not online."); + return; + + case TOX_ERR_FILE_CONTROL_NOT_FOUND: + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "File transfer failed: Invalid filenumber."); + return; + + case TOX_ERR_FILE_CONTROL_SENDQ: + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "File transfer failed: Connection error."); + return; + + default: + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "File transfer failed (error %d)\n", err); + return; + } } void cmd_sendfile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) { - if (max_file_senders_index >= (MAX_FILES - 1)) { - const char *errmsg = "Please wait for some of your outgoing file transfers to complete."; - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, errmsg); - return; - } + const char *errmsg = NULL; if (argc < 1) { line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "File path required."); @@ -199,51 +208,67 @@ void cmd_sendfile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv off_t filesize = file_size(path); - if (filesize == -1) { - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "File corrupt."); + if (filesize == 0) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid file."); fclose(file_to_send); return; } - char filename[MAX_STR_SIZE] = {0}; - get_file_name(filename, sizeof(filename), path); - int namelen = strlen(filename); - int filenum = tox_new_file_sender(m, self->num, filesize, (const uint8_t *) filename, namelen); + char file_name[TOX_MAX_FILENAME_LENGTH]; + size_t namelen = get_file_name(file_name, sizeof(file_name), path); - if (filenum == -1) { - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Error sending file."); - fclose(file_to_send); - return; + TOX_ERR_FILE_SEND err; + uint32_t filenum = tox_file_send(m, self->num, TOX_FILE_KIND_DATA, (uint64_t) filesize, NULL, + (uint8_t *) file_name, namelen, &err); + + if (err != TOX_ERR_FILE_SEND_OK) + goto on_send_error; + + struct FileTransfer *ft = get_new_file_sender(self->num); + + if (!ft) { + err = TOX_ERR_FILE_SEND_TOO_MANY; + goto on_send_error; } - int i; + memcpy(ft->file_name, file_name, namelen + 1); + ft->state = FILE_TRANSFER_PENDING; + ft->file = file_to_send; + ft->file_size = filesize; + ft->filenum = filenum; + ft->friendnum = self->num; + ft->direction = FILE_TRANSFER_SEND; - for (i = 0; i < MAX_FILES; ++i) { - if (!file_senders[i].active) { - memcpy(file_senders[i].filename, filename, namelen + 1); - file_senders[i].active = true; - file_senders[i].started = false; - file_senders[i].toxwin = self; - file_senders[i].file = file_to_send; - file_senders[i].filenum = filenum; - file_senders[i].friendnum = self->num; - file_senders[i].timestamp = get_unix_time(); - file_senders[i].size = filesize; - file_senders[i].piecelen = fread(file_senders[i].nextpiece, 1, - tox_file_data_size(m, self->num), file_to_send); + char sizestr[32]; + bytes_convert_str(sizestr, sizeof(sizestr), filesize); + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Sending file [%d]: '%s' (%s)", filenum, file_name, sizestr); - char sizestr[32]; - bytes_convert_str(sizestr, sizeof(sizestr), filesize); - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, - "Sending file [%d]: '%s' (%s)", filenum, filename, sizestr); + return; - ++num_active_file_senders; +on_send_error: + switch (err) { + case TOX_ERR_FILE_SEND_FRIEND_NOT_FOUND: + errmsg = "File transfer failed: Invalid friend."; + break; - if (i == max_file_senders_index) - ++max_file_senders_index; + case TOX_ERR_FILE_SEND_FRIEND_NOT_CONNECTED: + errmsg = "File transfer failed: Friend is offline."; + break; - reset_file_sender_queue(); - return; - } + case TOX_ERR_FILE_SEND_NAME_TOO_LONG: + errmsg = "File transfer failed: Filename is too long."; + break; + + case TOX_ERR_FILE_SEND_TOO_MANY: + errmsg = "File transfer failed: Too many concurrent file transfers."; + break; + + default: + errmsg = "File transfer failed."; + break; } + + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s", errmsg); + tox_file_control(m, self->num, filenum, TOX_FILE_CONTROL_CANCEL, NULL); + fclose(file_to_send); } diff --git a/src/dns.c b/src/dns.c index aafb911..ade723c 100644 --- a/src/dns.c +++ b/src/dns.c @@ -75,7 +75,7 @@ static struct dns3_server_backup { static struct thread_data { ToxWindow *self; - char id_bin[TOX_FRIEND_ADDRESS_SIZE]; + char id_bin[TOX_ADDRESS_SIZE]; char addr[MAX_STR_SIZE]; char msg[MAX_STR_SIZE]; uint8_t busy; @@ -168,39 +168,39 @@ static int parse_dns_response(ToxWindow *self, u_char *answer, int ans_len, char uint8_t *ans_pt = answer + sizeof(HEADER); uint8_t *ans_end = answer + ans_len; char exp_ans[PACKETSZ]; - + int len = dn_expand(answer, ans_end, ans_pt, exp_ans, sizeof(exp_ans)); if (len == -1) - return dns_error(self, "dn_expand failed."); + return dns_error(self, "dn_expand failed."); ans_pt += len; if (ans_pt > ans_end - 4) - return dns_error(self, "DNS reply was too short."); + return dns_error(self, "DNS reply was too short."); int type; GETSHORT(type, ans_pt); if (type != T_TXT) - return dns_error(self, "Broken DNS reply."); - + return dns_error(self, "Broken DNS reply."); + ans_pt += INT16SZ; /* class */ uint32_t size = 0; /* recurse through CNAME rr's */ - do { + do { ans_pt += size; len = dn_expand(answer, ans_end, ans_pt, exp_ans, sizeof(exp_ans)); if (len == -1) - return dns_error(self, "Second dn_expand failed."); + return dns_error(self, "Second dn_expand failed."); ans_pt += len; if (ans_pt > ans_end - 10) - return dns_error(self, "DNS reply was too short."); + return dns_error(self, "DNS reply was too short."); GETSHORT(type, ans_pt); ans_pt += INT16SZ; @@ -208,12 +208,12 @@ static int parse_dns_response(ToxWindow *self, u_char *answer, int ans_len, char GETSHORT(size, ans_pt); if (ans_pt + size < answer || ans_pt + size > ans_end) - return dns_error(self, "RR overflow."); + return dns_error(self, "RR overflow."); } while (type == T_CNAME); if (type != T_TXT) - return dns_error(self, "DNS response failed."); + return dns_error(self, "DNS response failed."); uint32_t txt_len = *ans_pt; @@ -230,7 +230,7 @@ static int parse_dns_response(ToxWindow *self, u_char *answer, int ans_len, char return txt_len; } -/* Takes address addr in the form "username@domain", puts the username in namebuf, +/* Takes address addr in the form "username@domain", puts the username in namebuf, and the domain in dombuf. return length of username on success, -1 on failure */ @@ -322,7 +322,7 @@ void *dns3_lookup_thread(void *data) char string[MAX_DNS_REQST_SIZE + 1]; uint32_t request_id; - int str_len = tox_generate_dns3_string(dns_obj, (uint8_t *) string, sizeof(string), &request_id, + int str_len = tox_generate_dns3_string(dns_obj, (uint8_t *) string, sizeof(string), &request_id, (uint8_t *) name, namelen); if (str_len == -1) { @@ -361,7 +361,7 @@ void *dns3_lookup_thread(void *data) memcpy(encrypted_id, ans_id + prfx_len, ans_len - prfx_len); - if (tox_decrypt_dns3_TXT(dns_obj, (uint8_t *) t_data.id_bin, (uint8_t *) encrypted_id, + if (tox_decrypt_dns3_TXT(dns_obj, (uint8_t *) t_data.id_bin, (uint8_t *) encrypted_id, strlen(encrypted_id), request_id) == -1) { dns_error(self, "Core failed to decrypt DNS response."); killdns_thread(dns_obj); @@ -378,7 +378,7 @@ void *dns3_lookup_thread(void *data) /* creates new thread for dns3 lookup. Only allows one lookup at a time. */ void dns3_lookup(ToxWindow *self, Tox *m, const char *id_bin, const char *addr, const char *msg) { - if (arg_opts.proxy_type != TOX_PROXY_NONE && arg_opts.force_tcp) { + if (arg_opts.proxy_type != TOX_PROXY_TYPE_NONE && arg_opts.force_tcp) { line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "DNS lookups are disabled."); return; } diff --git a/src/file_senders.c b/src/file_senders.c deleted file mode 100644 index 267d92c..0000000 --- a/src/file_senders.c +++ /dev/null @@ -1,293 +0,0 @@ -/* file_senders.c - * - * - * Copyright (C) 2014 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 - -#include "toxic.h" -#include "windows.h" -#include "friendlist.h" -#include "file_senders.h" -#include "line_info.h" -#include "misc_tools.h" -#include "notify.h" - -FileSender file_senders[MAX_FILES]; -uint8_t max_file_senders_index; -uint8_t num_active_file_senders; -extern FriendsList Friends; - -#define NUM_PROG_MARKS 50 /* number of "#"'s in file transfer progress bar. Keep well below MAX_STR_SIZE */ - -/* creates initial progress line that will be updated during file transfer. - Assumes progline is of size MAX_STR_SIZE */ -void prep_prog_line(char *progline) -{ - strcpy(progline, "0.0 B/s ["); - int i; - - for (i = 0; i < NUM_PROG_MARKS; ++i) - strcat(progline, "-"); - - strcat(progline, "] 0%"); -} - -/* prints a progress bar for file transfers. - if friendnum is -1 we're sending the file, otherwise we're receiving. */ -void print_progress_bar(ToxWindow *self, int idx, int friendnum, double pct_done) -{ - double bps; - uint32_t line_id; - - if (friendnum < 0) { - bps = file_senders[idx].bps; - line_id = file_senders[idx].line_id; - } else { - bps = Friends.list[friendnum].file_receiver[idx].bps; - line_id = Friends.list[friendnum].file_receiver[idx].line_id; - } - - char msg[MAX_STR_SIZE]; - bytes_convert_str(msg, sizeof(msg), bps); - strcat(msg, "/s ["); - - int n = pct_done / (100 / NUM_PROG_MARKS); - int i, j; - - for (i = 0; i < n; ++i) - strcat(msg, "#"); - - for (j = i; j < NUM_PROG_MARKS; ++j) - strcat(msg, "-"); - - strcat(msg, "] "); - - char pctstr[16]; - const char *frmt = pct_done == 100 ? "%.f%%" : "%.1f%%"; - snprintf(pctstr, sizeof(pctstr), frmt, pct_done); - strcat(msg, pctstr); - - line_info_set(self, line_id, msg); -} - -/* refreshes active file receiver status bars */ -static void refresh_recv_prog(Tox *m) -{ - int i; - uint64_t curtime = get_unix_time(); - - for (i = 2; i < MAX_WINDOWS_NUM; ++i) { - ToxWindow *toxwin = get_window_ptr(i); - - if (toxwin == NULL || !toxwin->is_chat) - continue; - - int fnum = toxwin->num; - int j; - - for (j = 0; j < MAX_FILES; ++j) { - if (!Friends.list[fnum].file_receiver[j].active) - continue; - - int filenum = Friends.list[fnum].file_receiver[j].filenum; - double remain = (double) tox_file_data_remaining(m, fnum, filenum, 1); - - /* must be called once per second */ - if (timed_out(Friends.list[fnum].file_receiver[filenum].last_progress, curtime, 1)) { - Friends.list[fnum].file_receiver[filenum].last_progress = curtime; - uint64_t size = Friends.list[fnum].file_receiver[filenum].size; - double pct_done = remain > 0 ? (1 - (remain / size)) * 100 : 100; - print_progress_bar(toxwin, filenum, fnum, pct_done); - Friends.list[fnum].file_receiver[filenum].bps = 0; - } - } - } -} - -/* refreshes active file sender status bars */ -static void refresh_sender_prog(Tox *m) -{ - int i; - uint64_t curtime = get_unix_time(); - - for (i = 0; i < max_file_senders_index; ++i) { - if (!file_senders[i].active || file_senders[i].finished) - continue; - - int filenum = file_senders[i].filenum; - int32_t friendnum = file_senders[i].friendnum; - double remain = (double) tox_file_data_remaining(m, friendnum, filenum, 0); - - /* must be called once per second */ - if (timed_out(file_senders[i].last_progress, curtime, 1)) { - file_senders[i].last_progress = curtime; - double pct_done = remain > 0 ? (1 - (remain / file_senders[i].size)) * 100 : 100; - print_progress_bar(file_senders[i].toxwin, i, -1, pct_done); - file_senders[i].bps = 0; - } - } -} - -static void set_max_file_senders_index(void) -{ - int j; - - for (j = max_file_senders_index; j > 0; --j) { - if (file_senders[j - 1].active) - break; - } - - max_file_senders_index = j; -} - -/* called whenever a file sender is opened or closed */ -void reset_file_sender_queue(void) -{ - int i; - int pos = 0; - - for (i = 0; i < max_file_senders_index; ++i) { - if (file_senders[i].active) - file_senders[i].queue_pos = pos++; - } -} - -/* set CTRL to -1 if we don't want to send a control signal. - set msg to NULL if we don't want to display a message */ -void close_file_sender(ToxWindow *self, Tox *m, int i, const char *msg, int CTRL, int filenum, int32_t friendnum) -{ - if (msg != NULL) - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s", msg); - - if (CTRL > 0) - tox_file_send_control(m, friendnum, 0, filenum, CTRL, 0, 0); - - fclose(file_senders[i].file); - memset(&file_senders[i], 0, sizeof(FileSender)); - set_max_file_senders_index(); - reset_file_sender_queue(); - --num_active_file_senders; -} - -void close_all_file_senders(Tox *m) -{ - int i; - - for (i = 0; i < max_file_senders_index; ++i) { - if (file_senders[i].active) { - fclose(file_senders[i].file); - tox_file_send_control(m, file_senders[i].friendnum, 0, file_senders[i].filenum, - TOX_FILECONTROL_KILL, 0, 0); - memset(&file_senders[i], 0, sizeof(FileSender)); - } - - set_max_file_senders_index(); - } -} - -static void send_file_data(ToxWindow *self, Tox *m, int i, int32_t friendnum, int filenum, const char *filename) -{ - FILE *fp = file_senders[i].file; - - while (true) { - if (tox_file_send_data(m, friendnum, filenum, (uint8_t *) file_senders[i].nextpiece, - file_senders[i].piecelen) == -1) - return; - - file_senders[i].timestamp = get_unix_time(); - file_senders[i].bps += file_senders[i].piecelen; - file_senders[i].piecelen = fread(file_senders[i].nextpiece, 1, - tox_file_data_size(m, friendnum), fp); - - /* note: file sender is closed in chat_onFileControl callback after receiving reply */ - if (file_senders[i].piecelen == 0) { - if (feof(fp) != 0) { /* make sure we're really at eof */ - print_progress_bar(self, i, -1, 100.0); - tox_file_send_control(m, friendnum, 0, filenum, TOX_FILECONTROL_FINISHED, 0, 0); - file_senders[i].finished = true; - } else { - char msg[MAX_STR_SIZE]; - snprintf(msg, sizeof(msg), "File transfer for '%s' failed: Read error.", file_senders[i].filename); - close_file_sender(self, m, i, msg, TOX_FILECONTROL_KILL, filenum, friendnum); - sound_notify(self, error, NT_NOFOCUS | NT_WNDALERT_2, NULL); - - if (self->active_box != -1) - box_notify2(self, error, NT_NOFOCUS | NT_WNDALERT_2, self->active_box, "%s", msg); - else - box_notify(self, error, NT_NOFOCUS | NT_WNDALERT_2, &self->active_box, self->name, "%s", msg); - } - - return; - } - } -} - -void do_file_senders(Tox *m) -{ - int i; - - for (i = 0; i < max_file_senders_index; ++i) { - if (!file_senders[i].active) - continue; - - if (file_senders[i].queue_pos > 0) { - --file_senders[i].queue_pos; - continue; - } - - ToxWindow *self = file_senders[i].toxwin; - char *filename = file_senders[i].filename; - int filenum = file_senders[i].filenum; - int32_t friendnum = file_senders[i].friendnum; - - /* kill file transfer if chatwindow is closed */ - if (self->chatwin == NULL) { - close_file_sender(self, m, i, NULL, TOX_FILECONTROL_KILL, filenum, friendnum); - continue; - } - - /* If file transfer has timed out kill transfer and send kill control */ - if (timed_out(file_senders[i].timestamp, get_unix_time(), TIMEOUT_FILESENDER) - && (!file_senders[i].paused || (file_senders[i].paused && file_senders[i].noconnection))) { - char msg[MAX_STR_SIZE]; - snprintf(msg, sizeof(msg), "File transfer for '%s' timed out.", filename); - close_file_sender(self, m, i, msg, TOX_FILECONTROL_KILL, filenum, friendnum); - - if (self->active_box != -1) - box_notify2(self, error, NT_NOFOCUS | NT_WNDALERT_2, self->active_box, "%s", msg); - else - box_notify(self, error, NT_NOFOCUS | NT_WNDALERT_2, &self->active_box, self->name, "%s", msg); - - continue; - } - - if ( !(file_senders[i].paused | file_senders[i].noconnection | file_senders[i].finished) ) - send_file_data(self, m, i, friendnum, filenum, filename); - - file_senders[i].queue_pos = num_active_file_senders - 1; - } - - refresh_sender_prog(m); - refresh_recv_prog(m); -} diff --git a/src/file_senders.h b/src/file_senders.h deleted file mode 100644 index 1581b4f..0000000 --- a/src/file_senders.h +++ /dev/null @@ -1,76 +0,0 @@ -/* file_senders.h - * - * - * Copyright (C) 2014 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 FILESENDERS_H -#define FILESENDERS_H - -#include "toxic.h" -#include "windows.h" - -#define KiB 1024 -#define MiB 1048576 /* 1024 ^ 2 */ -#define GiB 1073741824 /* 1024 ^ 3 */ - -#define FILE_PIECE_SIZE 2048 /* must be >= (MAX_CRYPTO_DATA_SIZE - 2) in toxcore/net_crypto.h */ -#define MAX_FILES 32 -#define TIMEOUT_FILESENDER 120 - -typedef struct { - FILE *file; - ToxWindow *toxwin; - int32_t friendnum; - bool active; - bool noconnection; /* set when the connection has been interrupted */ - bool paused; /* set when transfer has been explicitly paused */ - bool finished; /* set after entire file has been sent but no TOX_FILECONTROL_FINISHED receieved */ - bool started; /* set after TOX_FILECONTROL_ACCEPT received */ - int filenum; - char nextpiece[FILE_PIECE_SIZE]; - uint16_t piecelen; - char filename[MAX_STR_SIZE]; - uint64_t timestamp; /* marks the last time data was successfully transfered */ - uint64_t last_progress; /* marks the last time the progress bar was refreshed */ - double bps; - uint64_t size; - uint32_t line_id; - uint8_t queue_pos; -} FileSender; - -/* creates initial progress line that will be updated during file transfer. - Assumes progline is of size MAX_STR_SIZE */ -void prep_prog_line(char *progline); - -/* prints a progress bar for file transfers. - if friendnum is -1 we're sending the file, otherwise we're receiving. */ -void print_progress_bar(ToxWindow *self, int idx, int friendnum, double pct_remain); - -/* set CTRL to -1 if we don't want to send a control signal. - set msg to NULL if we don't want to display a message */ -void close_file_sender(ToxWindow *self, Tox *m, int i, const char *msg, int CTRL, int filenum, int32_t friendnum); - -/* called whenever a file sender is opened or closed */ -void reset_file_sender_queue(void); - -void close_all_file_senders(Tox *m); -void do_file_senders(Tox *m); - -#endif /* #define FILESENDERS_H */ diff --git a/src/file_transfers.c b/src/file_transfers.c new file mode 100644 index 0000000..4ac5c1b --- /dev/null +++ b/src/file_transfers.c @@ -0,0 +1,236 @@ +/* file_transfers.c + * + * + * Copyright (C) 2014 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 + +#include "toxic.h" +#include "windows.h" +#include "friendlist.h" +#include "file_transfers.h" +#include "line_info.h" +#include "misc_tools.h" +#include "notify.h" + +extern FriendsList Friends; + +#define NUM_PROG_MARKS 50 /* number of "#"'s in file transfer progress bar. Keep well below MAX_STR_SIZE */ + +/* creates initial progress line that will be updated during file transfer. + Assumes progline is of size MAX_STR_SIZE */ +void prep_prog_line(char *progline) +{ + strcpy(progline, "0.0 B/s ["); + int i; + + for (i = 0; i < NUM_PROG_MARKS; ++i) + strcat(progline, "-"); + + strcat(progline, "] 0%"); +} + +/* prints a progress bar for file transfers. + if friendnum is -1 we're sending the file, otherwise we're receiving. */ +void print_progress_bar(ToxWindow *self, double bps, double pct_done, uint32_t line_id) +{ + if (bps < 0 || pct_done < 0 || pct_done > 100) + return; + + char msg[MAX_STR_SIZE]; + bytes_convert_str(msg, sizeof(msg), bps); + strcat(msg, "/s ["); + + int n = pct_done / (100 / NUM_PROG_MARKS); + int i, j; + + for (i = 0; i < n; ++i) + strcat(msg, "#"); + + for (j = i; j < NUM_PROG_MARKS; ++j) + strcat(msg, "-"); + + strcat(msg, "] "); + + char pctstr[16]; + const char *frmt = pct_done == 100 ? "%.f%%" : "%.1f%%"; + snprintf(pctstr, sizeof(pctstr), frmt, pct_done); + strcat(msg, pctstr); + + line_info_set(self, line_id, msg); +} + +static void refresh_progress_helper(ToxWindow *self, struct FileTransfer *ft, uint64_t curtime) +{ + if (ft->state == FILE_TRANSFER_INACTIVE) + return; + + /* Timeout must be set to 1 second to show correct bytes per second */ + if (!timed_out(ft->last_progress, curtime, 1)) + return; + + double remain = ft->file_size - ft->position; + double pct_done = remain > 0 ? (1 - (remain / ft->file_size)) * 100 : 100; + print_progress_bar(self, ft->bps, pct_done, ft->line_id); + + ft->bps = 0; + ft->last_progress = curtime; +} + +/* refreshes active file receiver status bars for friendnum */ +void refresh_file_transfer_progress(ToxWindow *self, Tox *m, uint32_t friendnum) +{ + uint64_t curtime = get_unix_time(); + size_t i; + + for (i = 0; i < MAX_FILES; ++i) { + refresh_progress_helper(self, &Friends.list[friendnum].file_receiver[i], curtime); + refresh_progress_helper(self, &Friends.list[friendnum].file_sender[i], curtime); + } +} + +/* Returns a pointer to friendnum's FileTransfer struct associated with filenum. + * Returns NULL if filenum is invalid. + */ +struct FileTransfer *get_file_transfer_struct(uint32_t friendnum, uint32_t filenum) +{ + size_t i; + + for (i = 0; i < MAX_FILES; ++i) { + struct FileTransfer *ft_send = &Friends.list[friendnum].file_sender[i]; + + if (ft_send->state != FILE_TRANSFER_INACTIVE && ft_send->filenum == filenum) + return ft_send; + + struct FileTransfer *ft_recv = &Friends.list[friendnum].file_receiver[i]; + + if (ft_recv->state != FILE_TRANSFER_INACTIVE && ft_recv->filenum == filenum) + return ft_recv; + } + + return NULL; +} + +/* Returns a pointer to the FileTransfer struct associated with index with the direction specified. + * Returns NULL on failure. + */ +struct FileTransfer *get_file_transfer_struct_index(uint32_t friendnum, uint32_t index, + FILE_TRANSFER_DIRECTION direction) +{ + if (direction != FILE_TRANSFER_RECV && direction != FILE_TRANSFER_SEND) + return NULL; + + size_t i; + + for (i = 0; i < MAX_FILES; ++i) { + struct FileTransfer *ft = direction == FILE_TRANSFER_SEND ? + &Friends.list[friendnum].file_sender[i] : + &Friends.list[friendnum].file_receiver[i]; + + if (ft->state != FILE_TRANSFER_INACTIVE && ft->index == index) + return ft; + } + + return NULL; +} + +/* Returns a pointer to an unused file sender. + * Returns NULL if all file senders are in use. + */ +struct FileTransfer *get_new_file_sender(uint32_t friendnum) +{ + size_t i; + + for (i = 0; i < MAX_FILES; ++i) { + struct FileTransfer *ft = &Friends.list[friendnum].file_sender[i]; + + if (ft->state == FILE_TRANSFER_INACTIVE) { + ft->index = i; + return ft; + } + } + + return NULL; +} + +/* Returns a pointer to an unused file receiver. + * Returns NULL if all file receivers are in use. + */ +struct FileTransfer *get_new_file_receiver(uint32_t friendnum) +{ + size_t i; + + for (i = 0; i < MAX_FILES; ++i) { + struct FileTransfer *ft = &Friends.list[friendnum].file_receiver[i]; + + if (ft->state == FILE_TRANSFER_INACTIVE) { + ft->index = i; + return ft; + } + } + + return NULL; +} + +/* Closes file transfer ft. + * + * Set CTRL to -1 if we don't want to send a control signal. + * Set message or self to NULL if we don't want to display a message. + */ +void close_file_transfer(ToxWindow *self, Tox *m, struct FileTransfer *ft, int CTRL, const char *message, + Notification sound_type) +{ + if (!ft) + return; + + if (ft->state == FILE_TRANSFER_INACTIVE) + return; + + if (ft->file) + fclose(ft->file); + + memset(ft, 0, sizeof(struct FileTransfer)); + + if (CTRL >= 0) + tox_file_control(m, ft->friendnum, ft->filenum, (TOX_FILE_CONTROL) CTRL, NULL); + + if (message && self) { + if (self->active_box != -1) + box_notify2(self, sound_type, NT_NOFOCUS | NT_WNDALERT_2, self->active_box, "%s", message); + else + box_notify(self, sound_type, NT_NOFOCUS | NT_WNDALERT_2, &self->active_box, self->name, "%s", message); + + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s", message); + } +} + +/* Kills all active file transfers for friendnum */ +void kill_all_file_transfers_friend(Tox *m, uint32_t friendnum) +{ + size_t i; + + for (i = 0; i < MAX_FILES; ++i) { + close_file_transfer(NULL, m, &Friends.list[friendnum].file_sender[i], -1, NULL, silent); + close_file_transfer(NULL, m, &Friends.list[friendnum].file_receiver[i], -1, NULL, silent); + } +} diff --git a/src/file_transfers.h b/src/file_transfers.h new file mode 100644 index 0000000..ba12886 --- /dev/null +++ b/src/file_transfers.h @@ -0,0 +1,110 @@ +/* file_transfers.h + * + * + * Copyright (C) 2014 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 FILE_TRANSFERS_H +#define FILE_TRANSFERS_H + +#include + +#include "toxic.h" +#include "windows.h" +#include "notify.h" + +#define KiB 1024 +#define MiB 1048576 /* 1024 ^ 2 */ +#define GiB 1073741824 /* 1024 ^ 3 */ + +#define MAX_FILES 32 +#define TIMEOUT_FILESENDER 120 + +typedef enum FILE_TRANSFER_STATE { + FILE_TRANSFER_INACTIVE, + FILE_TRANSFER_PENDING, + FILE_TRANSFER_STARTED, + FILE_TRANSFER_PAUSED +} FILE_TRANSFER_STATE; + +typedef enum FILE_TRANSFER_DIRECTION { + FILE_TRANSFER_SEND, + FILE_TRANSFER_RECV +} FILE_TRANSFER_DIRECTION; + +struct FileTransfer { + FILE *file; + FILE_TRANSFER_STATE state; + FILE_TRANSFER_DIRECTION direction; + char file_name[TOX_MAX_FILENAME_LENGTH + 1]; + char file_path[PATH_MAX + 1]; /* Not used by senders */ + double bps; + uint32_t filenum; + uint32_t friendnum; + size_t index; + uint64_t file_size; + uint64_t last_progress; + uint64_t position; + uint32_t line_id; +}; + +/* creates initial progress line that will be updated during file transfer. + progline must be at lesat MAX_STR_SIZE bytes */ +void prep_prog_line(char *progline); + +/* prints a progress bar for file transfers */ +void print_progress_bar(ToxWindow *self, double pct_done, double bps, uint32_t line_id); + +/* refreshes active file transfer status bars for friendnum */ +void refresh_file_transfer_progress(ToxWindow *self, Tox *m, uint32_t friendnum); + +/* Returns a pointer to friendnum's FileTransfer struct associated with filenum. + * Returns NULL if filenum is invalid. + */ +struct FileTransfer *get_file_transfer_struct(uint32_t friendnum, uint32_t filenum); + + +/* Returns a pointer to the FileTransfer struct associated with index with the direction specified. + * Returns NULL on failure. + */ +struct FileTransfer *get_file_transfer_struct_index(uint32_t friendnum, uint32_t index, + FILE_TRANSFER_DIRECTION direction); + +/* Returns a pointer to an unused file sender. + * Returns NULL if all file senders are in use. + */ +struct FileTransfer *get_new_file_sender(uint32_t friendnum); + +/* Returns a pointer to an unused file receiver. + * Returns NULL if all file receivers are in use. + */ +struct FileTransfer *get_new_file_receiver(uint32_t friendnum); + +/* Closes file transfer ft. + * + * Set CTRL to -1 if we don't want to send a control signal. + * Set message or self to NULL if we don't want to display a message. + */ +void close_file_transfer(ToxWindow *self, Tox *m, struct FileTransfer *ft, int CTRL, const char *message, + Notification sound_type); + +/* Kills all active file transfers for friendnum */ +void kill_all_file_transfers_friend(Tox *m, uint32_t friendnum); + +#endif /* #define FILE_TRANSFERS_H */ diff --git a/src/friendlist.c b/src/friendlist.c index 0fb475a..8f352b2 100644 --- a/src/friendlist.c +++ b/src/friendlist.c @@ -59,16 +59,15 @@ static struct Blocked { int num_selected; int max_idx; int num_blocked; - - int *index; + uint32_t *index; BlockedFriend *list; } Blocked; -static struct pendingDel { - int num; +static struct PendingDel { + uint32_t num; bool active; WINDOW *popup; -} pendingdelete; +} PendingDelete; static void realloc_friends(int n) { @@ -81,7 +80,7 @@ static void realloc_friends(int n) } ToxicFriend *f = realloc(Friends.list, n * sizeof(ToxicFriend)); - int *f_idx = realloc(Friends.index, n * sizeof(int)); + uint32_t *f_idx = realloc(Friends.index, n * sizeof(uint32_t)); if (f == NULL || f_idx == NULL) exit_toxic_err("failed in realloc_friends", FATALERR_MEMORY); @@ -101,7 +100,7 @@ static void realloc_blocklist(int n) } BlockedFriend *b = realloc(Blocked.list, n * sizeof(BlockedFriend)); - int *b_idx = realloc(Blocked.index, n * sizeof(int)); + uint32_t *b_idx = realloc(Blocked.index, n * sizeof(uint32_t)); if (b == NULL || b_idx == NULL) exit_toxic_err("failed in realloc_blocklist", FATALERR_MEMORY); @@ -125,9 +124,6 @@ void kill_friendlist(void) static int save_blocklist(char *path) { - if (arg_opts.ignore_data_file) - return 0; - if (path == NULL) return -1; @@ -193,7 +189,7 @@ int load_blocklist(char *path) off_t len = file_size(path); - if (len == -1) { + if (len == 0) { fclose(fp); return -1; } @@ -255,8 +251,8 @@ static int index_name_cmp(const void *n1, const void *n2) int res = qsort_strcasecmp_hlpr(Friends.list[*(int *) n1].name, Friends.list[*(int *) n2].name); /* Use weight to make qsort always put online friends before offline */ - res = Friends.list[*(int *) n1].online ? (res - S_WEIGHT) : (res + S_WEIGHT); - res = Friends.list[*(int *) n2].online ? (res + S_WEIGHT) : (res - S_WEIGHT); + res = Friends.list[*(int *) n1].connection_status ? (res - S_WEIGHT) : (res + S_WEIGHT); + res = Friends.list[*(int *) n2].connection_status ? (res + S_WEIGHT) : (res - S_WEIGHT); return res; } @@ -264,15 +260,15 @@ static int index_name_cmp(const void *n1, const void *n2) /* sorts Friends.index first by connection status then alphabetically */ void sort_friendlist_index(void) { - int i; - int n = 0; + size_t i; + uint32_t n = 0; for (i = 0; i < Friends.max_idx; ++i) { if (Friends.list[i].active) Friends.index[n++] = Friends.list[i].num; } - qsort(Friends.index, Friends.num_friends, sizeof(int), index_name_cmp); + qsort(Friends.index, Friends.num_friends, sizeof(uint32_t), index_name_cmp); } static int index_name_cmp_block(const void *n1, const void *n2) @@ -282,18 +278,18 @@ static int index_name_cmp_block(const void *n1, const void *n2) static void sort_blocklist_index(void) { - int i; - int n = 0; + size_t i; + uint32_t n = 0; for (i = 0; i < Blocked.max_idx; ++i) { if (Blocked.list[i].active) Blocked.index[n++] = Blocked.list[i].num; } - qsort(Blocked.index, Blocked.num_blocked, sizeof(int), index_name_cmp_block); + qsort(Blocked.index, Blocked.num_blocked, sizeof(uint32_t), index_name_cmp_block); } -static void update_friend_last_online(int32_t num, uint64_t timestamp) +static void update_friend_last_online(uint32_t num, uint64_t timestamp) { Friends.list[num].last_online.last_on = timestamp; Friends.list[num].last_online.tm = *localtime((const time_t*)×tamp); @@ -304,42 +300,48 @@ static void update_friend_last_online(int32_t num, uint64_t timestamp) &Friends.list[num].last_online.tm); } -static void friendlist_onMessage(ToxWindow *self, Tox *m, int32_t num, const char *str, uint16_t len) +static void friendlist_onMessage(ToxWindow *self, Tox *m, uint32_t num, TOX_MESSAGE_TYPE type, const char *str, + size_t length) { if (num >= Friends.max_idx) return; - if (Friends.list[num].chatwin == -1) { - if (get_num_active_windows() < MAX_WINDOWS_NUM) { - Friends.list[num].chatwin = add_window(m, new_chat(m, Friends.list[num].num)); - } else { - char nick[TOX_MAX_NAME_LENGTH]; - get_nick_truncate(m, nick, num); + if (Friends.list[num].chatwin != -1) + return; - char timefrmt[TIME_STR_SIZE]; - get_time_str(timefrmt, sizeof(timefrmt)); - - line_info_add(prompt, timefrmt, nick, NULL, IN_MSG, 0, 0, "%s", str); - - const char *msg = "* Warning: Too many windows are open."; - line_info_add(prompt, NULL, NULL, NULL, SYS_MSG, 0, RED, msg); - sound_notify(prompt, error, NT_WNDALERT_1, NULL); - } + if (get_num_active_windows() < MAX_WINDOWS_NUM) { + Friends.list[num].chatwin = add_window(m, new_chat(m, Friends.list[num].num)); + return; } + + char nick[TOX_MAX_NAME_LENGTH]; + get_nick_truncate(m, nick, num); + + char timefrmt[TIME_STR_SIZE]; + get_time_str(timefrmt, sizeof(timefrmt)); + + line_info_add(prompt, timefrmt, nick, NULL, IN_MSG, 0, 0, "%s", str); + line_info_add(prompt, NULL, NULL, NULL, SYS_MSG, 0, RED, "* Warning: Too many windows are open."); + sound_notify(prompt, notif_error, NT_WNDALERT_1, NULL); } -static void friendlist_onConnectionChange(ToxWindow *self, Tox *m, int32_t num, uint8_t status) +static void friendlist_onConnectionChange(ToxWindow *self, Tox *m, uint32_t num, TOX_CONNECTION connection_status) { if (num >= Friends.max_idx) return; - Friends.list[num].online = status; + if (connection_status == TOX_CONNECTION_NONE) + --Friends.num_online; + else + ++Friends.num_online; + + Friends.list[num].connection_status = connection_status; update_friend_last_online(num, get_unix_time()); store_data(m, DATA_FILE); sort_friendlist_index(); } -static void friendlist_onNickChange(ToxWindow *self, Tox *m, int32_t num, const char *nick, uint16_t len) +static void friendlist_onNickChange(ToxWindow *self, Tox *m, uint32_t num, const char *nick, size_t length) { if (num >= Friends.max_idx) return; @@ -354,9 +356,9 @@ static void friendlist_onNickChange(ToxWindow *self, Tox *m, int32_t num, const /* get data for chatlog renaming */ char newnamecpy[TOXIC_MAX_NAME_LENGTH + 1]; - char myid[TOX_FRIEND_ADDRESS_SIZE]; + char myid[TOX_ADDRESS_SIZE]; strcpy(newnamecpy, Friends.list[num].name); - tox_get_address(m, (uint8_t *) myid); + tox_self_get_address(m, (uint8_t *) myid); if (strcmp(oldname, newnamecpy) != 0) rename_logfile(oldname, newnamecpy, myid, Friends.list[num].pub_key, Friends.list[num].chatwin); @@ -364,7 +366,7 @@ static void friendlist_onNickChange(ToxWindow *self, Tox *m, int32_t num, const sort_friendlist_index(); } -static void friendlist_onStatusChange(ToxWindow *self, Tox *m, int32_t num, uint8_t status) +static void friendlist_onStatusChange(ToxWindow *self, Tox *m, uint32_t num, TOX_USER_STATUS status) { if (num >= Friends.max_idx) return; @@ -372,50 +374,47 @@ static void friendlist_onStatusChange(ToxWindow *self, Tox *m, int32_t num, uint Friends.list[num].status = status; } -static void friendlist_onStatusMessageChange(ToxWindow *self, int32_t num, const char *status, uint16_t len) +static void friendlist_onStatusMessageChange(ToxWindow *self, uint32_t num, const char *note, size_t length) { - if (len > TOX_MAX_STATUSMESSAGE_LENGTH || num >= Friends.max_idx) + if (length > TOX_MAX_STATUS_MESSAGE_LENGTH || num >= Friends.max_idx) return; - snprintf(Friends.list[num].statusmsg, sizeof(Friends.list[num].statusmsg), "%s", status); + snprintf(Friends.list[num].statusmsg, sizeof(Friends.list[num].statusmsg), "%s", note); Friends.list[num].statusmsg_len = strlen(Friends.list[num].statusmsg); } -void friendlist_onFriendAdded(ToxWindow *self, Tox *m, int32_t num, bool sort) +void friendlist_onFriendAdded(ToxWindow *self, Tox *m, uint32_t num, bool sort) { - if (Friends.max_idx < 0) - return; - - - Friends.num_friends = tox_count_friendlist(m); realloc_friends(Friends.max_idx + 1); memset(&Friends.list[Friends.max_idx], 0, sizeof(ToxicFriend)); - int i; + uint32_t i; for (i = 0; i <= Friends.max_idx; ++i) { if (Friends.list[i].active) continue; + ++Friends.num_friends; + Friends.list[i].num = num; Friends.list[i].active = true; Friends.list[i].chatwin = -1; - Friends.list[i].online = false; - Friends.list[i].status = TOX_USERSTATUS_NONE; + Friends.list[i].connection_status = TOX_CONNECTION_NONE; + Friends.list[i].status = TOX_USER_STATUS_NONE; Friends.list[i].logging_on = (bool) user_settings->autolog == AUTOLOG_ON; - tox_get_client_id(m, num, (uint8_t *) Friends.list[i].pub_key); - update_friend_last_online(i, tox_get_last_online(m, i)); + + TOX_ERR_FRIEND_GET_PUBLIC_KEY err; + tox_friend_get_public_key(m, num, (uint8_t *) Friends.list[i].pub_key, &err); + + if (err != TOX_ERR_FRIEND_GET_PUBLIC_KEY_OK) + fprintf(stderr, "tox_friend_get_public_key failed (error %d)\n", err); + + // update_friend_last_online(i, 0); char tempname[TOX_MAX_NAME_LENGTH] = {0}; - int len = get_nick_truncate(m, tempname, num); - - if (len == -1 || tempname[0] == '\0') { - strcpy(Friends.list[i].name, UNKNOWN_NAME); - Friends.list[i].namelength = strlen(UNKNOWN_NAME); - } else { /* Enforce toxic's maximum name length */ - snprintf(Friends.list[i].name, sizeof(Friends.list[i].name), "%s", tempname); - Friends.list[i].namelength = strlen(Friends.list[i].name); - } + get_nick_truncate(m, tempname, num); + snprintf(Friends.list[i].name, sizeof(Friends.list[i].name), "%s", tempname); + Friends.list[i].namelength = strlen(Friends.list[i].name); if (i == Friends.max_idx) ++Friends.max_idx; @@ -428,9 +427,8 @@ 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) +static void friendlist_add_blocked(Tox *m, uint32_t fnum, uint32_t bnum) { - Friends.num_friends = tox_count_friendlist(m); realloc_friends(Friends.max_idx + 1); memset(&Friends.list[Friends.max_idx], 0, sizeof(ToxicFriend)); @@ -440,10 +438,12 @@ static void friendlist_add_blocked(Tox *m, int32_t fnum, int32_t bnum) if (Friends.list[i].active) continue; + ++Friends.num_friends; + Friends.list[i].num = fnum; Friends.list[i].active = true; Friends.list[i].chatwin = -1; - Friends.list[i].status = TOX_USERSTATUS_NONE; + Friends.list[i].status = TOX_USER_STATUS_NONE; Friends.list[i].logging_on = (bool) user_settings->autolog == AUTOLOG_ON; Friends.list[i].namelength = Blocked.list[bnum].namelength; update_friend_last_online(i, Blocked.list[bnum].last_on); @@ -460,27 +460,29 @@ static void friendlist_add_blocked(Tox *m, int32_t fnum, int32_t bnum) } } -static void friendlist_onFileSendRequest(ToxWindow *self, Tox *m, int32_t num, uint8_t filenum, - uint64_t filesize, const char *filename, uint16_t filename_len) +static void friendlist_onFileRecv(ToxWindow *self, Tox *m, uint32_t num, uint32_t filenum, + uint64_t file_size, const char *filename, size_t name_length) { if (num >= Friends.max_idx) return; - if (Friends.list[num].chatwin == -1) { - if (get_num_active_windows() < MAX_WINDOWS_NUM) { - Friends.list[num].chatwin = add_window(m, new_chat(m, Friends.list[num].num)); - } else { - tox_file_send_control(m, num, 1, filenum, TOX_FILECONTROL_KILL, 0, 0); + if (Friends.list[num].chatwin != -1) + return; - char nick[TOX_MAX_NAME_LENGTH]; - get_nick_truncate(m, nick, num); - - line_info_add(prompt, NULL, NULL, NULL, SYS_MSG, 0, RED, - "* File transfer from %s failed: too many windows are open.", nick); - - sound_notify(prompt, error, NT_WNDALERT_1, NULL); - } + if (get_num_active_windows() < MAX_WINDOWS_NUM) { + Friends.list[num].chatwin = add_window(m, new_chat(m, Friends.list[num].num)); + return; } + + tox_file_control(m, num, filenum, TOX_FILE_CONTROL_CANCEL, NULL); + + char nick[TOX_MAX_NAME_LENGTH]; + get_nick_truncate(m, nick, num); + + line_info_add(prompt, NULL, NULL, NULL, SYS_MSG, 0, RED, + "* File transfer from %s failed: too many windows are open.", nick); + + sound_notify(prompt, notif_error, NT_WNDALERT_1, NULL); } static void friendlist_onGroupInvite(ToxWindow *self, Tox *m, int32_t num, const char *data, @@ -489,17 +491,21 @@ static void friendlist_onGroupInvite(ToxWindow *self, Tox *m, int32_t num, const if (num >= Friends.max_idx) return; - if (Friends.list[num].chatwin == -1) { - if (get_num_active_windows() < MAX_WINDOWS_NUM) { - Friends.list[num].chatwin = add_window(m, new_chat(m, Friends.list[num].num)); - } else { - char nick[TOX_MAX_NAME_LENGTH]; - get_nick_truncate(m, nick, num); - line_info_add(prompt, NULL, NULL, NULL, SYS_MSG, 0, RED, - "* Group chat invite from %s failed: too many windows are open.", nick); - sound_notify(prompt, error, NT_WNDALERT_1, NULL); - } + if (Friends.list[num].chatwin != -1) + return; + + if (get_num_active_windows() < MAX_WINDOWS_NUM) { + Friends.list[num].chatwin = add_window(m, new_chat(m, Friends.list[num].num)); + return; } + + char nick[TOX_MAX_NAME_LENGTH]; + get_nick_truncate(m, nick, num); + + line_info_add(prompt, NULL, NULL, NULL, SYS_MSG, 0, RED, + "* Group chat invite from %s failed: too many windows are open.", nick); + + sound_notify(prompt, notif_error, NT_WNDALERT_1, NULL); } /* move friendlist/blocklist cursor up and down */ @@ -516,8 +522,20 @@ static void select_friend(ToxWindow *self, wint_t key, int *selected, int num) } } -static void delete_friend(Tox *m, int32_t f_num) +static void delete_friend(Tox *m, uint32_t f_num) { + TOX_ERR_FRIEND_DELETE err; + if (tox_friend_delete(m, f_num, &err) != true) { + fprintf(stderr, "tox_friend_delete failed with error %d\n", err); + return; + } + + --Friends.num_friends; + + if (Friends.list[f_num].connection_status != TOX_CONNECTION_NONE) + --Friends.num_online; + + /* close friend's chatwindow if it's currently open */ if (Friends.list[f_num].chatwin >= 0) { ToxWindow *toxwin = get_window_ptr(Friends.list[f_num].chatwin); @@ -527,7 +545,6 @@ static void delete_friend(Tox *m, int32_t f_num) } } - tox_del_friend(m, f_num); memset(&Friends.list[f_num], 0, sizeof(ToxicFriend)); int i; @@ -538,7 +555,6 @@ static void delete_friend(Tox *m, int32_t f_num) } Friends.max_idx = i; - Friends.num_friends = tox_count_friendlist(m); realloc_friends(i); /* make sure num_selected stays within Friends.num_friends range */ @@ -549,60 +565,60 @@ static void delete_friend(Tox *m, int32_t f_num) } /* activates delete friend popup */ -static void del_friend_activate(ToxWindow *self, Tox *m, int32_t f_num) +static void del_friend_activate(ToxWindow *self, Tox *m, uint32_t f_num) { - pendingdelete.popup = newwin(3, 22 + TOXIC_MAX_NAME_LENGTH, 8, 8); - pendingdelete.active = true; - pendingdelete.num = f_num; + PendingDelete.popup = newwin(3, 22 + TOXIC_MAX_NAME_LENGTH, 8, 8); + PendingDelete.active = true; + PendingDelete.num = f_num; } -static void delete_blocked_friend(int32_t bnum); +static void delete_blocked_friend(uint32_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') { if (blocklist_view == 0) { - delete_friend(m, pendingdelete.num); + delete_friend(m, PendingDelete.num); sort_friendlist_index(); } else { - delete_blocked_friend(pendingdelete.num); + delete_blocked_friend(PendingDelete.num); sort_blocklist_index(); } } - delwin(pendingdelete.popup); - memset(&pendingdelete, 0, sizeof(pendingdelete)); + delwin(PendingDelete.popup); + memset(&PendingDelete, 0, sizeof(PendingDelete)); clear(); refresh(); } static void draw_del_popup(void) { - if (!pendingdelete.active) + if (!PendingDelete.active) return; - wattron(pendingdelete.popup, A_BOLD); - box(pendingdelete.popup, ACS_VLINE, ACS_HLINE); - wattroff(pendingdelete.popup, A_BOLD); + wattron(PendingDelete.popup, A_BOLD); + box(PendingDelete.popup, ACS_VLINE, ACS_HLINE); + wattroff(PendingDelete.popup, A_BOLD); - wmove(pendingdelete.popup, 1, 1); - wprintw(pendingdelete.popup, "Delete contact "); - wattron(pendingdelete.popup, A_BOLD); + wmove(PendingDelete.popup, 1, 1); + wprintw(PendingDelete.popup, "Delete contact "); + wattron(PendingDelete.popup, A_BOLD); if (blocklist_view == 0) - wprintw(pendingdelete.popup, "%s", Friends.list[pendingdelete.num].name); + wprintw(PendingDelete.popup, "%s", Friends.list[PendingDelete.num].name); else - wprintw(pendingdelete.popup, "%s", Blocked.list[pendingdelete.num].name); + wprintw(PendingDelete.popup, "%s", Blocked.list[PendingDelete.num].name); - wattroff(pendingdelete.popup, A_BOLD); - wprintw(pendingdelete.popup, "? y/n"); + wattroff(PendingDelete.popup, A_BOLD); + wprintw(PendingDelete.popup, "? y/n"); - wrefresh(pendingdelete.popup); + wrefresh(PendingDelete.popup); } /* deletes contact from blocked list */ -static void delete_blocked_friend(int32_t bnum) +static void delete_blocked_friend(uint32_t bnum) { memset(&Blocked.list[bnum], 0, sizeof(BlockedFriend)); @@ -623,7 +639,7 @@ static void delete_blocked_friend(int32_t bnum) } /* deletes contact from friendlist and puts in blocklist */ -void block_friend(Tox *m, int32_t fnum) +void block_friend(Tox *m, uint32_t fnum) { if (Friends.num_friends <= 0) return; @@ -642,7 +658,7 @@ void block_friend(Tox *m, int32_t fnum) Blocked.list[i].namelength = Friends.list[fnum].namelength; Blocked.list[i].last_on = Friends.list[fnum].last_online.last_on; memcpy(Blocked.list[i].pub_key, Friends.list[fnum].pub_key, TOX_PUBLIC_KEY_SIZE); - memcpy(Blocked.list[i].name, Friends.list[fnum].name, Friends.list[fnum].namelength + 1); + memcpy(Blocked.list[i].name, Friends.list[fnum].name, Friends.list[fnum].namelength + 1); ++Blocked.num_blocked; @@ -659,15 +675,16 @@ void block_friend(Tox *m, int32_t fnum) } /* removes friend from blocklist, puts back in friendlist */ -static void unblock_friend(Tox *m, int32_t bnum) +static void unblock_friend(Tox *m, uint32_t bnum) { if (Blocked.num_blocked <= 0) return; - int32_t friendnum = tox_add_friend_norequest(m, (uint8_t *) Blocked.list[bnum].pub_key); + TOX_ERR_FRIEND_ADD err; + uint32_t friendnum = tox_friend_add_norequest(m, (uint8_t *) Blocked.list[bnum].pub_key, &err); - if (friendnum == -1) { - line_info_add(prompt, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to unblock friend"); + if (err != TOX_ERR_FRIEND_ADD_OK) { + line_info_add(prompt, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to unblock friend (error %d)\n", err); return; } @@ -704,7 +721,7 @@ static void friendlist_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr) f = Friends.index[Friends.num_selected]; /* lock screen and force decision on deletion popup */ - if (pendingdelete.active) { + if (PendingDelete.active) { if (key == 'y' || key == 'n') del_friend_deactivate(self, m, key); @@ -728,7 +745,7 @@ 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); - sound_notify(prompt, error, NT_WNDALERT_1, NULL); + sound_notify(prompt, notif_error, NT_WNDALERT_1, NULL); } break; @@ -770,7 +787,7 @@ static void blocklist_onDraw(ToxWindow *self, Tox *m, int y2, int x2) if ((y2 - FLIST_OFST) <= 0) return; - int selected_num = 0; + uint32_t selected_num = 0; /* Determine which portion of friendlist to draw based on current position */ int page = Blocked.num_selected / (y2 - FLIST_OFST); @@ -780,7 +797,7 @@ static void blocklist_onDraw(ToxWindow *self, Tox *m, int y2, int x2) int i; for (i = start; i < Blocked.num_blocked && i < end; ++i) { - int f = Blocked.index[i]; + uint32_t f = Blocked.index[i]; bool f_selected = false; if (i == Blocked.num_selected) { @@ -853,22 +870,18 @@ static void friendlist_onDraw(ToxWindow *self, Tox *m) 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); + // uint64_t cur_time = get_unix_time(); + // struct tm cur_loc_tm = *localtime((const time_t *) &cur_time); wattron(self->window, A_BOLD); wprintw(self->window, " Online: "); wattroff(self->window, A_BOLD); - wprintw(self->window, "%d/%d \n\n", nf, Friends.num_friends); + wprintw(self->window, "%d/%d \n\n", Friends.num_online, Friends.num_friends); if ((y2 - FLIST_OFST) <= 0) return; - int selected_num = 0; + uint32_t selected_num = 0; /* Determine which portion of friendlist to draw based on current position */ int page = Friends.num_selected / (y2 - FLIST_OFST); @@ -878,7 +891,7 @@ static void friendlist_onDraw(ToxWindow *self, Tox *m) int i; for (i = start; i < Friends.num_friends && i < end; ++i) { - int f = Friends.index[i]; + uint32_t f = Friends.index[i]; bool f_selected = false; if (Friends.list[f].active) { @@ -892,26 +905,20 @@ static void friendlist_onDraw(ToxWindow *self, Tox *m) wprintw(self->window, " "); } - if (Friends.list[f].online) { - uint8_t status = Friends.list[f].status; - int colour = WHITE; + if (Friends.list[f].connection_status != TOX_CONNECTION_NONE) { + TOX_USER_STATUS status = Friends.list[f].status; + int colour = MAGENTA; switch (status) { - case TOX_USERSTATUS_NONE: + case TOX_USER_STATUS_NONE: colour = GREEN; break; - - case TOX_USERSTATUS_AWAY: + case TOX_USER_STATUS_AWAY: colour = YELLOW; break; - - case TOX_USERSTATUS_BUSY: + case TOX_USER_STATUS_BUSY: colour = RED; break; - - case TOX_USERSTATUS_INVALID: - colour = MAGENTA; - break; } wattron(self->window, COLOR_PAIR(colour) | A_BOLD); @@ -930,11 +937,11 @@ static void friendlist_onDraw(ToxWindow *self, Tox *m) /* Reset Friends.list[f].statusmsg on window resize */ if (fix_statuses) { - char statusmsg[TOX_MAX_STATUSMESSAGE_LENGTH]; + char statusmsg[TOX_MAX_STATUS_MESSAGE_LENGTH]; pthread_mutex_lock(&Winthread.lock); - int s_len = tox_get_status_message(m, Friends.list[f].num, (uint8_t *) statusmsg, - TOX_MAX_STATUSMESSAGE_LENGTH); + tox_friend_get_status_message(m, Friends.list[f].num, (uint8_t *) statusmsg, NULL); + size_t s_len = tox_friend_get_status_message_size(m, Friends.list[f].num, NULL); pthread_mutex_unlock(&Winthread.lock); filter_str(statusmsg, s_len); @@ -943,7 +950,7 @@ static void friendlist_onDraw(ToxWindow *self, Tox *m) } /* Truncate note if it doesn't fit on one line */ - uint16_t maxlen = x2 - getcurx(self->window) - 2; + size_t maxlen = x2 - getcurx(self->window) - 2; if (Friends.list[f].statusmsg_len > maxlen) { Friends.list[f].statusmsg[maxlen - 3] = '\0'; @@ -969,31 +976,34 @@ static void friendlist_onDraw(ToxWindow *self, Tox *m) if (f_selected) wattroff(self->window, COLOR_PAIR(BLUE)); - uint64_t last_seen = Friends.list[f].last_online.last_on; + wprintw(self->window, "\n"); + /* Last online is currently broken in core */ - if (last_seen != 0) { - int day_dist = ( - cur_loc_tm.tm_yday - Friends.list[f].last_online.tm.tm_yday - + ((cur_loc_tm.tm_year - Friends.list[f].last_online.tm.tm_year) * 365) - ); - const char *hourmin = Friends.list[f].last_online.hour_min_str; + // uint64_t last_seen = Friends.list[f].last_online.last_on; + // + // if (last_seen != 0) { + // int day_dist = ( + // cur_loc_tm.tm_yday - Friends.list[f].last_online.tm.tm_yday + // + ((cur_loc_tm.tm_year - Friends.list[f].last_online.tm.tm_year) * 365) + // ); + // const char *hourmin = Friends.list[f].last_online.hour_min_str; - switch (day_dist) { - case 0: - wprintw(self->window, " Last seen: Today %s\n", hourmin); - break; + // switch (day_dist) { + // case 0: + // wprintw(self->window, " Last seen: Today %s\n", hourmin); + // break; - case 1: - wprintw(self->window, " Last seen: Yesterday %s\n", hourmin); - break; + // case 1: + // wprintw(self->window, " Last seen: Yesterday %s\n", hourmin); + // break; - default: - wprintw(self->window, " Last seen: %d days ago\n", day_dist); - break; - } - } else { - wprintw(self->window, " Last seen: Never\n"); - } + // default: + // wprintw(self->window, " Last seen: %d days ago\n", day_dist); + // break; + // } + // } else { + // wprintw(self->window, " Last seen: Never\n"); + // } } } } @@ -1020,7 +1030,7 @@ static void friendlist_onDraw(ToxWindow *self, Tox *m) help_onDraw(self); } -void disable_chatwin(int32_t f_num) +void disable_chatwin(uint32_t f_num) { Friends.list[f_num].chatwin = -1; } @@ -1048,7 +1058,7 @@ static void friendlist_onAv(ToxWindow *self, ToxAv *av, int call_index) const char *errmsg = "* Warning: Too many windows are open."; line_info_add(prompt, NULL, NULL, NULL, SYS_MSG, 0, RED, errmsg); - sound_notify(prompt, error, NT_WNDALERT_1, NULL); + sound_notify(prompt, notif_error, NT_WNDALERT_1, NULL); } } } @@ -1067,11 +1077,10 @@ ToxWindow new_friendlist(void) ret.onFriendAdded = &friendlist_onFriendAdded; ret.onMessage = &friendlist_onMessage; ret.onConnectionChange = &friendlist_onConnectionChange; - ret.onAction = &friendlist_onMessage; /* Action has identical behaviour to message */ ret.onNickChange = &friendlist_onNickChange; ret.onStatusChange = &friendlist_onStatusChange; ret.onStatusMessageChange = &friendlist_onStatusMessageChange; - ret.onFileSendRequest = &friendlist_onFileSendRequest; + ret.onFileRecv = &friendlist_onFileRecv; ret.onGroupInvite = &friendlist_onGroupInvite; #ifdef AUDIO diff --git a/src/friendlist.h b/src/friendlist.h index 0969b47..b7c612b 100644 --- a/src/friendlist.h +++ b/src/friendlist.h @@ -27,20 +27,7 @@ #include "toxic.h" #include "windows.h" -#include "file_senders.h" - -struct FileReceiver { - char filename[MAX_STR_SIZE]; - int filenum; - FILE *file; - bool pending; - bool active; - uint64_t size; - uint64_t bytes_recv; - double bps; - uint64_t last_progress; /* unix-time when we last updated progress */ - uint32_t line_id; -}; +#include "file_transfers.h" struct LastOnline { uint64_t last_on; @@ -56,45 +43,47 @@ struct GroupInvite { typedef struct { char name[TOXIC_MAX_NAME_LENGTH + 1]; int namelength; - char statusmsg[TOX_MAX_STATUSMESSAGE_LENGTH + 1]; - uint16_t statusmsg_len; + char statusmsg[TOX_MAX_STATUS_MESSAGE_LENGTH + 1]; + size_t statusmsg_len; char pub_key[TOX_PUBLIC_KEY_SIZE]; - int32_t num; + uint32_t num; int chatwin; bool active; - bool online; - uint8_t is_typing; + TOX_CONNECTION connection_status; + bool is_typing; bool logging_on; /* saves preference for friend irrespective of global settings */ uint8_t status; - struct GroupInvite group_invite; + struct LastOnline last_online; - struct FileReceiver file_receiver[MAX_FILES]; - uint8_t active_file_receivers; + struct GroupInvite group_invite; + struct FileTransfer file_receiver[MAX_FILES]; + struct FileTransfer file_sender[MAX_FILES]; } ToxicFriend; typedef struct { char name[TOXIC_MAX_NAME_LENGTH + 1]; int namelength; char pub_key[TOX_PUBLIC_KEY_SIZE]; - int32_t num; + uint32_t num; bool active; uint64_t last_on; } BlockedFriend; typedef struct { int num_selected; - int max_idx; /* 1 + the index of the last friend in list */ - int num_friends; - int *index; + size_t num_friends; + size_t num_online; + size_t max_idx; /* 1 + the index of the last friend in list */ + uint32_t *index; ToxicFriend *list; } FriendsList; ToxWindow new_friendlist(void); -void disable_chatwin(int32_t f_num); +void disable_chatwin(uint32_t f_num); int get_friendnum(uint8_t *name); int load_blocklist(char *data); void kill_friendlist(void); -void friendlist_onFriendAdded(ToxWindow *self, Tox *m, int32_t num, bool sort); +void friendlist_onFriendAdded(ToxWindow *self, Tox *m, uint32_t num, bool sort); /* sorts friendlist_index first by connection status then alphabetically */ void sort_friendlist_index(void); diff --git a/src/global_commands.c b/src/global_commands.c index 6d762b9..ede6e5d 100644 --- a/src/global_commands.c +++ b/src/global_commands.c @@ -61,13 +61,14 @@ void cmd_accept(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[ return; } - const char *msg; - int32_t friendnum = tox_add_friend_norequest(m, FrndRequests.request[req].key); + TOX_ERR_FRIEND_ADD err; + uint32_t friendnum = tox_friend_add_norequest(m, FrndRequests.request[req].key, &err); - if (friendnum == -1) - msg = "Failed to add friend."; - else { - msg = "Friend request accepted."; + if (err != TOX_ERR_FRIEND_ADD_OK) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to add friend (error %d\n)", err); + return; + } else { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Friend request accepted."); on_friendadded(m, friendnum, true); } @@ -82,47 +83,55 @@ void cmd_accept(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[ FrndRequests.max_idx = i; --FrndRequests.num_requests; - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s", msg); + } -void cmd_add_helper(ToxWindow *self, Tox *m, char *id_bin, char *msg) +void cmd_add_helper(ToxWindow *self, Tox *m, const char *id_bin, const char *msg) { const char *errmsg; - int32_t f_num = tox_add_friend(m, (uint8_t *) id_bin, (uint8_t *) msg, (uint16_t) strlen(msg)); - switch (f_num) { - case TOX_FAERR_TOOLONG: + TOX_ERR_FRIEND_ADD err; + uint32_t f_num = tox_friend_add(m, (uint8_t *) id_bin, (uint8_t *) msg, strlen(msg), &err); + + switch (err) { + case TOX_ERR_FRIEND_ADD_TOO_LONG: errmsg = "Message is too long."; break; - case TOX_FAERR_NOMESSAGE: + case TOX_ERR_FRIEND_ADD_NO_MESSAGE: errmsg = "Please add a message to your request."; break; - case TOX_FAERR_OWNKEY: + case TOX_ERR_FRIEND_ADD_OWN_KEY: errmsg = "That appears to be your own ID."; break; - case TOX_FAERR_ALREADYSENT: + case TOX_ERR_FRIEND_ADD_ALREADY_SENT: errmsg = "Friend request has already been sent."; break; - case TOX_FAERR_UNKNOWN: - errmsg = "Undefined error when adding friend."; - break; - - case TOX_FAERR_BADCHECKSUM: + case TOX_ERR_FRIEND_ADD_BAD_CHECKSUM: errmsg = "Bad checksum in address."; break; - case TOX_FAERR_SETNEWNOSPAM: + case TOX_ERR_FRIEND_ADD_SET_NEW_NOSPAM: errmsg = "Nospam was different."; break; - default: + case TOX_ERR_FRIEND_ADD_MALLOC: + errmsg = "Core memory allocation failed."; + break; + + case TOX_ERR_FRIEND_ADD_OK: errmsg = "Friend request sent."; on_friendadded(m, f_num, true); break; + + case TOX_ERR_FRIEND_ADD_NULL: + /* fallthrough */ + default: + errmsg = "Faile to add friend: Unknown error."; + break; } line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, errmsg); @@ -152,21 +161,23 @@ void cmd_add(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX snprintf(msg, sizeof(msg), "%s", tmp); } else { char selfname[TOX_MAX_NAME_LENGTH]; - uint16_t n_len = tox_get_self_name(m, (uint8_t *) selfname); + tox_self_get_name(m, (uint8_t *) selfname); + + size_t n_len = tox_self_get_name_size(m); selfname[n_len] = '\0'; snprintf(msg, sizeof(msg), "Hello, my name is %s. Care to Tox?", selfname); } - char id_bin[TOX_FRIEND_ADDRESS_SIZE] = {0}; + char id_bin[TOX_ADDRESS_SIZE] = {0}; uint16_t id_len = (uint16_t) strlen(id); /* try to add tox ID */ - if (id_len == 2 * TOX_FRIEND_ADDRESS_SIZE) { + if (id_len == 2 * TOX_ADDRESS_SIZE) { size_t i; char xx[3]; uint32_t x; - for (i = 0; i < TOX_FRIEND_ADDRESS_SIZE; ++i) { + for (i = 0; i < TOX_ADDRESS_SIZE; ++i) { xx[0] = id[2 * i]; xx[1] = id[2 * i + 1]; xx[2] = '\0'; @@ -187,77 +198,72 @@ void cmd_add(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX void cmd_avatar(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) { - if (argc < 2) { - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set avatar: No file path supplied."); - return; - } + // if (argc < 2) { + // line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set avatar: No file path supplied."); + // return; + // } - /* turns the avatar off */ - if (strlen(argv[1]) < 3) { - tox_unset_avatar(m); - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "No avatar set."); - return; - } + // /* turns the avatar off */ + // if (strlen(argv[1]) < 3) { + // tox_unset_avatar(m); + // line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "No avatar set."); + // return; + // } - if (argv[1][0] != '\"') { - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Path must be enclosed in quotes."); - return; - } + // if (argv[1][0] != '\"') { + // line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Path must be enclosed in quotes."); + // return; + // } - /* remove opening and closing quotes */ - char path[MAX_STR_SIZE]; - snprintf(path, sizeof(path), "%s", &argv[1][1]); - int len = strlen(path) - 1; - path[len] = '\0'; + // /* remove opening and closing quotes */ + // char path[MAX_STR_SIZE]; + // snprintf(path, sizeof(path), "%s", &argv[1][1]); + // int len = strlen(path) - 1; + // path[len] = '\0'; - off_t sz = file_size(path); + // off_t sz = file_size(path); - if (sz <= 8) { - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set avatar: Invalid file."); - return; - } + // if (sz <= 8) { + // line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set avatar: Invalid file."); + // return; + // } - if (sz > TOX_AVATAR_MAX_DATA_LENGTH) { - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set avatar: File is too large."); - return; - } + // FILE *fp = fopen(path, "rb"); - FILE *fp = fopen(path, "rb"); + // if (fp == NULL) { + // line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set avatar: Could not open file."); + // return; + // } - if (fp == NULL) { - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set avatar: Could not open file."); - return; - } + // char PNG_signature[8] = {0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A}; - char PNG_signature[8] = {0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A}; + // if (check_file_signature(PNG_signature, sizeof(PNG_signature), fp) != 0) { + // fclose(fp); + // line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set avatar: File type not supported."); + // return; + // } - if (check_file_signature(PNG_signature, sizeof(PNG_signature), fp) != 0) { - fclose(fp); - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set avatar: File type not supported."); - return; - } + // char *avatar = malloc(sz); - char *avatar = malloc(sz); + // if (avatar == NULL) + // exit_toxic_err("Failed in cmd_avatar", FATALERR_MEMORY); - if (avatar == NULL) - exit_toxic_err("Failed in set_avatar", FATALERR_MEMORY); + // if (fread(avatar, sz, 1, fp) != 1) { + // fclose(fp); + // free(avatar); + // line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set avatar: Read fail."); + // return; + // } - if (fread(avatar, sz, 1, fp) != 1) { - fclose(fp); - free(avatar); - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set avatar: Read fail."); - return; - } + // if (tox_set_avatar(m, TOX_AVATAR_FORMAT_PNG, (const uint8_t *) avatar, (uint32_t) sz) == -1) + // line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set avatar"); - if (tox_set_avatar(m, TOX_AVATAR_FORMAT_PNG, (const uint8_t *) avatar, (uint32_t) sz) == -1) - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set avatar: Core error."); + // char filename[MAX_STR_SIZE]; + // get_file_name(filename, sizeof(filename), path); + // line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Avatar set to '%s'", filename); - char filename[MAX_STR_SIZE]; - get_file_name(filename, sizeof(filename), path); - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Avatar set to '%s'", filename); - - fclose(fp); - free(avatar); + // fclose(fp); + // free(avatar); } void cmd_clear(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) @@ -283,8 +289,26 @@ void cmd_connect(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv) } char *binary_string = hex_string_to_bin(key); - tox_bootstrap_from_address(m, ip, atoi(port), (uint8_t *) binary_string); + + TOX_ERR_BOOTSTRAP err; + tox_bootstrap(m, ip, atoi(port), (uint8_t *) binary_string, &err); free(binary_string); + + switch (err) { + case TOX_ERR_BOOTSTRAP_BAD_HOST: + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Bootstrap failed: Invalid IP."); + break; + + case TOX_ERR_BOOTSTRAP_BAD_PORT: + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Bootstrap failed: Invalid port."); + break; + + case TOX_ERR_BOOTSTRAP_NULL: + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Bootstrap failed."); + break; + default: + break; + } } void cmd_decline(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) @@ -456,8 +480,8 @@ void cmd_log(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX const char *swch = argv[1]; if (!strcmp(swch, "1") || !strcmp(swch, "on")) { - char myid[TOX_FRIEND_ADDRESS_SIZE]; - tox_get_address(m, (uint8_t *) myid); + char myid[TOX_ADDRESS_SIZE]; + tox_self_get_address(m, (uint8_t *) myid); if (self->is_chat) { Friends.list[self->num].logging_on = true; @@ -488,13 +512,13 @@ 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_FRIEND_ADDRESS_SIZE * 2 + 1] = {0}; - char address[TOX_FRIEND_ADDRESS_SIZE]; - tox_get_address(m, (uint8_t *) address); + char id[TOX_ADDRESS_SIZE * 2 + 1] = {0}; + char address[TOX_ADDRESS_SIZE]; + tox_self_get_address(m, (uint8_t *) address); size_t i; - for (i = 0; i < TOX_FRIEND_ADDRESS_SIZE; ++i) { + for (i = 0; i < TOX_ADDRESS_SIZE; ++i) { char xx[3]; snprintf(xx, sizeof(xx), "%02X", address[i] & 0xff); strcat(id, xx); @@ -511,7 +535,7 @@ void cmd_nick(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA } char nick[MAX_STR_SIZE]; - int len = 0; + size_t len = 0; if (argv[1][0] == '\"') { /* remove opening and closing quotes */ snprintf(nick, sizeof(nick), "%s", &argv[1][1]); @@ -530,11 +554,7 @@ void cmd_nick(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA len = MIN(len, TOXIC_MAX_NAME_LENGTH - 1); nick[len] = '\0'; - if (tox_set_name(m, (uint8_t *) nick, (uint16_t) len) == -1) { - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Core error setting nick."); - return; - } - + tox_self_set_name(m, (uint8_t *) nick, len, NULL); prompt_update_nick(prompt, nick); set_nick_all_groups(m, nick, len); @@ -606,31 +626,24 @@ void cmd_status(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[ goto finish; } - char status[MAX_STR_SIZE]; - snprintf(status, sizeof(status), "%s", argv[1]); - str_to_lower(status); + const char *status_str = argv[1]; + TOX_USER_STATUS status; - TOX_USERSTATUS status_kind; - - if (!strcmp(status, "online")) - status_kind = TOX_USERSTATUS_NONE; - else if (!strcmp(status, "away")) - status_kind = TOX_USERSTATUS_AWAY; - else if (!strcmp(status, "busy")) - status_kind = TOX_USERSTATUS_BUSY; + if (!strcasecmp(status_str, "online")) + status = TOX_USER_STATUS_NONE; + else if (!strcasecmp(status_str, "away")) + status = TOX_USER_STATUS_AWAY; + else if (!strcasecmp(status_str, "busy")) + status = TOX_USER_STATUS_BUSY; else { errmsg = "Invalid status. Valid statuses are: online, busy and away."; line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, errmsg); goto finish; } - if (tox_set_user_status(m, status_kind) == -1) { - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Core failed to set status\n"); - return; - } - - set_status_all_groups(m, status_kind); - prompt_update_status(prompt, status_kind); + tox_self_set_status(m, status); + prompt_update_status(prompt, status); + set_status_all_groups(m, status); if (have_note) { if (argv[2][0] != '\"') { diff --git a/src/global_commands.h b/src/global_commands.h index 6f2ff03..4615087 100644 --- a/src/global_commands.h +++ b/src/global_commands.h @@ -43,7 +43,7 @@ void cmd_quit(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE] void cmd_requests(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_status(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]); -void cmd_add_helper(ToxWindow *self, Tox *m, char *id_bin, char *msg); +void cmd_add_helper(ToxWindow *self, Tox *m, const char *id_bin, const char *msg); #ifdef AUDIO void cmd_list_devices(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]); diff --git a/src/groupchat.c b/src/groupchat.c index f024b68..93b2c66 100644 --- a/src/groupchat.c +++ b/src/groupchat.c @@ -284,7 +284,9 @@ static void groupchat_onGroupMessage(ToxWindow *self, Tox *m, int groupnum, int get_group_nick_truncate(m, nick, peernum, groupnum); char selfnick[TOX_MAX_NAME_LENGTH]; - uint16_t sn_len = tox_group_get_self_name(m, groupnum, (uint8_t *) selfnick); + tox_self_get_name(m, (uint8_t *) selfnick); + + size_t sn_len = tox_self_get_name_size(m); selfnick[sn_len] = '\0'; int nick_clr = CYAN; @@ -323,7 +325,9 @@ static void groupchat_onGroupAction(ToxWindow *self, Tox *m, int groupnum, int p get_group_nick_truncate(m, nick, peernum, groupnum); char selfnick[TOX_MAX_NAME_LENGTH]; - uint16_t n_len = tox_group_get_self_name(m, groupnum, (uint8_t *) selfnick); + tox_self_get_name(m, (uint8_t *) selfnick); + + size_t n_len = tox_self_get_name_size(m); selfnick[n_len] = '\0'; if (strcasestr(action, selfnick)) { @@ -782,10 +786,10 @@ static void groupchat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr) ctx->start = wlen < x2 ? 0 : wlen - x2 + 1; } } else { - sound_notify(self, error, 0, NULL); + sound_notify(self, notif_error, 0, NULL); } } else { - sound_notify(self, error, 0, NULL); + sound_notify(self, notif_error, 0, NULL); } } else if (key == user_settings->key_peer_list_down) { /* Scroll peerlist up and down one position */ int L = y2 - CHATBOX_HEIGHT - SDBAR_OFST; @@ -931,8 +935,8 @@ static void groupchat_onInit(ToxWindow *self, Tox *m) line_info_init(ctx->hst); if (user_settings->autolog == AUTOLOG_ON) { - char myid[TOX_FRIEND_ADDRESS_SIZE]; - tox_get_address(m, (uint8_t *) myid); + char myid[TOX_ADDRESS_SIZE]; + tox_self_get_address(m, (uint8_t *) myid); log_enable(self->name, myid, NULL, ctx->log, LOG_GROUP); } diff --git a/src/input.c b/src/input.c index 0024455..86f94f1 100644 --- a/src/input.c +++ b/src/input.c @@ -46,12 +46,12 @@ void input_new_char(ToxWindow *self, wint_t key, int x, int y, int mx_x, int mx_ /* this is the only place we need to do this check */ if (cur_len == -1) { - sound_notify(self, error, 0, NULL); + sound_notify(self, notif_error, 0, NULL); return; } if (add_char_to_buf(ctx, key) == -1) { - sound_notify(self, error, 0, NULL); + sound_notify(self, notif_error, 0, NULL); return; } @@ -67,7 +67,7 @@ static void input_backspace(ToxWindow *self, int x, int mx_x) ChatContext *ctx = self->chatwin; if (del_char_buf_bck(ctx) == -1) { - sound_notify(self, error, 0, NULL); + sound_notify(self, notif_error, 0, NULL); return; } @@ -84,7 +84,7 @@ static void input_backspace(ToxWindow *self, int x, int mx_x) static void input_delete(ToxWindow *self) { if (del_char_buf_frnt(self->chatwin) == -1) - sound_notify(self, error, 0, NULL); + sound_notify(self, notif_error, 0, NULL); } /* delete last typed word */ @@ -93,7 +93,7 @@ static void input_del_word(ToxWindow *self, int x, int mx_x) ChatContext *ctx = self->chatwin; if (del_word_buf(ctx) == -1) { - sound_notify(self, error, 0, NULL); + sound_notify(self, notif_error, 0, NULL); return; } } @@ -102,14 +102,14 @@ static void input_del_word(ToxWindow *self, int x, int mx_x) static void input_discard(ToxWindow *self) { if (discard_buf(self->chatwin) == -1) - sound_notify(self, error, 0, NULL); + sound_notify(self, notif_error, 0, NULL); } /* deletes entire line after cursor from input field and buffer */ static void input_kill(ChatContext *ctx) { if (kill_buf(ctx) == -1) - sound_notify(NULL, error, NT_ALWAYS, NULL); + sound_notify(NULL, notif_error, NT_ALWAYS, NULL); } static void input_yank(ToxWindow *self, int x, int mx_x) @@ -117,7 +117,7 @@ static void input_yank(ToxWindow *self, int x, int mx_x) ChatContext *ctx = self->chatwin; if (yank_buf(ctx) == -1) { - sound_notify(self, error, 0, NULL); + sound_notify(self, notif_error, 0, NULL); return; } @@ -264,7 +264,7 @@ bool input_handle(ToxWindow *self, wint_t key, int x, int y, int mx_x, int mx_y) break; } - /* TODO: this special case is ugly. + /* TODO: this special case is ugly. maybe convert entire function to if/else and make them all customizable keys? */ if (!match && key == user_settings->key_toggle_peerlist) { if (self->is_groupchat) { diff --git a/src/line_info.c b/src/line_info.c index 460ad78..1ea7b6e 100644 --- a/src/line_info.c +++ b/src/line_info.c @@ -155,11 +155,13 @@ void line_info_add(ToxWindow *self, const char *timestr, const char *name1, cons /* for type-specific formatting in print function */ switch (type) { case IN_ACTION: + /* fallthrough */ case OUT_ACTION: len += strlen(user_settings->line_normal) + 2; break; case IN_MSG: + /* fallthrough */ case OUT_MSG: len += strlen(user_settings->line_normal) + 3; break; @@ -304,7 +306,9 @@ void line_info_print(ToxWindow *self) switch (type) { case OUT_MSG: + /* fallthrough */ case OUT_MSG_READ: + /* fallthrough */ case IN_MSG: case IN_PRVT_MSG: case OUT_PRVT_MSG: @@ -349,7 +353,9 @@ void line_info_print(ToxWindow *self) break; case OUT_ACTION_READ: + /* fallthrough */ case OUT_ACTION: + /* fallthrough */ case IN_ACTION: wattron(win, COLOR_PAIR(BLUE)); wprintw(win, "%s ", line->timestr); @@ -494,14 +500,14 @@ static void line_info_scroll_up(struct history *hst) { if (hst->line_start->prev) hst->line_start = hst->line_start->prev; - else sound_notify(NULL, error, NT_ALWAYS, NULL); + else sound_notify(NULL, notif_error, NT_ALWAYS, NULL); } static void line_info_scroll_down(struct history *hst) { if (hst->line_start->next) hst->line_start = hst->line_start->next; - else sound_notify(NULL, error, NT_ALWAYS, NULL); + else sound_notify(NULL, notif_error, NT_ALWAYS, NULL); } static void line_info_page_up(ToxWindow *self, struct history *hst) diff --git a/src/message_queue.c b/src/message_queue.c index 845b9da..70ccadb 100644 --- a/src/message_queue.c +++ b/src/message_queue.c @@ -42,7 +42,7 @@ void cqueue_cleanup(struct chat_queue *q) free(q); } -void cqueue_add(struct chat_queue *q, const char *msg, int len, uint8_t type, uint32_t line_id) +void cqueue_add(struct chat_queue *q, const char *msg, size_t len, uint8_t type, uint32_t line_id) { struct cqueue_msg *new_m = malloc(sizeof(struct cqueue_msg)); @@ -103,7 +103,9 @@ void cqueue_remove(ToxWindow *self, Tox *m, uint32_t receipt) } char selfname[TOX_MAX_NAME_LENGTH]; - uint16_t len = tox_get_self_name(m, (uint8_t *) selfname); + tox_self_get_name(m, (uint8_t *) selfname); + + size_t len = tox_self_get_name_size(m); selfname[len] = '\0'; write_to_log(msg->message, selfname, self->chatwin->log, msg->type == OUT_ACTION); @@ -145,10 +147,8 @@ void cqueue_try_send(ToxWindow *self, Tox *m) uint32_t receipt = 0; - if (msg->type == OUT_MSG) - receipt = tox_send_message(m, self->num, (uint8_t *) msg->message, msg->len); - else - receipt = tox_send_action(m, self->num, (uint8_t *) msg->message, msg->len); + TOX_MESSAGE_TYPE type = msg->type == OUT_MSG ? TOX_MESSAGE_TYPE_NORMAL : TOX_MESSAGE_TYPE_ACTION; + receipt = tox_friend_send_message(m, self->num, type, (uint8_t *) msg->message, msg->len, NULL); msg->last_send_try = curtime; msg->receipt = receipt; diff --git a/src/message_queue.h b/src/message_queue.h index b82cec3..df0317e 100644 --- a/src/message_queue.h +++ b/src/message_queue.h @@ -25,7 +25,7 @@ struct cqueue_msg { char message[MAX_STR_SIZE]; - int len; + size_t len; int line_id; uint8_t type; uint32_t receipt; @@ -40,7 +40,7 @@ struct chat_queue { }; void cqueue_cleanup(struct chat_queue *q); -void cqueue_add(struct chat_queue *q, const char *msg, int len, uint8_t type, uint32_t line_id); +void cqueue_add(struct chat_queue *q, const char *msg, size_t len, uint8_t type, uint32_t line_id); /* Tries to send the oldest unsent message in queue. */ void cqueue_try_send(ToxWindow *self, Tox *m); @@ -48,4 +48,4 @@ void cqueue_try_send(ToxWindow *self, Tox *m); /* removes message with matching receipt from queue, writes to log and updates line to show the message was received. */ void cqueue_remove(ToxWindow *self, Tox *m, uint32_t receipt); -#endif /* #define MESSAGE_QUEUE_H */ \ No newline at end of file +#endif /* #define MESSAGE_QUEUE_H */ diff --git a/src/misc_tools.c b/src/misc_tools.c index 736e495..3990327 100644 --- a/src/misc_tools.c +++ b/src/misc_tools.c @@ -32,7 +32,7 @@ #include "windows.h" #include "misc_tools.h" #include "settings.h" -#include "file_senders.h" +#include "file_transfers.h" extern ToxWindow *prompt; extern struct user_settings *user_settings; @@ -212,9 +212,9 @@ int valid_nick(const char *nick) } /* Converts all newline/tab chars to spaces (use for strings that should be contained to a single line) */ -void filter_str(char *str, int len) +void filter_str(char *str, size_t len) { - int i; + size_t i; for (i = 0; i < len; ++i) { if (str[i] == '\n' || str[i] == '\r' || str[i] == '\t' || str[i] == '\v') @@ -222,17 +222,19 @@ void filter_str(char *str, int len) } } -/* gets base file name from path or original file name if no path is supplied */ -void get_file_name(char *namebuf, int bufsize, const char *pathname) +/* gets base file name from path or original file name if no path is supplied. + * Returns the file name length + */ +size_t get_file_name(char *namebuf, size_t bufsize, const char *pathname) { - int idx = strlen(pathname) - 1; + int len = strlen(pathname) - 1; char *path = strdup(pathname); if (path == NULL) exit_toxic_err("failed in get_file_name", FATALERR_MEMORY); - while (idx >= 0 && pathname[idx] == '/') - path[idx--] = '\0'; + while (len >= 0 && pathname[len] == '/') + path[len--] = '\0'; char *finalname = strdup(path); @@ -249,6 +251,8 @@ void get_file_name(char *namebuf, int bufsize, const char *pathname) snprintf(namebuf, bufsize, "%s", finalname); free(finalname); free(path); + + return strlen(namebuf); } /* converts str to all lowercase */ @@ -263,13 +267,15 @@ void str_to_lower(char *str) /* puts friendnum's nick in buf, truncating at TOXIC_MAX_NAME_LENGTH if necessary. if toxcore API call fails, put UNKNOWN_NAME in buf Returns nick len */ -int get_nick_truncate(Tox *m, char *buf, int friendnum) +size_t get_nick_truncate(Tox *m, char *buf, uint32_t friendnum) { - int len = tox_get_name(m, friendnum, (uint8_t *) buf); + size_t len = tox_friend_get_name_size(m, friendnum, NULL); - if (len == -1) { + if (len == 0) { strcpy(buf, UNKNOWN_NAME); len = strlen(UNKNOWN_NAME); + } else { + tox_friend_get_name(m, friendnum, (uint8_t *) buf, NULL); } len = MIN(len, TOXIC_MAX_NAME_LENGTH - 1); @@ -297,7 +303,7 @@ int get_group_nick_truncate(Tox *m, char *buf, int peernum, int groupnum) /* copies data to msg buffer. returns length of msg. returns 0 and nulls msg if length is too big for buffer size */ -uint16_t copy_tox_str(char *msg, size_t size, const char *data, uint16_t length) +size_t copy_tox_str(char *msg, size_t size, const char *data, size_t length) { if (length > size - 1) { msg[0] = '\0'; @@ -366,13 +372,13 @@ bool file_exists(const char *path) return stat(path, &s) == 0; } -/* returns file size or -1 on error */ +/* returns file size. If file doesn't exist returns 0. */ off_t file_size(const char *path) { struct stat st; if (stat(path, &st) == -1) - return -1; + return 0; return st.st_size; } diff --git a/src/misc_tools.h b/src/misc_tools.h index 970faaa..3a5ca09 100644 --- a/src/misc_tools.h +++ b/src/misc_tools.h @@ -92,17 +92,17 @@ int qsort_strcasecmp_hlpr(const void *str1, const void *str2); int valid_nick(const char *nick); /* Converts all newline/tab chars to spaces (use for strings that should be contained to a single line) */ -void filter_str(char *str, int len); +void filter_str(char *str, size_t len); /* gets base file name from path or original file name if no path is supplied */ -void get_file_name(char *namebuf, int bufsize, const char *pathname); +size_t get_file_name(char *namebuf, size_t bufsize, const char *pathname); /* converts str to all lowercase */ void str_to_lower(char *str); /* puts friendnum's nick in buf, truncating at TOXIC_MAX_NAME_LENGTH if necessary. Returns nick len on success, -1 on failure */ -int get_nick_truncate(Tox *m, char *buf, int friendnum); +size_t get_nick_truncate(Tox *m, char *buf, uint32_t friendnum); /* same as get_nick_truncate but for groupchats */ int get_group_nick_truncate(Tox *m, char *buf, int peernum, int groupnum); @@ -110,7 +110,7 @@ int get_group_nick_truncate(Tox *m, char *buf, int peernum, int groupnum); /* copies data to msg buffer. returns length of msg. returns 0 and nulls msg if length is too big for buffer size */ -uint16_t copy_tox_str(char *msg, size_t size, const char *data, uint16_t length); +size_t copy_tox_str(char *msg, size_t size, const char *data, size_t length); /* returns index of the first instance of ch in s starting at idx. returns length of s if char not found */ @@ -126,7 +126,7 @@ void bytes_convert_str(char *buf, int size, uint64_t bytes); /* checks if a file exists. Returns true or false */ bool file_exists(const char *path); -/* returns file size or -1 on error */ +/* returns file size. If file doesn't exist returns 0. */ off_t file_size(const char *path); /* compares the first size bytes of fp and signature. diff --git a/src/notify.c b/src/notify.c index 2346991..8560659 100644 --- a/src/notify.c +++ b/src/notify.c @@ -1,5 +1,5 @@ /* notify.c - * + * * * Copyright (C) 2014 Toxic All Rights Reserved. * @@ -67,12 +67,12 @@ extern struct user_settings *user_settings; struct Control { time_t cooldown; time_t notif_timeout; - + #if defined(SOUND_NOTIFY) || defined(BOX_NOTIFY) pthread_mutex_t poll_mutex[1]; bool poll_active; #endif - + #ifdef SOUND_NOTIFY uint32_t device_idx; /* index of output device */ char* sounds[SOUNDS_SIZE]; @@ -107,11 +107,11 @@ static void tab_notify(ToxWindow *self, uint64_t flags) if (self == NULL) return; - if (flags & NT_WNDALERT_0) + if (flags & NT_WNDALERT_0) self->alert = WINDOW_ALERT_0; - else if ( (flags & NT_WNDALERT_1) && (!self->alert || self->alert > WINDOW_ALERT_0) ) + else if ( (flags & NT_WNDALERT_1) && (!self->alert || self->alert > WINDOW_ALERT_0) ) self->alert = WINDOW_ALERT_1; - else if ( (flags & NT_WNDALERT_2) && (!self->alert || self->alert > WINDOW_ALERT_1) ) + else if ( (flags & NT_WNDALERT_2) && (!self->alert || self->alert > WINDOW_ALERT_1) ) self->alert = WINDOW_ALERT_2; } @@ -154,14 +154,14 @@ static bool device_opened = false; time_t last_opened_update = 0; bool m_open_device() -{ +{ last_opened_update = get_unix_time(); - + if (device_opened) return true; - + /* Blah error check */ open_primary_device(output, &Control.device_idx, 48000, 20, 1); - + return (device_opened = true); } @@ -194,9 +194,9 @@ void graceful_clear() *actives[i].id_indicator = -1; /* reset indicator value */ if ( actives[i].looping ) { - stop_sound(i); + stop_sound(i); } else { - if (!is_playing(actives[i].source)) + if (!is_playing(actives[i].source)) memset(&actives[i], 0, sizeof(struct _ActiveNotifications)); else break; } @@ -217,17 +217,17 @@ void* do_playing(void* _p) { (void)_p; int i; - + bool has_looping = false; - + while(Control.poll_active) { control_lock(); - - + + for (i = 0; i < ACTIVE_NOTIFS_MAX; i ++) { - + if (actives[i].looping) has_looping = true; - + if (actives[i].active && !actives[i].looping #ifdef BOX_NOTIFY && !actives[i].box @@ -237,7 +237,7 @@ void* do_playing(void* _p) *actives[i].id_indicator = -1; /* reset indicator value */ if (!is_playing(actives[i].source)) { - /* Close */ + /* Close */ alSourceStop(actives[i].source); alDeleteSources(1, &actives[i].source); alDeleteBuffers(1, &actives[i].buffer); @@ -263,14 +263,14 @@ void* do_playing(void* _p) } #endif } - + /* device is opened and no activity in under DEVICE_COOLDOWN time, close device*/ - if (device_opened && !has_looping && + if (device_opened && !has_looping && (get_unix_time() - last_opened_update) > DEVICE_COOLDOWN) { m_close_device(); } has_looping = false; - + control_unlock(); usleep(10000); } @@ -278,20 +278,20 @@ void* do_playing(void* _p) } int play_source(uint32_t source, uint32_t buffer, bool looping) -{ +{ int i = 0; for (; i < ACTIVE_NOTIFS_MAX && actives[i].active; i ++); if ( i == ACTIVE_NOTIFS_MAX ) { return -1; /* Full */ } - + alSourcePlay(source); - + actives[i].active = 1; actives[i].source = source; actives[i].buffer = buffer; actives[i].looping = looping; - + return i; } @@ -324,20 +324,20 @@ void graceful_clear() { int i; control_lock(); - + for (i = 0; i < ACTIVE_NOTIFS_MAX; i ++) { if (actives[i].box) { GError* ignore; notify_notification_close(actives[i].box, &ignore); actives[i].box = NULL; } - + if (actives[i].id_indicator) *actives[i].id_indicator = -1; /* reset indicator value */ memset(&actives[i], 0, sizeof(struct _ActiveNotifications)); - } - + } + control_unlock(); } #endif @@ -356,7 +356,7 @@ int init_notify(int login_cooldown, int notification_timeout) #ifdef SOUND_NOTIFY alutInitWithoutContext(NULL, NULL); #endif /* SOUND_NOTIFY */ - + #if defined(SOUND_NOTIFY) || defined(BOX_NOTIFY) if (pthread_mutex_init(Control.poll_mutex, NULL) != 0) return -1; @@ -371,8 +371,8 @@ int init_notify(int login_cooldown, int notification_timeout) Control.poll_active = 1; #endif Control.cooldown = get_unix_time() + login_cooldown; - - + + #ifdef BOX_NOTIFY notify_init("Toxic"); #endif @@ -381,11 +381,11 @@ int init_notify(int login_cooldown, int notification_timeout) } void terminate_notify() -{ -#if defined(SOUND_NOTIFY) || defined(BOX_NOTIFY) - if ( !Control.poll_active ) return; +{ +#if defined(SOUND_NOTIFY) || defined(BOX_NOTIFY) + if ( !Control.poll_active ) return; Control.poll_active = 0; - + graceful_clear(); #endif @@ -394,7 +394,7 @@ void terminate_notify() for (; i < SOUNDS_SIZE; i ++) free(Control.sounds[i]); alutExit(); #endif /* SOUND_NOTIFY */ - + #ifdef BOX_NOTIFY notify_uninit(); #endif @@ -404,7 +404,7 @@ void terminate_notify() int set_sound(Notification sound, const char* value) { if (sound == silent) return 0; - + free(Control.sounds[sound]); size_t len = strlen(value) + 1; @@ -416,18 +416,18 @@ int set_sound(Notification sound, const char* value) } int play_sound_internal(Notification what, bool loop) -{ +{ uint32_t source; uint32_t buffer; - + m_open_device(); - + alGenSources(1, &source); alGenBuffers(1, &buffer); buffer = alutCreateBufferFromFile(Control.sounds[what]); alSourcei(source, AL_BUFFER, buffer); alSourcei(source, AL_LOOPING, loop); - + int rc = play_source(source, buffer, loop); if (rc < 0) { alSourceStop(source); @@ -435,7 +435,7 @@ int play_sound_internal(Notification what, bool loop) alDeleteBuffers(1,&buffer); return -1; } - + return rc; } @@ -464,7 +464,7 @@ void stop_sound(int id) notify_notification_close(actives[id].box, &ignore); } #endif - if (actives[id].id_indicator) + if (actives[id].id_indicator) *actives[id].id_indicator = -1; // alSourcei(actives[id].source, AL_LOOPING, false); alSourceStop(actives[id].source); @@ -484,11 +484,11 @@ static int m_play_sound(Notification notif, uint64_t flags) beep(); return -1; -#endif /* SOUND_NOTIFY */ +#endif /* SOUND_NOTIFY */ } #ifdef BOX_NOTIFY -void m_notify_action(NotifyNotification *box, char *action, void* data) +void m_notify_action(NotifyNotification *box, char *action, void* data) { } #endif @@ -503,7 +503,7 @@ int sound_notify(ToxWindow* self, Notification notif, uint64_t flags, int* id_in int id = -1; control_lock(); - if (self && (!self->stb || self->stb->status != TOX_USERSTATUS_BUSY) && user_settings->alerts == ALERTS_ENABLED) + if (self && (!self->stb || self->stb->status != TOX_USER_STATUS_BUSY) && user_settings->alerts == ALERTS_ENABLED) id = m_play_sound(notif, flags); else if (flags & NT_ALWAYS) id = m_play_sound(notif, flags); @@ -520,7 +520,7 @@ int sound_notify(ToxWindow* self, Notification notif, uint64_t flags, int* id_in #endif - if ( id_indicator && id != -1 ) { + if ( id_indicator && id != -1 ) { actives[id].id_indicator = id_indicator; *id_indicator = id; } @@ -533,46 +533,46 @@ int sound_notify(ToxWindow* self, Notification notif, uint64_t flags, int* id_in int sound_notify2(ToxWindow* self, Notification notif, uint64_t flags, int id) { tab_notify(self, flags); - + if (notifications_are_disabled(flags)) return -1; - + if (id < 0 || id >= ACTIVE_NOTIFS_MAX) return -1; -#ifdef SOUND_NOTIFY +#ifdef SOUND_NOTIFY control_lock(); - + if (!actives[id].active || !Control.sounds[notif]) { control_unlock(); return -1; } - + m_open_device(); - + alSourceStop(actives[id].source); alDeleteSources(1, &actives[id].source); alDeleteBuffers(1,&actives[id].buffer); - - + + alGenSources(1, &actives[id].source); alGenBuffers(1, &actives[id].buffer); actives[id].buffer = alutCreateBufferFromFile(Control.sounds[notif]); alSourcei(actives[id].source, AL_BUFFER, actives[id].buffer); alSourcei(actives[id].source, AL_LOOPING, flags & NT_LOOP); - + alSourcePlay(actives[id].source); - + control_unlock(); - + return id; #else if (notif != silent) beep(); - + return 0; #endif /* SOUND_NOTIFY */ } -int box_notify(ToxWindow* self, Notification notif, uint64_t flags, int* id_indicator, char* title, const char* format, ...) +int box_notify(ToxWindow* self, Notification notif, uint64_t flags, int* id_indicator, const char* title, const char* format, ...) { if (notifications_are_disabled(flags)) { tab_notify(self, flags); @@ -594,7 +594,7 @@ int box_notify(ToxWindow* self, Notification notif, uint64_t flags, int* id_indi return -1; /* Full */ } - actives[id].active = 1; + actives[id].active = 1; actives[id].id_indicator = id_indicator; if (id_indicator) *id_indicator = id; } @@ -607,13 +607,13 @@ int box_notify(ToxWindow* self, Notification notif, uint64_t flags, int* id_indi vsnprintf (actives[id].messages[0], MAX_BOX_MSG_LEN, format, __ARGS__); va_end (__ARGS__); - if (strlen(actives[id].messages[0]) > MAX_BOX_MSG_LEN - 3) + if (strlen(actives[id].messages[0]) > MAX_BOX_MSG_LEN - 3) strcpy(actives[id].messages[0] + MAX_BOX_MSG_LEN - 3, "..."); actives[id].box = notify_notification_new(actives[id].title, actives[id].messages[0], NULL); actives[id].size++; actives[id].n_timeout = get_unix_time() + Control.notif_timeout / 1000; - + notify_notification_set_timeout(actives[id].box, Control.notif_timeout); notify_notification_set_app_name(actives[id].box, "toxic"); /*notify_notification_add_action(actives[id].box, "lel", "default", m_notify_action, self, NULL);*/ @@ -687,7 +687,7 @@ int box_silent_notify(ToxWindow* self, uint64_t flags, int* id_indicator, const control_lock(); - int id; + int id; for (id = 0; id < ACTIVE_NOTIFS_MAX && actives[id].active; id ++); if ( id == ACTIVE_NOTIFS_MAX ) { control_unlock(); @@ -706,7 +706,7 @@ int box_silent_notify(ToxWindow* self, uint64_t flags, int* id_indicator, const vsnprintf (actives[id].messages[0], MAX_BOX_MSG_LEN, format, __ARGS__); va_end (__ARGS__); - if (strlen(actives[id].messages[0]) > MAX_BOX_MSG_LEN - 3) + if (strlen(actives[id].messages[0]) > MAX_BOX_MSG_LEN - 3) strcpy(actives[id].messages[0] + MAX_BOX_MSG_LEN - 3, "..."); actives[id].active = 1; diff --git a/src/notify.h b/src/notify.h index d8a276c..6fd81f0 100644 --- a/src/notify.h +++ b/src/notify.h @@ -1,5 +1,5 @@ /* notify.h - * + * * * Copyright (C) 2014 Toxic All Rights Reserved. * @@ -29,7 +29,7 @@ typedef enum _Notification { silent = -1, - error, + notif_error, self_log_in, self_log_out, user_log_in, @@ -49,14 +49,14 @@ typedef enum _Flags { NT_LOOP = 1 << 2, /* Loop sound. If this setting active, notify() will return id of the sound * so it could be stopped. It will return 0 if error or NT_NATIVE flag is set and play \a instead */ - NT_RESTOL = 1 << 3, /* Respect tolerance. Usually used to stop flood at toxic startup + NT_RESTOL = 1 << 3, /* Respect tolerance. Usually used to stop flood at toxic startup * Only works if login_cooldown is true when calling init_notify() */ NT_NOTIFWND = 1 << 4, /* Pop notify window. NOTE: only works(/WILL WORK) if libnotify is present */ NT_WNDALERT_0 = 1 << 5, /* Alert toxic */ NT_WNDALERT_1 = 1 << 6, /* Alert toxic */ NT_WNDALERT_2 = 1 << 7, /* Alert toxic */ - + NT_ALWAYS = 1 << 8, /* Force sound to play */ } Flags; @@ -68,7 +68,7 @@ int sound_notify2(ToxWindow* self, Notification notif, uint64_t flags, int id); void stop_sound(int id); -int box_notify(ToxWindow* self, Notification notif, uint64_t flags, int* id_indicator, char* title, const char* format, ...); +int box_notify(ToxWindow* self, Notification notif, uint64_t flags, int* id_indicator, const char* title, const char* format, ...); int box_notify2(ToxWindow* self, Notification notif, uint64_t flags, int id, const char* format, ...); int box_silent_notify(ToxWindow* self, uint64_t flags, int* id_indicator, const char* title, const char* format, ...); int box_silent_notify2(ToxWindow* self, uint64_t flags, int id, const char* format, ...); diff --git a/src/prompt.c b/src/prompt.c index e007030..26e55b3 100644 --- a/src/prompt.c +++ b/src/prompt.c @@ -102,6 +102,13 @@ void kill_prompt_window(ToxWindow *self) del_window(self); } +/* callback: Updates own connection status in prompt statusbar */ +void prompt_onSelfConnectionChange(Tox *m, TOX_CONNECTION connection_status, void *userdata) +{ + StatusBar *statusbar = prompt->stb; + statusbar->connection = connection_status; +} + /* Updates own nick in prompt statusbar */ void prompt_update_nick(ToxWindow *prompt, const char *nick) { @@ -115,25 +122,23 @@ void prompt_update_statusmessage(ToxWindow *prompt, Tox *m, const char *statusms { StatusBar *statusbar = prompt->stb; snprintf(statusbar->statusmsg, sizeof(statusbar->statusmsg), "%s", statusmsg); - int len = strlen(statusbar->statusmsg); + size_t len = strlen(statusbar->statusmsg); statusbar->statusmsg_len = len; - tox_set_status_message(m, (uint8_t *) statusmsg, (uint64_t) len); + + TOX_ERR_SET_INFO err; + tox_self_set_status_message(m, (uint8_t *) statusmsg, len, &err); + + if (err != TOX_ERR_SET_INFO_OK) + line_info_add(prompt, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set note (error %d)\n", err); } /* Updates own status in prompt statusbar */ -void prompt_update_status(ToxWindow *prompt, uint8_t status) +void prompt_update_status(ToxWindow *prompt, TOX_USER_STATUS status) { StatusBar *statusbar = prompt->stb; statusbar->status = status; } -/* Updates own connection status in prompt statusbar */ -void prompt_update_connectionstatus(ToxWindow *prompt, bool is_connected) -{ - StatusBar *statusbar = prompt->stb; - statusbar->is_online = is_connected; -} - /* Adds friend request to pending friend requests. Returns request number on success, -1 if queue is full. */ static int add_friend_request(const char *public_key, const char *data) @@ -210,10 +215,10 @@ static void prompt_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr) ctx->start = wlen < x2 ? 0 : wlen - x2 + 1; } } else { - sound_notify(self, error, 0, NULL); + sound_notify(self, notif_error, 0, NULL); } } else { - sound_notify(self, error, 0, NULL); + sound_notify(self, notif_error, 0, NULL); } } else if (key == '\n') { rm_trailing_spaces_buf(ctx); @@ -254,30 +259,23 @@ static void prompt_onDraw(ToxWindow *self, Tox *m) mvwhline(statusbar->topline, 1, 0, ACS_HLINE, x2); wmove(statusbar->topline, 0, 0); - if (statusbar->is_online) { - int colour = WHITE; - const char *status_text = "Unknown"; + if (statusbar->connection != TOX_CONNECTION_NONE) { + int colour = MAGENTA; + const char *status_text = "ERROR"; switch (statusbar->status) { - case TOX_USERSTATUS_NONE: + case TOX_USER_STATUS_NONE: status_text = "Online"; colour = GREEN; break; - - case TOX_USERSTATUS_AWAY: + case TOX_USER_STATUS_AWAY: status_text = "Away"; colour = YELLOW; break; - - case TOX_USERSTATUS_BUSY: + case TOX_USER_STATUS_BUSY: status_text = "Busy"; colour = RED; break; - - case TOX_USERSTATUS_INVALID: - status_text = "ERROR"; - colour = MAGENTA; - break; } wattron(statusbar->topline, COLOR_PAIR(colour) | A_BOLD); @@ -296,10 +294,10 @@ static void prompt_onDraw(ToxWindow *self, Tox *m) /* Reset statusbar->statusmsg on window resize */ if (x2 != self->x) { - char statusmsg[TOX_MAX_STATUSMESSAGE_LENGTH] = {0}; + char statusmsg[TOX_MAX_STATUS_MESSAGE_LENGTH]; pthread_mutex_lock(&Winthread.lock); - tox_get_self_status_message(m, (uint8_t *) statusmsg, TOX_MAX_STATUSMESSAGE_LENGTH); + tox_self_get_status_message(m, (uint8_t *) statusmsg); pthread_mutex_unlock(&Winthread.lock); snprintf(statusbar->statusmsg, sizeof(statusbar->statusmsg), "%s", statusmsg); @@ -335,11 +333,8 @@ static void prompt_onDraw(ToxWindow *self, Tox *m) help_onDraw(self); } -static void prompt_onConnectionChange(ToxWindow *self, Tox *m, int32_t friendnum , uint8_t status) +static void prompt_onConnectionChange(ToxWindow *self, Tox *m, uint32_t friendnum , TOX_CONNECTION connection_status) { - if (friendnum < 0) - return; - ChatContext *ctx = self->chatwin; char nick[TOX_MAX_NAME_LENGTH] = {0}; /* stop removing this initiation */ @@ -352,7 +347,7 @@ static void prompt_onConnectionChange(ToxWindow *self, Tox *m, int32_t friendnum get_time_str(timefrmt, sizeof(timefrmt)); const char *msg; - if (status == 1) { + if (connection_status != TOX_CONNECTION_NONE) { msg = "has come online"; line_info_add(self, timefrmt, nick, NULL, CONNECTION, 0, GREEN, msg); write_to_log(msg, nick, ctx->log, true); @@ -377,7 +372,7 @@ static void prompt_onConnectionChange(ToxWindow *self, Tox *m, int32_t friendnum } } -static void prompt_onFriendRequest(ToxWindow *self, Tox *m, const char *key, const char *data, uint16_t length) +static void prompt_onFriendRequest(ToxWindow *self, Tox *m, const char *key, const char *data, size_t length) { ChatContext *ctx = self->chatwin; @@ -407,15 +402,19 @@ void prompt_init_statusbar(ToxWindow *self, Tox *m) /* Init statusbar info */ StatusBar *statusbar = self->stb; - statusbar->status = TOX_USERSTATUS_NONE; - statusbar->is_online = false; + statusbar->status = TOX_USER_STATUS_NONE; + statusbar->connection = TOX_CONNECTION_NONE; char nick[TOX_MAX_NAME_LENGTH]; - char statusmsg[MAX_STR_SIZE]; + char statusmsg[TOX_MAX_STATUS_MESSAGE_LENGTH]; - uint16_t n_len = tox_get_self_name(m, (uint8_t *) nick); - uint16_t s_len = tox_get_self_status_message(m, (uint8_t *) statusmsg, MAX_STR_SIZE); - uint8_t status = tox_get_self_user_status(m); + size_t n_len = tox_self_get_name_size(m); + tox_self_get_name(m, (uint8_t *) nick); + + size_t s_len = tox_self_get_status_message_size(m); + tox_self_get_status_message(m, (uint8_t *) statusmsg); + + TOX_USER_STATUS status = tox_self_get_status(m); nick[n_len] = '\0'; statusmsg[s_len] = '\0'; @@ -469,8 +468,8 @@ static void prompt_onInit(ToxWindow *self, Tox *m) line_info_init(ctx->hst); if (user_settings->autolog == AUTOLOG_ON) { - char myid[TOX_FRIEND_ADDRESS_SIZE]; - tox_get_address(m, (uint8_t *) myid); + char myid[TOX_ADDRESS_SIZE]; + tox_self_get_address(m, (uint8_t *) myid); log_enable(self->name, myid, NULL, ctx->log, LOG_PROMPT); } diff --git a/src/prompt.h b/src/prompt.h index e6eb0cc..4842f6c 100644 --- a/src/prompt.h +++ b/src/prompt.h @@ -45,8 +45,11 @@ void prep_prompt_win(void); void prompt_init_statusbar(ToxWindow *self, Tox *m); void prompt_update_nick(ToxWindow *prompt, const char *nick); void prompt_update_statusmessage(ToxWindow *prompt, Tox *m, const char *statusmsg); -void prompt_update_status(ToxWindow *prompt, uint8_t status); +void prompt_update_status(ToxWindow *prompt, TOX_USER_STATUS status); void prompt_update_connectionstatus(ToxWindow *prompt, bool is_connected); void kill_prompt_window(ToxWindow *self); +/* callback: Updates own connection status in prompt statusbar */ +void prompt_onSelfConnectionChange(Tox *m, TOX_CONNECTION connection_status, void *userdata); + #endif /* end of include guard: PROMPT_H */ diff --git a/src/settings.c b/src/settings.c index 9df7c60..5c98d48 100644 --- a/src/settings.c +++ b/src/settings.c @@ -199,7 +199,7 @@ static void audio_defaults(struct user_settings* settings) #ifdef SOUND_NOTIFY static const struct sound_strings { const char* self; - const char* error; + const char* notif_error; const char* self_log_in; const char* self_log_out; const char* user_log_in; @@ -211,7 +211,7 @@ static const struct sound_strings { const char* transfer_completed; } sound_strings = { "sounds", - "error", + "notif_error", "self_log_in", "self_log_out", "user_log_in", @@ -406,10 +406,10 @@ int settings_load(struct user_settings *s, const char *patharg) #ifdef SOUND_NOTIFY if ((setting = config_lookup(cfg, sound_strings.self)) != NULL) { - if ( (config_setting_lookup_string(setting, sound_strings.error, &str) != CONFIG_TRUE) || - !set_sound(error, str) ) { + if ( (config_setting_lookup_string(setting, sound_strings.notif_error, &str) != CONFIG_TRUE) || + !set_sound(notif_error, str) ) { if (str && strcasecmp(str, NO_SOUND) != 0) - set_sound(error, PACKAGE_DATADIR "/sounds/ToxicError.wav"); + set_sound(notif_error, PACKAGE_DATADIR "/sounds/ToxicError.wav"); } if ( !config_setting_lookup_string(setting, sound_strings.user_log_in, &str) || @@ -455,7 +455,7 @@ int settings_load(struct user_settings *s, const char *patharg) } } else { - set_sound(error, PACKAGE_DATADIR "/sounds/ToxicError.wav"); + set_sound(notif_error, PACKAGE_DATADIR "/sounds/ToxicError.wav"); set_sound(user_log_in, PACKAGE_DATADIR "/sounds/ToxicContactOnline.wav"); set_sound(user_log_out, PACKAGE_DATADIR "/sounds/ToxicContactOffline.wav"); set_sound(call_incoming, PACKAGE_DATADIR "/sounds/ToxicIncomingCall.wav"); diff --git a/src/settings.h b/src/settings.h index 2e02a01..1e51c7b 100644 --- a/src/settings.h +++ b/src/settings.h @@ -67,7 +67,7 @@ struct user_settings { int key_toggle_peerlist; int mplex_away; /* boolean (1 for reaction to terminal attach/detach) */ - char mplex_away_note [TOX_MAX_STATUSMESSAGE_LENGTH]; + char mplex_away_note [TOX_MAX_STATUS_MESSAGE_LENGTH]; #ifdef AUDIO int audio_in_dev; diff --git a/src/term_mplex.c b/src/term_mplex.c index f150938..0036b73 100644 --- a/src/term_mplex.c +++ b/src/term_mplex.c @@ -70,8 +70,8 @@ static char buffer [BUFFER_SIZE]; static bool auto_away_active = false; static mplex_status mplex = MPLEX_NONE; -static TOX_USERSTATUS prev_status = TOX_USERSTATUS_NONE; -static char prev_note [TOX_MAX_STATUSMESSAGE_LENGTH] = ""; +static TOX_USER_STATUS prev_status = TOX_USER_STATUS_NONE; +static char prev_note [TOX_MAX_STATUS_MESSAGE_LENGTH] = ""; /* mutex for access to status data, for sync between: - user command /status from ncurses thread @@ -314,7 +314,7 @@ static int mplex_is_detached () static void mplex_timer_handler (Tox *m) { - TOX_USERSTATUS current_status, new_status; + TOX_USER_STATUS current_status, new_status; const char *new_note; if (mplex == MPLEX_NONE) @@ -323,23 +323,23 @@ static void mplex_timer_handler (Tox *m) int detached = mplex_is_detached (); pthread_mutex_lock (&Winthread.lock); - current_status = tox_get_self_user_status (m); + current_status = tox_self_get_status (m); pthread_mutex_unlock (&Winthread.lock); - if (auto_away_active && current_status == TOX_USERSTATUS_AWAY && !detached) + if (auto_away_active && current_status == TOX_USER_STATUS_AWAY && !detached) { auto_away_active = false; new_status = prev_status; new_note = prev_note; } else - if (current_status == TOX_USERSTATUS_NONE && detached) + if (current_status == TOX_USER_STATUS_NONE && detached) { auto_away_active = true; prev_status = current_status; - new_status = TOX_USERSTATUS_AWAY; + new_status = TOX_USER_STATUS_AWAY; pthread_mutex_lock (&Winthread.lock); - tox_get_self_status_message (m, (uint8_t*) prev_note, sizeof (prev_note)); + tox_self_get_status_message (m, (uint8_t*) prev_note); pthread_mutex_unlock (&Winthread.lock); new_note = user_settings->mplex_away_note; } @@ -348,8 +348,8 @@ static void mplex_timer_handler (Tox *m) char argv[3][MAX_STR_SIZE]; strcpy (argv[0], "/status"); - strcpy (argv[1], (new_status == TOX_USERSTATUS_AWAY ? "away" : - new_status == TOX_USERSTATUS_BUSY ? "busy" : "online")); + strcpy (argv[1], (new_status == TOX_USER_STATUS_AWAY ? "away" : + new_status == TOX_USER_STATUS_BUSY ? "busy" : "online")); argv[2][0] = '\"'; strcpy (argv[2] + 1, new_note); strcat (argv[2], "\""); diff --git a/src/toxic.c b/src/toxic.c index 44c282a..a6abfd6 100644 --- a/src/toxic.c +++ b/src/toxic.c @@ -50,7 +50,7 @@ #include "groupchat.h" #include "prompt.h" #include "misc_tools.h" -#include "file_senders.h" +#include "file_transfers.h" #include "line_info.h" #include "settings.h" #include "log.h" @@ -79,6 +79,8 @@ char *BLOCK_FILE = NULL; ToxWindow *prompt = NULL; #define AUTOSAVE_FREQ 60 +#define MIN_PASSWORD_LEN 6 +#define MAX_PASSWORD_LEN 64 struct Winthread Winthread; struct cqueue_thread cqueue_thread; @@ -86,8 +88,6 @@ struct audio_thread audio_thread; struct arg_opts arg_opts; struct user_settings *user_settings = NULL; -#define MIN_PASSWORD_LEN 6 -#define MAX_PASSWORD_LEN 64 static struct user_password { bool data_is_encrypted; @@ -102,7 +102,7 @@ static void catch_SIGINT(int sig) static void catch_SIGSEGV(int sig) { - freopen("/dev/tty", "w", stderr); + freopen("/dev/tty", "w", stderr); // make sure stderr is enabled since we may have disabled it endwin(); fprintf(stderr, "Caught SIGSEGV: Aborting toxic session.\n"); exit(EXIT_FAILURE); @@ -124,7 +124,6 @@ void exit_toxic_success(Tox *m) { store_data(m, DATA_FILE); memset(&user_password, 0, sizeof(struct user_password)); - close_all_file_senders(m); kill_all_windows(m); terminate_notify(); @@ -151,9 +150,6 @@ void exit_toxic_success(Tox *m) void exit_toxic_err(const char *errmsg, int errcode) { - if (errmsg == NULL) - errmsg = "No error message"; - freopen("/dev/tty", "w", stderr); endwin(); fprintf(stderr, "Toxic session aborted with error code %d (%s)\n", errcode, errmsg); @@ -167,7 +163,7 @@ static void init_term(void) if (!arg_opts.default_locale) { if (setlocale(LC_ALL, "") == NULL) exit_toxic_err("Could not set your locale, please check your locale settings or " - "disable unicode support with the -d flag.", FATALERR_LOCALE_SET); + "disable unicode support with the -d flag.", FATALERR_LOCALE_NOT_SET); } #endif @@ -255,82 +251,6 @@ static void print_init_messages(ToxWindow *toxwin) line_info_add(toxwin, NULL, NULL, NULL, SYS_MSG, 0, 0, init_messages.msgs[i]); } -static Tox *init_tox(void) -{ - Tox_Options tox_opts; - tox_opts.ipv6enabled = !arg_opts.use_ipv4; - tox_opts.udp_disabled = arg_opts.force_tcp; - tox_opts.proxy_type = arg_opts.proxy_type; - - if (tox_opts.proxy_type != TOX_PROXY_NONE) { - tox_opts.proxy_port = arg_opts.proxy_port; - snprintf(tox_opts.proxy_address, sizeof(tox_opts.proxy_address), "%s", arg_opts.proxy_address); - const char *ps = tox_opts.proxy_type == TOX_PROXY_SOCKS5 ? "SOCKS5" : "HTTP"; - - char tmp[48]; - snprintf(tmp, sizeof(tmp), "Using %s proxy %s : %d", ps, arg_opts.proxy_address, arg_opts.proxy_port); - queue_init_message("%s", tmp); - } - - if (tox_opts.udp_disabled) { - queue_init_message("UDP disabled"); - } else if (tox_opts.proxy_type != TOX_PROXY_NONE) { - const char *msg = "WARNING: Using a proxy without disabling UDP may leak your real IP address."; - queue_init_message("%s", msg); - msg = "Use the -t option to disable UDP."; - queue_init_message("%s", msg); - } - - /* Init core */ - Tox *m = tox_new(&tox_opts); - - if (tox_opts.ipv6enabled && m == NULL) { - queue_init_message("IPv6 failed to initialize"); - tox_opts.ipv6enabled = 0; - m = tox_new(&tox_opts); - } - - if (!tox_opts.ipv6enabled) - queue_init_message("Forcing IPv4 connection"); - - if (tox_opts.proxy_type != TOX_PROXY_NONE && m == NULL) - exit_toxic_err("Proxy error", FATALERR_PROXY); - - if (m == NULL) - return NULL; - - /* Callbacks */ - tox_callback_connection_status(m, on_connectionchange, NULL); - tox_callback_typing_change(m, on_typing_change, NULL); - tox_callback_friend_request(m, on_request, NULL); - tox_callback_friend_message(m, on_message, NULL); - tox_callback_name_change(m, on_nickchange, NULL); - tox_callback_user_status(m, on_statuschange, NULL); - tox_callback_status_message(m, on_statusmessagechange, NULL); - tox_callback_friend_action(m, on_action, NULL); - tox_callback_file_send_request(m, on_file_sendrequest, NULL); - tox_callback_file_control(m, on_file_control, NULL); - tox_callback_file_data(m, on_file_data, NULL); - tox_callback_read_receipt(m, on_read_receipt, NULL); - tox_callback_group_invite(m, on_group_invite, NULL); - tox_callback_group_message(m, on_group_message, NULL); - tox_callback_group_action(m, on_group_action, NULL); - tox_callback_group_private_message(m, on_group_private_message, NULL); - tox_callback_group_op_certificate(m, on_group_op_certificate, NULL); - tox_callback_group_peerlist_update(m, on_group_namelistchange, NULL); - tox_callback_group_peer_join(m, on_group_peer_join, NULL); - tox_callback_group_peer_exit(m, on_group_peer_exit, NULL); - tox_callback_group_nick_change(m, on_group_nick_change, NULL); - tox_callback_group_topic_change(m, on_group_topic_change, NULL); - tox_callback_group_self_join(m, on_group_self_join, NULL); - tox_callback_group_self_timeout(m, on_group_self_timeout, NULL); - tox_callback_group_rejected(m, on_group_rejected, NULL); - - tox_set_name(m, (uint8_t *) "Toxic User", strlen("Toxic User")); - - return m; -} - #define MIN_NODE_LINE 50 /* IP: 7 + port: 5 + key: 38 + spaces: 2 = 70. ! (& e.g. tox.im = 6) */ #define MAX_NODE_LINE 256 /* Approx max number of chars in a sever line (name + port + key) */ #define MAXNODES 50 @@ -387,7 +307,7 @@ static int load_nodelist(const char *filename) int init_connection_helper(Tox *m, int line) { - return tox_bootstrap_from_address(m, toxNodes.nodes[line], toxNodes.ports[line], (uint8_t *) toxNodes.keys[line]); + return tox_bootstrap(m, toxNodes.nodes[line], toxNodes.ports[line], (uint8_t *) toxNodes.keys[line], NULL); } /* Connects to a random DHT node listed in the DHTnodes file @@ -439,43 +359,10 @@ int init_connection(Tox *m) return 4; } -#define TRY_CONNECT 10 /* Seconds between connection attempts when DHT is not connected */ - -static void do_connection(Tox *m, ToxWindow *prompt) -{ - if (arg_opts.no_connect == 1) - return; - - static int conn_err = 0; - static bool was_connected = false; - static uint64_t last_conn_try = 0; - uint64_t curtime = get_unix_time(); - bool is_connected = tox_isconnected(m); - - if (was_connected && is_connected) - return; - - if (!was_connected && is_connected) { - was_connected = true; - prompt_update_connectionstatus(prompt, was_connected); - } else if (was_connected && !is_connected) { - was_connected = false; - prompt_update_connectionstatus(prompt, was_connected); - } else if (!was_connected && !is_connected && timed_out(last_conn_try, curtime, TRY_CONNECT)) { - /* if autoconnect has already failed there's no point in trying again */ - if (conn_err == 0) { - last_conn_try = curtime; - - if ((conn_err = init_connection(m)) != 0) - line_info_add(prompt, NULL, NULL, NULL, SYS_MSG, 0, 0, "Auto-connect failed with error code %d", conn_err); - } - } -} - static void load_friendlist(Tox *m) { - uint32_t i; - uint32_t numfriends = tox_count_friendlist(m); + size_t i; + size_t numfriends = tox_self_get_friend_list_size(m); for (i = 0; i < numfriends; ++i) friendlist_onFriendAdded(NULL, m, i, false); @@ -554,6 +441,7 @@ static void first_time_encrypt(const char *msg) int len = 0; bool valid_password = false; char passconfirm[MAX_PASSWORD_LEN + 1] = {0}; + printf("Enter a new password (must be at least %d characters) ", MIN_PASSWORD_LEN); while (valid_password == false) { @@ -584,7 +472,7 @@ static void first_time_encrypt(const char *msg) valid_password = true; } - queue_init_message("Data file '%s' has been encrypted", DATA_FILE); + queue_init_message("Data file '%s' will be encrypted", DATA_FILE); memset(passconfirm, 0, sizeof(passconfirm)); user_password.data_is_encrypted = true; } @@ -598,13 +486,10 @@ static void first_time_encrypt(const char *msg) */ int store_data(Tox *m, const char *path) { - if (arg_opts.ignore_data_file) - return 0; - if (path == NULL) return -1; - int len = user_password.data_is_encrypted ? tox_encrypted_size(m) : tox_size(m); + size_t len = user_password.data_is_encrypted ? tox_encrypted_size(m) : tox_get_savedata_size(m); char *buf = malloc(len); if (buf == NULL) @@ -616,72 +501,136 @@ int store_data(Tox *m, const char *path) return -1; } } else { - tox_save(m, (uint8_t *) buf); + tox_get_savedata(m, (uint8_t *) buf); } - FILE *fd = fopen(path, "wb"); + FILE *fp = fopen(path, "wb"); - if (fd == NULL) { + if (fp == NULL) { free(buf); return -1; } - if (fwrite(buf, len, 1, fd) != 1) { + if (fwrite(buf, len, 1, fp) != 1) { free(buf); - fclose(fd); + fclose(fp); return -1; } free(buf); - fclose(fd); + fclose(fp); return 0; } -static void load_data(Tox *m, char *path) +static void init_tox_callbacks(Tox *m) { - if (arg_opts.ignore_data_file) - return; + tox_callback_self_connection_status(m, prompt_onSelfConnectionChange, NULL); - FILE *fd = fopen(path, "rb"); + tox_callback_friend_connection_status(m, on_connectionchange, NULL); + tox_callback_friend_typing(m, on_typing_change, NULL); + tox_callback_friend_request(m, on_request, NULL); + tox_callback_friend_message(m, on_message, NULL); + tox_callback_friend_name(m, on_nickchange, NULL); + tox_callback_friend_status(m, on_statuschange, NULL); + tox_callback_friend_status_message(m, on_statusmessagechange, NULL); + tox_callback_friend_read_receipt(m, on_read_receipt, NULL); - if (fd != NULL) { - off_t len = file_size(path); + tox_callback_file_recv(m, on_file_recv, NULL); + tox_callback_file_chunk_request(m, on_file_chunk_request, NULL); + tox_callback_file_recv_control(m, on_file_control, NULL); + tox_callback_file_recv_chunk(m, on_file_recv_chunk, NULL); - if (len == -1) { - fclose(fd); - exit_toxic_err("failed in load_data", FATALERR_FILEOP); + tox_callback_group_invite(m, on_group_invite, NULL); + tox_callback_group_message(m, on_group_message, NULL); + tox_callback_group_action(m, on_group_action, NULL); + tox_callback_group_private_message(m, on_group_private_message, NULL); + tox_callback_group_op_certificate(m, on_group_op_certificate, NULL); + tox_callback_group_peerlist_update(m, on_group_namelistchange, NULL); + tox_callback_group_peer_join(m, on_group_peer_join, NULL); + tox_callback_group_peer_exit(m, on_group_peer_exit, NULL); + tox_callback_group_nick_change(m, on_group_nick_change, NULL); + tox_callback_group_topic_change(m, on_group_topic_change, NULL); + tox_callback_group_self_join(m, on_group_self_join, NULL); + tox_callback_group_self_timeout(m, on_group_self_timeout, NULL); + tox_callback_group_rejected(m, on_group_rejected, NULL); +} + +static void init_tox_options(struct Tox_Options *tox_opts) +{ + tox_opts->ipv6_enabled = !arg_opts.use_ipv4; + tox_opts->udp_enabled = !arg_opts.force_tcp; + tox_opts->proxy_type = arg_opts.proxy_type; + + if (!tox_opts->ipv6_enabled) + queue_init_message("Forcing IPv4 connection"); + + if (tox_opts->proxy_type != TOX_PROXY_TYPE_NONE) { + tox_opts->proxy_port = arg_opts.proxy_port; + tox_opts->proxy_host = arg_opts.proxy_address; + const char *ps = tox_opts->proxy_type == TOX_PROXY_TYPE_SOCKS5 ? "SOCKS5" : "HTTP"; + + char tmp[48]; + snprintf(tmp, sizeof(tmp), "Using %s proxy %s : %d", ps, arg_opts.proxy_address, arg_opts.proxy_port); + queue_init_message("%s", tmp); + } + + if (!tox_opts->udp_enabled) { + queue_init_message("UDP disabled"); + } else if (tox_opts->proxy_type != TOX_PROXY_TYPE_NONE) { + const char *msg = "WARNING: Using a proxy without disabling UDP may leak your real IP address."; + queue_init_message("%s", msg); + msg = "Use the -t option to disable UDP."; + queue_init_message("%s", msg); + } +} + +/* Returns a new Tox object on success. + * If object fails to initialize the toxic process will terminate. + */ +static Tox *load_tox(char *data_path, struct Tox_Options *tox_opts) +{ + Tox *m = NULL; + + FILE *fp = fopen(data_path, "rb"); + + if (fp != NULL) { + off_t len = file_size(data_path); + + if (len == 0) { + fclose(fp); + exit_toxic_err("failed in load_toxic", FATALERR_FILEOP); } char *buf = malloc(len); if (buf == NULL) { - fclose(fd); - exit_toxic_err("failed in load_data", FATALERR_MEMORY); + fclose(fp); + exit_toxic_err("failed in load_toxic", FATALERR_MEMORY); } - if (fread(buf, len, 1, fd) != 1) { + if (fread(buf, len, 1, fp) != 1) { free(buf); - fclose(fd); - exit_toxic_err("failed in load_data", FATALERR_FILEOP); + fclose(fp); + exit_toxic_err("failed in load_toxic", FATALERR_FILEOP); } - bool is_encrypted = tox_is_save_encrypted((uint8_t *) buf); + bool is_encrypted = tox_is_data_encrypted((uint8_t *) buf); /* attempt to encrypt an already encrypted data file */ if (arg_opts.encrypt_data && is_encrypted) - exit_toxic_err("failed in load_data", FATALERR_ENCRYPT); + exit_toxic_err("failed in load_toxic", FATALERR_ENCRYPT); if (arg_opts.unencrypt_data && is_encrypted) - queue_init_message("Data file '%s' has been unencrypted", path); + queue_init_message("Data file '%s' has been unencrypted", data_path); else if (arg_opts.unencrypt_data) - queue_init_message("Warning: passed --unencrypt-data option with unencrypted data file '%s'", path); + queue_init_message("Warning: passed --unencrypt-data option with unencrypted data file '%s'", data_path); if (is_encrypted) { if (!arg_opts.unencrypt_data) user_password.data_is_encrypted = true; - int pwlen = 0; - system("clear"); + size_t pwlen = 0; + system("clear"); // TODO: is this portable? printf("Enter password (q to quit) "); while (true) { @@ -698,44 +647,99 @@ static void load_data(Tox *m, char *path) continue; } - if (tox_encrypted_load(m, (uint8_t *) buf, len, (uint8_t *) user_password.pass, pwlen) == 0) { + TOX_ERR_ENCRYPTED_NEW enc_err; + m = tox_encrypted_new(tox_opts, (uint8_t *) buf, len, (uint8_t *) user_password.pass, pwlen, &enc_err); + + if (enc_err == TOX_ERR_ENCRYPTED_NEW_OK) { break; - } else { + } else if (enc_err == TOX_ERR_ENCRYPTED_NEW_LOAD_DECRYPTION_FAILED) { system("clear"); sleep(1); printf("Invalid password. Try again. "); + } else { + exit_toxic_err("tox_encrypted_new() failed", enc_err); } } } else { - /* tox_load errors are to be ignored until toxcore is fixed */ - tox_load(m, (uint8_t *) buf, len); + TOX_ERR_NEW err; + m = tox_new(tox_opts, (uint8_t *) buf, len, &err); + + if (err != TOX_ERR_NEW_OK) + exit_toxic_err("tox_new() failed", err); } - load_friendlist(m); - load_blocklist(BLOCK_FILE); - free(buf); - fclose(fd); + fclose(fp); } else { /* if file exists then open() failing is fatal */ - if (file_exists(path)) - exit_toxic_err("failed in load_data", FATALERR_FILEOP); + if (file_exists(data_path)) + exit_toxic_err("failed in load_toxic", FATALERR_FILEOP); - if (store_data(m, path) != 0) - exit_toxic_err("failed in load_data", FATALERR_STORE_DATA); + TOX_ERR_NEW err; + m = tox_new(tox_opts, NULL, 0, &err); + + if (err != TOX_ERR_NEW_OK) + exit_toxic_err("tox_new() failed", err); + + if (store_data(m, data_path) == -1) + exit_toxic_err("failed in load_toxic", FATALERR_FILEOP); } + + return m; +} + +static Tox *load_toxic(char *data_path) +{ + struct Tox_Options tox_opts; + init_tox_options(&tox_opts); + + Tox *m = load_tox(data_path, &tox_opts); + + if (m == NULL) + exit_toxic_err("load_tox() failed", FATALERR_TOX_INIT); + + init_tox_callbacks(m); + load_friendlist(m); + load_blocklist(BLOCK_FILE); + + if (tox_self_get_name_size(m) == 0) + tox_self_set_name(m, (uint8_t *) "Toxic User", strlen("Toxic User"), NULL); + + return m; +} + +#define TRY_BOOTSTRAP_INTERVAL 5 +static uint64_t last_bootstrap_time = 0; + +static void do_bootstrap(Tox *m) +{ + static int conn_err = 0; + uint64_t curtime = get_unix_time(); + + if (!timed_out(last_bootstrap_time, curtime, TRY_BOOTSTRAP_INTERVAL)) + return; + + if (tox_self_get_connection_status(m) != TOX_CONNECTION_NONE) + return; + + if (conn_err != 0) + return; + + last_bootstrap_time = curtime; + conn_err = init_connection(m); + + if (conn_err != 0) + line_info_add(prompt, NULL, NULL, NULL, SYS_MSG, 0, 0, "Auto-connect failed with error code %d", conn_err); } static void do_toxic(Tox *m, ToxWindow *prompt) { + if (arg_opts.no_connect) + return; + pthread_mutex_lock(&Winthread.lock); - do_connection(m, prompt); - do_file_senders(m); - - if (arg_opts.no_connect == 0) { - tox_do(m); /* main tox-core loop */ - } - + tox_iterate(m); + do_bootstrap(m); pthread_mutex_unlock(&Winthread.lock); } @@ -772,16 +776,19 @@ void *thread_cqueue(void *data) while (true) { pthread_mutex_lock(&Winthread.lock); - int i; + + size_t i; for (i = 2; i < MAX_WINDOWS_NUM; ++i) { ToxWindow *toxwin = get_window_ptr(i); - if (toxwin != NULL && toxwin->is_chat && tox_get_friend_connection_status(m, toxwin->num) == 1) + if (toxwin != NULL && toxwin->is_chat + && tox_friend_get_connection_status(m, toxwin->num, NULL) != TOX_CONNECTION_NONE) cqueue_try_send(toxwin, m); } pthread_mutex_unlock(&Winthread.lock); + usleep(4000); } } @@ -795,6 +802,7 @@ void *thread_audio(void *data) pthread_mutex_lock(&Winthread.lock); toxav_do(av); pthread_mutex_unlock(&Winthread.lock); + usleep(toxav_do_interval(av) * 1000); } } @@ -817,7 +825,6 @@ static void print_usage(void) fprintf(stderr, " -r, --dnslist Use specified DNSservers file\n"); fprintf(stderr, " -t, --force-tcp Force TCP connection (use this with proxies)\n"); fprintf(stderr, " -u, --unencrypt-data Unencrypt an encrypted data file\n"); - fprintf(stderr, " -x, --nodata Ignore data file\n"); } static void set_default_opts(void) @@ -825,7 +832,7 @@ static void set_default_opts(void) memset(&arg_opts, 0, sizeof(struct arg_opts)); /* set any non-zero defaults here*/ - arg_opts.proxy_type = TOX_PROXY_NONE; + arg_opts.proxy_type = TOX_PROXY_TYPE_NONE; } static void parse_args(int argc, char *argv[]) @@ -834,7 +841,6 @@ static void parse_args(int argc, char *argv[]) static struct option long_opts[] = { {"file", required_argument, 0, 'f'}, - {"nodata", no_argument, 0, 'x'}, {"ipv4", no_argument, 0, '4'}, {"debug", no_argument, 0, 'b'}, {"default-locale", no_argument, 0, 'd'}, @@ -911,7 +917,7 @@ static void parse_args(int argc, char *argv[]) break; case 'p': - arg_opts.proxy_type = TOX_PROXY_SOCKS5; + arg_opts.proxy_type = TOX_PROXY_TYPE_SOCKS5; snprintf(arg_opts.proxy_address, sizeof(arg_opts.proxy_address), "%s", optarg); if (++optind > argc || argv[optind-1][0] == '-') @@ -921,7 +927,7 @@ static void parse_args(int argc, char *argv[]) break; case 'P': - arg_opts.proxy_type = TOX_PROXY_HTTP; + arg_opts.proxy_type = TOX_PROXY_TYPE_HTTP; snprintf(arg_opts.proxy_address, sizeof(arg_opts.proxy_address), "%s", optarg); if (++optind > argc || argv[optind-1][0] == '-') @@ -946,11 +952,6 @@ static void parse_args(int argc, char *argv[]) arg_opts.unencrypt_data = 1; break; - case 'x': - arg_opts.ignore_data_file = 1; - queue_init_message("Ignoring data file"); - break; - case 'h': default: print_usage(); @@ -1015,6 +1016,7 @@ static useconds_t optimal_msleepval(uint64_t *looptimer, uint64_t *loopcount, ui } #ifdef X11 +// FIXME void DnD_callback(const char* asdv, DropType dt) { if (dt != DT_plain) @@ -1026,31 +1028,32 @@ void DnD_callback(const char* asdv, DropType dt) int main(int argc, char *argv[]) { - parse_args(argc, argv); + /* Use the -b flag to enable stderr */ + if (!arg_opts.debug) + freopen("/dev/null", "w", stderr); + if (arg_opts.encrypt_data && arg_opts.unencrypt_data) { arg_opts.encrypt_data = 0; arg_opts.unencrypt_data = 0; queue_init_message("Warning: Using --unencrypt-data and --encrypt-data simultaneously has no effect"); } - /* Use the -b flag to enable stderr */ - if (!arg_opts.debug) - freopen("/dev/null", "w", stderr); - /* Make sure all written files are read/writeable only by the current user. */ umask(S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); int config_err = init_default_data_files(); bool datafile_exists = file_exists(DATA_FILE); - if (!arg_opts.ignore_data_file) { - if (!datafile_exists && !arg_opts.unencrypt_data) - first_time_encrypt("Creating new data file. Would you like to encrypt it? Y/n (q to quit)"); - else if (arg_opts.encrypt_data) - first_time_encrypt("Encrypt existing data file? Y/n (q to quit)"); - } + if (datafile_exists) + last_bootstrap_time = get_unix_time(); + + if (!datafile_exists && !arg_opts.unencrypt_data) + first_time_encrypt("Creating new data file. Would you like to encrypt it? Y/n (q to quit)"); + else if (arg_opts.encrypt_data) + first_time_encrypt("Encrypt existing data file? Y/n (q to quit)"); + /* init user_settings struct and load settings from conf file */ user_settings = calloc(1, sizeof(struct user_settings)); @@ -1066,20 +1069,14 @@ int main(int argc, char *argv[]) queue_init_message("X failed to initialize"); #endif - Tox *m = init_tox(); + Tox *m = load_toxic(DATA_FILE); - if (m == NULL) - exit_toxic_err("failed in main", FATALERR_NETWORKINIT); + if (arg_opts.encrypt_data && !datafile_exists) + arg_opts.encrypt_data = 0; - if (!arg_opts.ignore_data_file) { - if (arg_opts.encrypt_data && !datafile_exists) - arg_opts.encrypt_data = 0; - - load_data(m, DATA_FILE); - - } init_term(); + prompt = init_windows(m); prompt_init_statusbar(prompt, m); @@ -1124,7 +1121,7 @@ int main(int argc, char *argv[]) queue_init_message("Failed to load user settings"); /* screen/tmux auto-away timer */ - if (init_mplex_away_timer (m) == -1) + if (init_mplex_away_timer(m) == -1) queue_init_message("Failed to init mplex auto-away."); load_groups(m); diff --git a/src/toxic.h b/src/toxic.h index 0a1ef8f..4bcacd6 100644 --- a/src/toxic.h +++ b/src/toxic.h @@ -77,13 +77,13 @@ typedef enum _FATAL_ERRS { FATALERR_THREAD_CREATE = -3, /* thread creation failed for critical thread */ FATALERR_MUTEX_INIT = -4, /* mutex init for critical thread failed */ FATALERR_THREAD_ATTR = -5, /* thread attr object init failed */ - FATALERR_LOCALE_SET = -6, /* system locale not set */ + FATALERR_LOCALE_NOT_SET = -6, /* system locale not set */ FATALERR_STORE_DATA = -7, /* store_data failed in critical section */ - FATALERR_NETWORKINIT = -8, /* Tox network failed to init */ - FATALERR_INFLOOP = -9, /* infinite loop detected */ - FATALERR_WININIT = -10, /* window init failed */ - FATALERR_PROXY = -11, /* Tox network failed to init using a proxy */ - FATALERR_ENCRYPT = -12, /* Data file encryption failure */ + FATALERR_INFLOOP = -8, /* infinite loop detected */ + FATALERR_WININIT = -9, /* window init failed */ + 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 */ } FATAL_ERRS; /* Fixes text color problem on some terminals. @@ -98,21 +98,23 @@ void exit_toxic_err(const char *errmsg, int errcode); int store_data(Tox *m, const char *path); -void on_request(Tox *m, const uint8_t *public_key, const uint8_t *data, uint16_t length, void *userdata); -void on_connectionchange(Tox *m, int32_t friendnumber, uint8_t status, void *userdata); -void on_message(Tox *m, int32_t friendnumber, const uint8_t *string, uint16_t length, void *userdata); -void on_action(Tox *m, int32_t friendnumber, const uint8_t *string, uint16_t length, void *userdata); -void on_nickchange(Tox *m, int32_t friendnumber, const uint8_t *string, uint16_t length, void *userdata); -void on_statuschange(Tox *m, int32_t friendnumber, uint8_t status, void *userdata); -void on_statusmessagechange(Tox *m, int32_t friendnumber, const uint8_t *string, uint16_t length, void *userdata); -void on_friendadded(Tox *m, int32_t friendnumber, bool sort); -void on_file_sendrequest(Tox *m, int32_t friendnumber, uint8_t filenumber, uint64_t filesize, const uint8_t *pathname, - uint16_t pathname_length, void *userdata); -void on_file_control(Tox *m, int32_t friendnumber, uint8_t receive_send, uint8_t filenumber, uint8_t control_type, - const uint8_t *data, uint16_t length, void *userdata); -void on_file_data(Tox *m, int32_t friendnumber, uint8_t filenumber, const uint8_t *data, uint16_t length, void *userdata); -void on_typing_change(Tox *m, int32_t friendnumber, uint8_t is_typing, void *userdata); -void on_read_receipt(Tox *m, int32_t, uint32_t, void *userdata); +/* callbacks */ +void on_request(Tox *m, const uint8_t *public_key, const uint8_t *data, size_t length, void *userdata); +void on_connectionchange(Tox *m, uint32_t friendnumber, TOX_CONNECTION status, void *userdata); +void on_message(Tox *m, uint32_t friendnumber, TOX_MESSAGE_TYPE type, const uint8_t *string, size_t length, void *userdata); +void on_action(Tox *m, uint32_t friendnumber, const uint8_t *string, size_t length, void *userdata); +void on_nickchange(Tox *m, uint32_t friendnumber, const uint8_t *string, size_t length, void *userdata); +void on_statuschange(Tox *m, uint32_t friendnumber, TOX_USER_STATUS status, void *userdata); +void on_statusmessagechange(Tox *m, uint32_t friendnumber, const uint8_t *string, size_t length, void *userdata); +void on_friendadded(Tox *m, uint32_t friendnumber, bool sort); +void on_file_chunk_request(Tox *m, uint32_t friendnumber, uint32_t filenumber, uint64_t position, size_t length, void *userdata); +void on_file_recv_chunk(Tox *m, uint32_t friendnumber, uint32_t filenumber, uint64_t position, const uint8_t *data, + size_t length, void *userdata); +void on_file_control (Tox *m, uint32_t friendnumber, uint32_t filenumber, TOX_FILE_CONTROL control, void *userdata); +void on_file_recv(Tox *m, uint32_t friendnumber, uint32_t filenumber, uint32_t kind, uint64_t file_size, + const uint8_t *filename, size_t filename_length, void *userdata); +void on_typing_change(Tox *m, uint32_t friendnumber, bool is_typing, void *userdata); +void on_read_receipt(Tox *m, uint32_t friendnumber, uint32_t receipt, void *userdata); void on_group_invite(Tox *m, int32_t friendnumber, const uint8_t *invite_data, uint16_t length, void *userdata); void on_group_message(Tox *m, int groupnumber, uint32_t peernumber, const uint8_t *message, uint16_t length, void *userdata); diff --git a/src/toxic_strings.c b/src/toxic_strings.c index 0709f13..e2417ba 100644 --- a/src/toxic_strings.c +++ b/src/toxic_strings.c @@ -125,7 +125,7 @@ int yank_buf(ChatContext *ctx) return 0; } -/* Deletes all characters from line starting at pos and going backwards +/* Deletes all characters from line starting at pos and going backwards until we find a space or run out of characters. Return 0 on success, -1 if nothing to delete */ int del_word_buf(ChatContext *ctx) @@ -225,7 +225,7 @@ void fetch_hist_item(ChatContext *ctx, int key_dir) if (key_dir == KEY_UP) { if (--ctx->hst_pos < 0) { ctx->hst_pos = 0; - sound_notify(NULL, error, NT_ALWAYS, NULL); + sound_notify(NULL, notif_error, NT_ALWAYS, NULL); } } else { if (++ctx->hst_pos >= ctx->hst_tot) { diff --git a/src/windows.c b/src/windows.c index 4f03e75..899cd3b 100644 --- a/src/windows.c +++ b/src/windows.c @@ -46,12 +46,12 @@ extern struct user_settings *user_settings; static int num_active_windows; /* CALLBACKS START */ -void on_request(Tox *m, const uint8_t *public_key, const uint8_t *data, uint16_t length, void *userdata) +void on_request(Tox *m, const uint8_t *public_key, const uint8_t *data, size_t length, void *userdata) { char msg[MAX_STR_SIZE + 1]; length = copy_tox_str(msg, sizeof(msg), (const char *) data, length); - int i; + size_t i; for (i = 0; i < MAX_WINDOWS_NUM; ++i) { if (windows[i].onFriendRequest != NULL) { @@ -60,22 +60,22 @@ void on_request(Tox *m, const uint8_t *public_key, const uint8_t *data, uint16_t } } -void on_connectionchange(Tox *m, int32_t friendnumber, uint8_t status, void *userdata) +void on_connectionchange(Tox *m, uint32_t friendnumber, TOX_CONNECTION connection_status, void *userdata) { - int i; + size_t i; for (i = 0; i < MAX_WINDOWS_NUM; ++i) { if (windows[i].onConnectionChange != NULL) - windows[i].onConnectionChange(&windows[i], m, friendnumber, status); + windows[i].onConnectionChange(&windows[i], m, friendnumber, connection_status); } } -void on_typing_change(Tox *m, int32_t friendnumber, uint8_t is_typing, void *userdata) +void on_typing_change(Tox *m, uint32_t friendnumber, bool is_typing, void *userdata) { if (user_settings->show_typing_other == SHOW_TYPING_OFF) return; - int i; + size_t i; for (i = 0; i < MAX_WINDOWS_NUM; ++i) { if (windows[i].onTypingChange != NULL) @@ -83,39 +83,27 @@ void on_typing_change(Tox *m, int32_t friendnumber, uint8_t is_typing, void *use } } -void on_message(Tox *m, int32_t friendnumber, const uint8_t *string, uint16_t length, void *userdata) +void on_message(Tox *m, uint32_t friendnumber, TOX_MESSAGE_TYPE type, const uint8_t *string, size_t length, + void *userdata) { char msg[MAX_STR_SIZE + 1]; length = copy_tox_str(msg, sizeof(msg), (const char *) string, length); - int i; + size_t i; for (i = 0; i < MAX_WINDOWS_NUM; ++i) { if (windows[i].onMessage != NULL) - windows[i].onMessage(&windows[i], m, friendnumber, msg, length); + windows[i].onMessage(&windows[i], m, friendnumber, type, msg, length); } } -void on_action(Tox *m, int32_t friendnumber, const uint8_t *string, uint16_t length, void *userdata) -{ - char msg[MAX_STR_SIZE + 1]; - length = copy_tox_str(msg, sizeof(msg), (const char *) string, length); - - int i; - - for (i = 0; i < MAX_WINDOWS_NUM; ++i) { - if (windows[i].onAction != NULL) - windows[i].onAction(&windows[i], m, friendnumber, msg, length); - } -} - -void on_nickchange(Tox *m, int32_t friendnumber, const uint8_t *string, uint16_t length, void *userdata) +void on_nickchange(Tox *m, uint32_t friendnumber, const uint8_t *string, size_t length, void *userdata) { char nick[TOXIC_MAX_NAME_LENGTH + 1]; length = copy_tox_str(nick, sizeof(nick), (const char *) string, length); filter_str(nick, length); - int i; + size_t i; for (i = 0; i < MAX_WINDOWS_NUM; ++i) { if (windows[i].onNickChange != NULL) @@ -125,13 +113,13 @@ void on_nickchange(Tox *m, int32_t friendnumber, const uint8_t *string, uint16_t store_data(m, DATA_FILE); } -void on_statusmessagechange(Tox *m, int32_t friendnumber, const uint8_t *string, uint16_t length, void *userdata) +void on_statusmessagechange(Tox *m, uint32_t friendnumber, const uint8_t *string, size_t length, void *userdata) { - char msg[TOX_MAX_STATUSMESSAGE_LENGTH + 1]; + char msg[TOX_MAX_STATUS_MESSAGE_LENGTH + 1]; length = copy_tox_str(msg, sizeof(msg), (const char *) string, length); filter_str(msg, length); - int i; + size_t i; for (i = 0; i < MAX_WINDOWS_NUM; ++i) { if (windows[i].onStatusMessageChange != NULL) @@ -139,9 +127,9 @@ void on_statusmessagechange(Tox *m, int32_t friendnumber, const uint8_t *string, } } -void on_statuschange(Tox *m, int32_t friendnumber, uint8_t status, void *userdata) +void on_statuschange(Tox *m, uint32_t friendnumber, TOX_USER_STATUS status, void *userdata) { - int i; + size_t i; for (i = 0; i < MAX_WINDOWS_NUM; ++i) { if (windows[i].onStatusChange != NULL) @@ -149,9 +137,9 @@ void on_statuschange(Tox *m, int32_t friendnumber, uint8_t status, void *userdat } } -void on_friendadded(Tox *m, int32_t friendnumber, bool sort) +void on_friendadded(Tox *m, uint32_t friendnumber, bool sort) { - int i; + size_t i; for (i = 0; i < MAX_WINDOWS_NUM; ++i) { if (windows[i].onFriendAdded != NULL) @@ -177,7 +165,7 @@ void on_group_message(Tox *m, int groupnumber, uint32_t peernumber, const uint8_ char msg[MAX_STR_SIZE + 1]; length = copy_tox_str(msg, sizeof(msg), (const char *) message, length); - int i; + size_t i; for (i = 0; i < MAX_WINDOWS_NUM; ++i) { if (windows[i].onGroupMessage != NULL) @@ -191,7 +179,7 @@ void on_group_action(Tox *m, int groupnumber, uint32_t peernumber, const uint8_t char msg[MAX_STR_SIZE + 1]; length = copy_tox_str(msg, sizeof(msg), (const char *) action, length); - int i; + size_t i; for (i = 0; i < MAX_WINDOWS_NUM; ++i) { if (windows[i].onGroupAction != NULL) @@ -205,7 +193,7 @@ void on_group_private_message(Tox *m, int groupnumber, uint32_t peernumber, cons char msg[MAX_STR_SIZE + 1]; length = copy_tox_str(msg, sizeof(msg), (const char *) message, length); - int i; + size_t i; for (i = 0; i < MAX_WINDOWS_NUM; ++i) { if (windows[i].onGroupPrivateMessage != NULL) @@ -215,7 +203,7 @@ void on_group_private_message(Tox *m, int groupnumber, uint32_t peernumber, cons void on_group_namelistchange(Tox *m, int groupnumber, void *userdata) { - int i; + size_t i; for (i = 0; i < MAX_WINDOWS_NUM; ++i) { if (windows[i].onGroupNamelistChange != NULL) @@ -259,7 +247,7 @@ void on_group_topic_change(Tox *m, int groupnumber, uint32_t peernumber, const u char data[MAX_STR_SIZE + 1]; length = copy_tox_str(data, sizeof(data), (const char *) topic, length); - int i; + size_t i; for (i = 0; i < MAX_WINDOWS_NUM; ++i) { if (windows[i].onGroupTopicChange != NULL) @@ -323,44 +311,60 @@ void on_group_rejected(Tox *m, int groupnumber, uint8_t type, void *userdata) } } -void on_file_sendrequest(Tox *m, int32_t friendnumber, uint8_t filenumber, uint64_t filesize, - const uint8_t *filename, uint16_t filename_length, void *userdata) +void on_file_chunk_request(Tox *m, uint32_t friendnumber, uint32_t filenumber, uint64_t position, + size_t length, void *userdata) { - int i; + size_t i; for (i = 0; i < MAX_WINDOWS_NUM; ++i) { - if (windows[i].onFileSendRequest != NULL) - windows[i].onFileSendRequest(&windows[i], m, friendnumber, filenumber, filesize, - (const char *) filename, filename_length); + if (windows[i].onFileChunkRequest != NULL) + windows[i].onFileChunkRequest(&windows[i], m, friendnumber, filenumber, position, length); } } -void on_file_control (Tox *m, int32_t friendnumber, uint8_t receive_send, uint8_t filenumber, - uint8_t control_type, const uint8_t *data, uint16_t length, void *userdata) +void on_file_recv_chunk(Tox *m, uint32_t friendnumber, uint32_t filenumber, uint64_t position, + const uint8_t *data, size_t length, void *user_data) { - int i; + size_t i; + + for (i = 0; i < MAX_WINDOWS_NUM; ++i) { + if (windows[i].onFileRecvChunk != NULL) + windows[i].onFileRecvChunk(&windows[i], m, friendnumber, filenumber, position, (char *) data, length); + } +} + +void on_file_control(Tox *m, uint32_t friendnumber, uint32_t filenumber, TOX_FILE_CONTROL control, + void *userdata) +{ + size_t i; for (i = 0; i < MAX_WINDOWS_NUM; ++i) { if (windows[i].onFileControl != NULL) - windows[i].onFileControl(&windows[i], m, friendnumber, receive_send, filenumber, - control_type, (const char *) data, length); + windows[i].onFileControl(&windows[i], m, friendnumber, filenumber, control); } } -void on_file_data(Tox *m, int32_t friendnumber, uint8_t filenumber, const uint8_t *data, uint16_t length, - void *userdata) +void on_file_recv(Tox *m, uint32_t friendnumber, uint32_t filenumber, uint32_t kind, uint64_t file_size, + const uint8_t *filename, size_t filename_length, void *userdata) { - int i; + /* We don't care about receiving avatars */ + if (kind != TOX_FILE_KIND_DATA) { + tox_file_control(m, friendnumber, filenumber, TOX_FILE_CONTROL_CANCEL, NULL); + return; + } + + size_t i; for (i = 0; i < MAX_WINDOWS_NUM; ++i) { - if (windows[i].onFileData != NULL) - windows[i].onFileData(&windows[i], m, friendnumber, filenumber, (const char *) data, length); + if (windows[i].onFileRecv != NULL) + windows[i].onFileRecv(&windows[i], m, friendnumber, filenumber, file_size, (char *) filename, + filename_length); } } -void on_read_receipt(Tox *m, int32_t friendnumber, uint32_t receipt, void *userdata) +void on_read_receipt(Tox *m, uint32_t friendnumber, uint32_t receipt, void *userdata) { - int i; + size_t i; for (i = 0; i < MAX_WINDOWS_NUM; ++i) { if (windows[i].onReadReceipt != NULL) @@ -375,7 +379,7 @@ int add_window(Tox *m, ToxWindow w) if (LINES < 2) return -1; - int i; + size_t i; for (i = 0; i < MAX_WINDOWS_NUM; i++) { if (windows[i].active) @@ -469,7 +473,7 @@ void on_window_resize(void) getmaxyx(stdscr, y2, x2); y2 -= 2; - int i; + size_t i; for (i = 0; i < MAX_WINDOWS_NUM; ++i) { if (!windows[i].active) @@ -541,7 +545,7 @@ static void draw_bar(void) printw(" TOXIC " TOXICVER " |"); attroff(COLOR_PAIR(BLUE) | A_BOLD); - int i; + size_t i; for (i = 0; i < MAX_WINDOWS_NUM; ++i) { if (!windows[i].active) @@ -619,7 +623,7 @@ void draw_active_window(Tox *m) call at least once per second */ void refresh_inactive_windows(void) { - int i; + size_t i; for (i = 0; i < MAX_WINDOWS_NUM; ++i) { ToxWindow *a = &windows[i]; @@ -655,7 +659,7 @@ int get_num_active_windows(void) /* destroys all chat and groupchat windows (should only be called on shutdown) */ void kill_all_windows(Tox *m) { - int i; + size_t i; for (i = 0; i < MAX_WINDOWS_NUM; ++i) { if (windows[i].is_chat) diff --git a/src/windows.h b/src/windows.h index 2e1394b..ace1259 100644 --- a/src/windows.h +++ b/src/windows.h @@ -81,21 +81,21 @@ struct audio_thread { }; struct arg_opts { - int ignore_data_file; - int use_ipv4; - int force_tcp; - int debug; - int default_locale; - int use_custom_data; - int no_connect; - int encrypt_data; - int unencrypt_data; + bool use_ipv4; + bool force_tcp; + bool debug; + bool default_locale; + bool use_custom_data; + bool no_connect; + bool encrypt_data; + bool unencrypt_data; + char dns_path[MAX_STR_SIZE]; char config_path[MAX_STR_SIZE]; char nodes_path[MAX_STR_SIZE]; - uint8_t proxy_type; char proxy_address[256]; + uint8_t proxy_type; uint16_t proxy_port; }; @@ -106,22 +106,25 @@ typedef struct ChatContext ChatContext; typedef struct Help Help; struct ToxWindow { + /* ncurses */ void(*onKey)(ToxWindow *, Tox *, wint_t, bool); void(*onDraw)(ToxWindow *, Tox *); void(*onInit)(ToxWindow *, Tox *); - void(*onFriendRequest)(ToxWindow *, Tox *, const char *, const char *, uint16_t); - void(*onFriendAdded)(ToxWindow *, Tox *, int32_t, bool); - void(*onConnectionChange)(ToxWindow *, Tox *, int32_t, uint8_t); - void(*onMessage)(ToxWindow *, Tox *, int32_t, const char *, uint16_t); - void(*onNickChange)(ToxWindow *, Tox *, int32_t, const char *, uint16_t); - void(*onStatusChange)(ToxWindow *, Tox *, int32_t, uint8_t); - void(*onStatusMessageChange)(ToxWindow *, int32_t, const char *, uint16_t); - void(*onAction)(ToxWindow *, Tox *, int32_t, const char *, uint16_t); - void(*onFileSendRequest)(ToxWindow *, Tox *, int32_t, uint8_t, uint64_t, const char *, uint16_t); - void(*onFileControl)(ToxWindow *, Tox *, int32_t, uint8_t, uint8_t, uint8_t, const char *, uint16_t); - void(*onFileData)(ToxWindow *, Tox *, int32_t, uint8_t, const char *, uint16_t); - void(*onTypingChange)(ToxWindow *, Tox *, int32_t, uint8_t); - void(*onReadReceipt)(ToxWindow *, Tox *, int32_t, uint32_t); + + /* toxcore */ + void(*onFriendRequest)(ToxWindow *, Tox *, const char *, const char *, size_t); + void(*onFriendAdded)(ToxWindow *, Tox *, uint32_t, bool); + void(*onConnectionChange)(ToxWindow *, Tox *, uint32_t, TOX_CONNECTION); + void(*onMessage)(ToxWindow *, Tox *, uint32_t, TOX_MESSAGE_TYPE, const char *, size_t); + void(*onNickChange)(ToxWindow *, Tox *, uint32_t, const char *, size_t); + void(*onStatusChange)(ToxWindow *, Tox *, uint32_t, TOX_USER_STATUS); + void(*onStatusMessageChange)(ToxWindow *, uint32_t, const char *, size_t); + void(*onFileChunkRequest)(ToxWindow *, Tox *, uint32_t, uint32_t, uint64_t, size_t); + void(*onFileRecvChunk)(ToxWindow *, Tox *, uint32_t, uint32_t, uint64_t, const char *, size_t); + void(*onFileControl)(ToxWindow *, Tox *, uint32_t, uint32_t, TOX_FILE_CONTROL); + void(*onFileRecv)(ToxWindow *, Tox *, uint32_t, uint32_t, uint64_t, const char *, size_t); + void(*onTypingChange)(ToxWindow *, Tox *, uint32_t, bool); + void(*onReadReceipt)(ToxWindow *, Tox *, uint32_t, uint32_t); void(*onGroupInvite)(ToxWindow *, Tox *, int32_t, const char *, uint16_t); void(*onGroupMessage)(ToxWindow *, Tox *, int, int, const char *, uint16_t); @@ -161,7 +164,7 @@ struct ToxWindow { int active_box; /* For box notify */ char name[TOXIC_MAX_NAME_LENGTH + 1]; - int32_t num; /* corresponds to friendnumber in chat windows */ + uint32_t num; /* corresponds to friendnumber in chat windows */ bool active; int x; @@ -183,19 +186,19 @@ struct ToxWindow { /* statusbar info holder */ struct StatusBar { WINDOW *topline; - char statusmsg[TOX_MAX_STATUSMESSAGE_LENGTH + 1]; - uint16_t statusmsg_len; + char statusmsg[TOX_MAX_STATUS_MESSAGE_LENGTH + 1]; + size_t statusmsg_len; char nick[TOXIC_MAX_NAME_LENGTH + 1]; - int nick_len; - uint8_t status; - bool is_online; + size_t nick_len; + TOX_USER_STATUS status; + TOX_CONNECTION connection; }; #ifdef AUDIO - #define INFOBOX_HEIGHT 7 #define INFOBOX_WIDTH 21 + /* holds display info for audio calls */ struct infobox { float vad_lvl; From b2c0753fdf4a13d57d3f2dc762e0804be082a228 Mon Sep 17 00:00:00 2001 From: JFreegman Date: Thu, 2 Apr 2015 22:31:20 -0400 Subject: [PATCH 28/45] Update .travis.yml --- .travis.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.travis.yml b/.travis.yml index a218319..986365c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,3 +9,9 @@ script: notifications: email: false + + irc: + channels: + - "chat.freenode.net#tox-groupchats" + on_success: always + on_failure: always From a360afe08ad58b84e2165ed499aaa6ce18ef3248 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Sun, 12 Apr 2015 21:56:42 -0400 Subject: [PATCH 29/45] remove group self-timeout callback --- src/groupchat.c | 21 --------------------- src/toxic.c | 1 - src/toxic.h | 1 - src/windows.c | 10 ---------- src/windows.h | 1 - 5 files changed, 34 deletions(-) diff --git a/src/groupchat.c b/src/groupchat.c index 93b2c66..d149aa2 100644 --- a/src/groupchat.c +++ b/src/groupchat.c @@ -533,26 +533,6 @@ static void groupchat_onGroupSelfJoin(ToxWindow *self, Tox *m, int groupnum) line_info_add(self, timefrmt, NULL, NULL, SYS_MSG, 1, MAGENTA, "-!- Topic set to: %s", topic); } -static void groupchat_onGroupSelfTimeout(ToxWindow *self, Tox *m, int groupnum) -{ - if (groupnum != self->num) - return; - - int i; - - for (i = 0; i < max_groupchat_index; ++i) { - if (groupchats[i].active && groupchats[i].groupnumber == groupnum) { - groupchats[i].is_connected = false; - break; - } - } - - char timefrmt[TIME_STR_SIZE]; - get_time_str(timefrmt, sizeof(timefrmt)); - - line_info_add(self, timefrmt, NULL, NULL, SYS_MSG, 0, RED, "-!- Disconnected from group"); -} - static void groupchat_onGroupRejected(ToxWindow *self, Tox *m, int groupnum, uint8_t type) { if (groupnum != self->num) @@ -967,7 +947,6 @@ ToxWindow new_group_chat(Tox *m, int groupnum, const char *groupname, int length ret.onGroupOpCertificate = &groupchat_onGroupOpCertificate; ret.onGroupNickChange = &groupchat_onGroupNickChange; ret.onGroupSelfJoin = &groupchat_onGroupSelfJoin; - ret.onGroupSelfTimeout = &groupchat_onGroupSelfTimeout; ret.onGroupRejected = &groupchat_onGroupRejected; ChatContext *chatwin = calloc(1, sizeof(ChatContext)); diff --git a/src/toxic.c b/src/toxic.c index bf19d2f..ab2a414 100644 --- a/src/toxic.c +++ b/src/toxic.c @@ -556,7 +556,6 @@ static void init_tox_callbacks(Tox *m) tox_callback_group_nick_change(m, on_group_nick_change, NULL); tox_callback_group_topic_change(m, on_group_topic_change, NULL); tox_callback_group_self_join(m, on_group_self_join, NULL); - tox_callback_group_self_timeout(m, on_group_self_timeout, NULL); tox_callback_group_rejected(m, on_group_rejected, NULL); } diff --git a/src/toxic.h b/src/toxic.h index 9a23908..2a7680a 100644 --- a/src/toxic.h +++ b/src/toxic.h @@ -127,6 +127,5 @@ void on_group_topic_change(Tox *m, int groupnumber, uint32_t peernumber, const u void on_group_nick_change(Tox *m, int groupnumber, uint32_t peernumber, const uint8_t *newname, uint16_t length, void *userdata); void on_group_op_certificate(Tox *m, int groupnumber, uint32_t src_peernum, uint32_t tgt_peernum, uint8_t cert_type, void *userdata); void on_group_self_join(Tox *m, int groupnumber, void *userdata); -void on_group_self_timeout(Tox *m, int groupnumber, void *userdata); void on_group_rejected(Tox *m, int groupnumber, uint8_t type, void *userdata); #endif /* #define TOXIC_H */ diff --git a/src/windows.c b/src/windows.c index 88154b0..9801a1a 100644 --- a/src/windows.c +++ b/src/windows.c @@ -293,16 +293,6 @@ void on_group_self_join(Tox *m, int groupnumber, void *userdata) } } -void on_group_self_timeout(Tox *m, int groupnumber, void *userdata) -{ - size_t i; - - for (i = 0; i < MAX_WINDOWS_NUM; ++i) { - if (windows[i].onGroupSelfTimeout != NULL) - windows[i].onGroupSelfTimeout(&windows[i], m, groupnumber); - } -} - void on_group_rejected(Tox *m, int groupnumber, uint8_t type, void *userdata) { size_t i; diff --git a/src/windows.h b/src/windows.h index ace1259..9bfa502 100644 --- a/src/windows.h +++ b/src/windows.h @@ -137,7 +137,6 @@ struct ToxWindow { void(*onGroupNickChange)(ToxWindow *, Tox *, int, uint32_t, const char *, uint16_t); void(*onGroupTopicChange)(ToxWindow *, Tox *, int, uint32_t, const char *, uint16_t); void(*onGroupSelfJoin)(ToxWindow *, Tox *, int); - void(*onGroupSelfTimeout)(ToxWindow *, Tox *, int); void(*onGroupRejected)(ToxWindow *, Tox *, int, uint8_t); #ifdef AUDIO From 540bf4a5c42f3e757fe53185cf5553ef35dbf45b Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Mon, 13 Apr 2015 00:45:15 -0400 Subject: [PATCH 30/45] not clear which error message is given for ipv6 failure --- src/toxic.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/toxic.c b/src/toxic.c index ba52981..347ce49 100644 --- a/src/toxic.c +++ b/src/toxic.c @@ -689,14 +689,13 @@ static Tox *load_toxic(char *data_path) TOX_ERR_NEW new_err; Tox *m = load_tox(data_path, &tox_opts, &new_err); - if (new_err == TOX_ERR_NEW_PORT_ALLOC && tox_opts.ipv6_enabled) { + if (new_err != TOX_ERR_NEW_OK && tox_opts.ipv6_enabled) { queue_init_message("Falling back to ipv4"); tox_opts.ipv6_enabled = false; m = load_tox(data_path, &tox_opts, &new_err); - } - - if (m == NULL || new_err != TOX_ERR_NEW_OK) + } else if (new_err != TOX_ERR_NEW_OK) { exit_toxic_err("Tox network failed to initialize (tox_new failed with error %d)", new_err); + } init_tox_callbacks(m); load_friendlist(m); From 9385f1145fa7abe8aed61785f5d2a23d9afc793e Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Tue, 5 May 2015 22:32:42 -0400 Subject: [PATCH 31/45] update group api call --- src/global_commands.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/global_commands.c b/src/global_commands.c index 76df5fc..2223db7 100644 --- a/src/global_commands.c +++ b/src/global_commands.c @@ -341,7 +341,7 @@ void cmd_groupchat(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*arg snprintf(name, sizeof(name), "%s", argv[1]); } - int groupnum = tox_group_new(m, (uint8_t *) name, len); + int groupnum = tox_group_new(m, TOX_GP_PUBLIC, (uint8_t *) name, len); if (groupnum == -1) { line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group chat instance failed to initialize."); From f021908f8bf5db4e467263fa327f453e19d6aca1 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Wed, 20 May 2015 19:07:25 -0400 Subject: [PATCH 32/45] implement group passwords --- src/chat.c | 7 ++++--- src/chat_commands.c | 38 +++++++++++++++++++++++++++++++++++--- src/chat_commands.h | 1 + src/execute.c | 15 +++++++++++---- src/execute.h | 2 -- src/global_commands.c | 39 ++++++++++++--------------------------- src/group_commands.c | 38 +++++++++++++++++++++++++++++++++++++- src/group_commands.h | 1 + src/groupchat.c | 9 +++++---- src/help.c | 8 +++++--- 10 files changed, 111 insertions(+), 47 deletions(-) diff --git a/src/chat.c b/src/chat.c index 2e0743d..7894056 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 27 +#define AC_NUM_CHAT_COMMANDS 28 #else -#define AC_NUM_CHAT_COMMANDS 20 +#define AC_NUM_CHAT_COMMANDS 21 #endif /* AUDIO */ /* Array of chat command names used for tab completion. */ @@ -78,6 +78,7 @@ static const char chat_cmd_list[AC_NUM_CHAT_COMMANDS][MAX_CMDNAME_SIZE] = { { "/close" }, { "/connect" }, { "/exit" }, + { "/gaccept" }, { "/group" }, { "/help" }, { "/invite" }, @@ -533,7 +534,7 @@ static void chat_onGroupInvite(ToxWindow *self, Tox *m, int32_t friendnumber, co box_silent_notify(self, NT_WNDALERT_2 | NT_NOFOCUS, &self->active_box, name, "invites you to join group chat"); line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s has invited you to a group chat.", name); - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Type \"/join\" to join the chat."); + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Type \"/gaccept\" to join the chat."); } /* Av Stuff */ diff --git a/src/chat_commands.c b/src/chat_commands.c index e2a417b..d252911 100644 --- a/src/chat_commands.c +++ b/src/chat_commands.c @@ -78,6 +78,41 @@ void cmd_cancelfile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*ar close_file_transfer(self, m, ft, TOX_FILE_CONTROL_CANCEL, msg, silent); } +void cmd_groupaccept(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) +{ + if (get_num_active_windows() >= MAX_WINDOWS_NUM) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, RED, " * Warning: Too many windows are open."); + return; + } + + if (Friends.list[self->num].group_invite.length == 0) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "No pending group invite"); + return; + } + + const char *passwd = NULL; + uint16_t passwd_len = 0; + + if (argc > 0) { + passwd = argv[1]; + passwd_len = strlen(passwd); + } + + int groupnumber = tox_group_accept_invite(m, Friends.list[self->num].group_invite.data, + Friends.list[self->num].group_invite.length, + (uint8_t *) passwd, passwd_len); + if (groupnumber == -1) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to join group."); + return; + } + + if (init_groupchat_win(m, groupnumber, NULL, 0) == -1) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group chat window failed to initialize."); + tox_group_delete(m, groupnumber, NULL, 0); + return; + } +} + void cmd_groupinvite(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) { if (argc < 1) { @@ -149,9 +184,6 @@ void cmd_savefile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv ft->state = FILE_TRANSFER_STARTED; return; - - - on_recv_error: switch (err) { diff --git a/src/chat_commands.h b/src/chat_commands.h index afe314e..ca4fd78 100644 --- a/src/chat_commands.h +++ b/src/chat_commands.h @@ -26,6 +26,7 @@ #include "windows.h" #include "toxic.h" +void cmd_groupaccept(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_groupinvite(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_cancelfile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_savefile(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]); diff --git a/src/execute.c b/src/execute.c index dd24f28..cd100b8 100644 --- a/src/execute.c +++ b/src/execute.c @@ -34,6 +34,8 @@ #include "misc_tools.h" #include "notify.h" +#define MAX_NUM_ARGS 10 /* Includes command */ + struct cmd_func { const char *name; void (*func)(WINDOW *w, ToxWindow *, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); @@ -67,6 +69,7 @@ static struct cmd_func global_commands[] = { static struct cmd_func chat_commands[] = { { "/cancel", cmd_cancelfile }, + { "/gaccept", cmd_groupaccept }, { "/invite", cmd_groupinvite }, { "/savefile", cmd_savefile }, { "/sendfile", cmd_sendfile }, @@ -84,6 +87,7 @@ static struct cmd_func chat_commands[] = { static struct cmd_func group_commands[] = { { "/chatid", cmd_chatid }, { "/ignore", cmd_ignore }, + { "/passwd", cmd_set_passwd }, { "/rejoin", cmd_rejoin }, { "/topic", cmd_set_topic }, { "/unignore", cmd_unignore }, @@ -94,15 +98,14 @@ static struct cmd_func group_commands[] = { { NULL, NULL }, }; -#define NUM_SPECIAL_COMMANDS 9 +#define NUM_SPECIAL_COMMANDS 8 static const char special_commands[NUM_SPECIAL_COMMANDS][MAX_CMDNAME_SIZE] = { - "/ban", - "/deop", + "/gaccept", "/group", "/ignore", "/nick", "/note", - "/op", + "/passwd", "/topic", "/unignore" }; @@ -194,6 +197,10 @@ static int parse_command(WINDOW *w, ToxWindow *self, const char *input, char (*a strcpy(cmd, tmp); /* tmp will always fit inside cmd */ } + /* Ugly special case concatinates all args after arg1 for multi-word group passwords */ + if (num_args > 2 && strcmp(args[0], "/join") == 0) + strcpy(args[2], input + strlen(args[0]) + 1 + strlen(args[1]) + 1); + free(cmd); return num_args; } diff --git a/src/execute.h b/src/execute.h index b755c8b..4daa360 100644 --- a/src/execute.h +++ b/src/execute.h @@ -26,8 +26,6 @@ #include "toxic.h" #include "windows.h" -#define MAX_NUM_ARGS 4 /* Includes command */ - enum { GLOBAL_COMMAND_MODE, CHAT_COMMAND_MODE, diff --git a/src/global_commands.c b/src/global_commands.c index 2223db7..84a0b2c 100644 --- a/src/global_commands.c +++ b/src/global_commands.c @@ -355,23 +355,6 @@ void cmd_groupchat(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*arg } } -static void join_invite(ToxWindow *self, Tox *m) -{ - int groupnumber = tox_group_accept_invite(m, Friends.list[self->num].group_invite.data, - Friends.list[self->num].group_invite.length); - - if (groupnumber == -1) { - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group chat instance failed to initialize."); - return; - } - - if (init_groupchat_win(m, groupnumber, NULL, 0) == -1) { - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group chat window failed to initialize."); - tox_group_delete(m, groupnumber, NULL, 0); - return; - } -} - void cmd_join(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) { if (get_num_active_windows() >= MAX_WINDOWS_NUM) { @@ -379,15 +362,9 @@ void cmd_join(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA return; } - /* If no input check for a group invite */ if (argc < 1) { - if (!self->is_chat || Friends.list[self->num].group_invite.length == 0) { - const char *msg = "You must either be invited to a group or input the group ID of the group you wish to join."; - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s", msg); - return; - } - - return join_invite(self, m); + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Chat ID is required."); + return; } const char *chat_id = argv[1]; @@ -416,10 +393,18 @@ void cmd_join(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA id_bin[i] = x; } - int groupnum = tox_group_new_join(m, (uint8_t *) id_bin); + const char *passwd = NULL; + uint16_t passwd_len = 0; + + if (argc > 1) { + passwd = argv[2]; + passwd_len = strlen(passwd); + } + + int groupnum = tox_group_new_join(m, (uint8_t *) id_bin, (uint8_t *) passwd, passwd_len); if (groupnum == -1) { - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group chat instance failed to initialize."); + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to join group."); return; } diff --git a/src/group_commands.c b/src/group_commands.c index 701e074..d72f97f 100644 --- a/src/group_commands.c +++ b/src/group_commands.c @@ -76,6 +76,42 @@ void cmd_ignore(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[ line_info_add(self, timefrmt, NULL, NULL, SYS_MSG, 1, BLUE, "-!- Ignoring %s", nick); } +void cmd_set_passwd(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) +{ + const char *passwd = NULL; + size_t len = 0; + + if (argc > 0) { + passwd = argv[1]; + len = strlen(passwd); + } + + if (len > TOX_MAX_GROUP_PASSWD_SIZE) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Password exceeds %d character limit", TOX_MAX_GROUP_PASSWD_SIZE); + return; + } + + int ret = tox_group_set_password(m, self->num, (uint8_t *) passwd, len); + + switch (ret) { + case 0: { + if (len > 0) + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Password has been set to %s", passwd); + else + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Password has been unset"); + return; + } + case -2: { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "You do not have permission to set the password"); + return; + } + default: { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Error setting password"); + return; + } + } +} + void cmd_rejoin(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) { if (tox_group_reconnect(m, self->num) == -1) @@ -111,7 +147,7 @@ void cmd_set_topic(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*arg char selfnick[TOX_MAX_NAME_LENGTH]; get_time_str(timefrmt, sizeof(timefrmt)); - + tox_self_get_name(m, (uint8_t *) selfnick); size_t sn_len = tox_self_get_name_size(m); selfnick[sn_len] = '\0'; diff --git a/src/group_commands.h b/src/group_commands.h index a9dc6c7..b1addf0 100644 --- a/src/group_commands.h +++ b/src/group_commands.h @@ -28,6 +28,7 @@ void cmd_chatid(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_ignore(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); +void cmd_set_passwd(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_rejoin(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_set_topic(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_unignore(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); diff --git a/src/groupchat.c b/src/groupchat.c index eb1a078..43d3be9 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 28 +#define AC_NUM_GROUP_COMMANDS 29 #else -#define AC_NUM_GROUP_COMMANDS 24 +#define AC_NUM_GROUP_COMMANDS 25 #endif /* AUDIO */ /* groupchat command names used for tab completion. */ @@ -97,6 +97,7 @@ static const char group_cmd_list[AC_NUM_GROUP_COMMANDS][MAX_CMDNAME_SIZE] = { { "/quit" }, { "/rejoin" }, { "/requests" }, + { "/passwd" }, { "/status" }, { "/topic" }, { "/unignore" }, @@ -552,8 +553,8 @@ static void groupchat_onGroupRejected(ToxWindow *self, Tox *m, int groupnum, uin case TOX_GJ_GROUP_FULL: msg = "Group is full. Try again with the 'rejoin' command."; break; - case TOX_GJ_INVITES_DISABLED: - msg = "Invites for this group have been disabled."; + case TOX_GJ_INCORRECT_PASSWORD: + msg = "Invalid password."; break; case TOX_GJ_INVITE_FAILED: msg = "Invite failed. Try again with the 'rejoin' command."; diff --git a/src/help.c b/src/help.c index b5c06e7..e656379 100644 --- a/src/help.c +++ b/src/help.c @@ -151,7 +151,7 @@ static void help_draw_global(ToxWindow *self) wprintw(win, " /status : Set status with optional note\n"); wprintw(win, " /note : Set a personal note\n"); wprintw(win, " /group : Create a group chat\n"); - wprintw(win, " /join : Join a group chat\n"); + wprintw(win, " /join : Join a group chat with optional password\n"); wprintw(win, " /nick : Set your nickname\n"); wprintw(win, " /log or : Enable/disable logging\n"); wprintw(win, " /myid : Print your Tox ID\n"); @@ -184,6 +184,7 @@ static void help_draw_chat(ToxWindow *self) wprintw(win, "Chat Commands:\n"); wattroff(win, A_BOLD | COLOR_PAIR(RED)); + wprintw(win, " /gaccept : Accept a group invite with optional password\n"); wprintw(win, " /sendfile : Send a file\n"); wprintw(win, " /savefile : Receive a file\n"); wprintw(win, " /cancel : Cancel file transfer where type: in|out\n"); @@ -244,7 +245,8 @@ static void help_draw_group(ToxWindow *self) wprintw(win, " /chatid : Print the group chat id to share with others.\n"); wprintw(win, " /ignore : Ignore peer\n"); - wprintw(win, " /rejoin : Rejoin the group (only works if not connected)\n"); + wprintw(win, " /passwd : Set group password (leave blank to unset)\n"); + wprintw(win, " /rejoin : Rejoin the group\n"); wprintw(win, " /topic : Set group topic (show current topic if no msg)\n"); wprintw(win, " /unignore : Unignore peer \n"); wprintw(win, " /whisper : Send private message to nick\n\n"); @@ -306,7 +308,7 @@ void help_onKey(ToxWindow *self, wint_t key) break; case 'r': - help_init_window(self, 6, 80); + help_init_window(self, 12, 80); self->help->type = HELP_GROUP; break; From 0481f4374694e987fe073cfc5f4c5d4e02392b19 Mon Sep 17 00:00:00 2001 From: JFreegman Date: Wed, 20 May 2015 21:00:28 -0400 Subject: [PATCH 33/45] Update .travis.yml --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 294c660..beb7aca 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,10 +2,10 @@ env: secure: m+RsGCgemJNMKbinD97PtjC1pUuFzDBrAol3tI6Z3xP1FE2qF0/efbcC5OyNwUWwcaqGRb83d0vWt4hzhxMwrwJC8O6EFLFHgJs0WpslP+++KRN30PUOqRFFqH404InF4pFNULlnwJYFZ8bGft4ThxppbEOeSYcXN4WSgb66RjM= before_script: - - sudo apt-get install curl + - sudo apt-get install wget script: - - curl https://jenkins.libtoxcore.so/job/toxic_linux_beta/build?token=$TOKEN + - wget -O temp https://jenkins.libtoxcore.so/job/toxic_linux_beta/build?token=$TOKEN && cat temp notifications: email: false From 29d0384a905c59d140435886fbd0e4bf068b95ec Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Fri, 22 May 2015 21:41:32 -0400 Subject: [PATCH 34/45] add ability for founder to set group privacy state --- src/execute.c | 1 + src/group_commands.c | 45 ++++++++++++++++++++++++++++++++++++++++++++ src/group_commands.h | 1 + src/groupchat.c | 7 ++++--- src/help.c | 3 ++- 5 files changed, 53 insertions(+), 4 deletions(-) diff --git a/src/execute.c b/src/execute.c index cd100b8..927e5f4 100644 --- a/src/execute.c +++ b/src/execute.c @@ -88,6 +88,7 @@ static struct cmd_func group_commands[] = { { "/chatid", cmd_chatid }, { "/ignore", cmd_ignore }, { "/passwd", cmd_set_passwd }, + { "/privacy", cmd_set_privacy }, { "/rejoin", cmd_rejoin }, { "/topic", cmd_set_topic }, { "/unignore", cmd_unignore }, diff --git a/src/group_commands.c b/src/group_commands.c index d72f97f..734a823 100644 --- a/src/group_commands.c +++ b/src/group_commands.c @@ -112,6 +112,51 @@ void cmd_set_passwd(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*ar } } +void cmd_set_privacy(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) +{ + const char *pstate_str = NULL; + TOX_GROUP_PRIVACY_STATE privacy_state; + + if (argc < 1) { + privacy_state = tox_group_get_privacy_state(m, self->num); + + if (privacy_state == TOX_GP_INVALID) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to retrieve privacy state"); + return; + } + + pstate_str = privacy_state == TOX_GP_PRIVATE ? "private" : "public"; + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Privacy state is set to %s.", pstate_str); + return; + } + + pstate_str = argv[1]; + + if (strcasecmp(pstate_str, "private") != 0 && strcasecmp(pstate_str, "public") != 0) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Privacy state must be \"private\" or \"public\"."); + return; + } + + privacy_state = strcasecmp(pstate_str, "private") == 0 ? TOX_GP_PRIVATE : TOX_GP_PUBLIC; + + int ret = tox_group_set_privacy_state(m, self->num, privacy_state); + + switch (ret) { + case 0: { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Privacy state has been set to %s.", pstate_str); + return; + } + case -2: { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "You do not have permission to set the privacy state."); + return; + } + default: { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Error setting privacy state."); + return; + } + } +} + void cmd_rejoin(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) { if (tox_group_reconnect(m, self->num) == -1) diff --git a/src/group_commands.h b/src/group_commands.h index b1addf0..8d83043 100644 --- a/src/group_commands.h +++ b/src/group_commands.h @@ -29,6 +29,7 @@ void cmd_chatid(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_ignore(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_set_passwd(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); +void cmd_set_privacy(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_rejoin(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_set_topic(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_unignore(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); diff --git a/src/groupchat.c b/src/groupchat.c index 43d3be9..d966f4a 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 29 +#define AC_NUM_GROUP_COMMANDS 30 #else -#define AC_NUM_GROUP_COMMANDS 25 +#define AC_NUM_GROUP_COMMANDS 26 #endif /* AUDIO */ /* groupchat command names used for tab completion. */ @@ -94,10 +94,11 @@ static const char group_cmd_list[AC_NUM_GROUP_COMMANDS][MAX_CMDNAME_SIZE] = { { "/myid" }, { "/nick" }, { "/note" }, + { "/passwd" }, + { "/privacy" }, { "/quit" }, { "/rejoin" }, { "/requests" }, - { "/passwd" }, { "/status" }, { "/topic" }, { "/unignore" }, diff --git a/src/help.c b/src/help.c index e656379..973c05a 100644 --- a/src/help.c +++ b/src/help.c @@ -246,6 +246,7 @@ static void help_draw_group(ToxWindow *self) wprintw(win, " /chatid : Print the group chat id to share with others.\n"); wprintw(win, " /ignore : Ignore peer\n"); wprintw(win, " /passwd : Set group password (leave blank to unset)\n"); + wprintw(win, " /privacy : Set group privacy state: private|public\n"); wprintw(win, " /rejoin : Rejoin the group\n"); wprintw(win, " /topic : Set group topic (show current topic if no msg)\n"); wprintw(win, " /unignore : Unignore peer \n"); @@ -308,7 +309,7 @@ void help_onKey(ToxWindow *self, wint_t key) break; case 'r': - help_init_window(self, 12, 80); + help_init_window(self, 13, 80); self->help->type = HELP_GROUP; break; From a6d7e9b83930f4b2dde18255e7cadb9c3a658327 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Sun, 24 May 2015 03:27:50 -0400 Subject: [PATCH 35/45] add ability for founder to set group peer limit --- src/execute.c | 21 +++++++++++---------- src/group_commands.c | 42 ++++++++++++++++++++++++++++++++++++++++++ src/group_commands.h | 1 + src/groupchat.c | 5 +++-- src/help.c | 3 ++- 5 files changed, 59 insertions(+), 13 deletions(-) diff --git a/src/execute.c b/src/execute.c index 927e5f4..f4b4d9f 100644 --- a/src/execute.c +++ b/src/execute.c @@ -85,18 +85,19 @@ static struct cmd_func chat_commands[] = { }; static struct cmd_func group_commands[] = { - { "/chatid", cmd_chatid }, - { "/ignore", cmd_ignore }, - { "/passwd", cmd_set_passwd }, - { "/privacy", cmd_set_privacy }, - { "/rejoin", cmd_rejoin }, - { "/topic", cmd_set_topic }, - { "/unignore", cmd_unignore }, + { "/chatid", cmd_chatid }, + { "/ignore", cmd_ignore }, + { "/passwd", cmd_set_passwd }, + { "/peerlimit", cmd_set_peerlimit }, + { "/privacy", cmd_set_privacy }, + { "/rejoin", cmd_rejoin }, + { "/topic", cmd_set_topic }, + { "/unignore", cmd_unignore }, #ifdef AUDIO - { "/mute", cmd_mute }, - { "/sense", cmd_sense }, + { "/mute", cmd_mute }, + { "/sense", cmd_sense }, #endif /* AUDIO */ - { NULL, NULL }, + { NULL, NULL }, }; #define NUM_SPECIAL_COMMANDS 8 diff --git a/src/group_commands.c b/src/group_commands.c index 734a823..92cc4d2 100644 --- a/src/group_commands.c +++ b/src/group_commands.c @@ -21,6 +21,7 @@ */ #include +#include #include "toxic.h" #include "windows.h" @@ -112,6 +113,47 @@ void cmd_set_passwd(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*ar } } +void cmd_set_peerlimit(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) +{ + int maxpeers = 0; + + if (argc < 1) { + maxpeers = tox_group_get_peer_limit(m, self->num); + + if (maxpeers == -1) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to retrieve peer limit"); + return; + } + + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Peer limit is set to %d", maxpeers); + return; + } + + maxpeers = atoi(argv[1]); + + if (maxpeers <= 0) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Peer limit must be a value greater than 0"); + return; + } + + int ret = tox_group_set_peer_limit(m, self->num, (uint32_t) maxpeers); + + switch (ret) { + case 0: { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Peer limit has been set to %d", maxpeers); + return; + } + case -2: { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "You do not have permission to set the peer limit."); + return; + } + default: { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set the peer limit"); + return; + } + } +} + void cmd_set_privacy(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) { const char *pstate_str = NULL; diff --git a/src/group_commands.h b/src/group_commands.h index 8d83043..bd536c0 100644 --- a/src/group_commands.h +++ b/src/group_commands.h @@ -29,6 +29,7 @@ void cmd_chatid(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_ignore(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_set_passwd(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); +void cmd_set_peerlimit(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_set_privacy(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_rejoin(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_set_topic(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); diff --git a/src/groupchat.c b/src/groupchat.c index d966f4a..e37e565 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 30 +#define AC_NUM_GROUP_COMMANDS 31 #else -#define AC_NUM_GROUP_COMMANDS 26 +#define AC_NUM_GROUP_COMMANDS 27 #endif /* AUDIO */ /* groupchat command names used for tab completion. */ @@ -95,6 +95,7 @@ static const char group_cmd_list[AC_NUM_GROUP_COMMANDS][MAX_CMDNAME_SIZE] = { { "/nick" }, { "/note" }, { "/passwd" }, + { "/peerlimit" }, { "/privacy" }, { "/quit" }, { "/rejoin" }, diff --git a/src/help.c b/src/help.c index 973c05a..4f0f065 100644 --- a/src/help.c +++ b/src/help.c @@ -246,6 +246,7 @@ static void help_draw_group(ToxWindow *self) wprintw(win, " /chatid : Print the group chat id to share with others.\n"); wprintw(win, " /ignore : Ignore peer\n"); wprintw(win, " /passwd : Set group password (leave blank to unset)\n"); + wprintw(win, " /peerlimit : Set group peer limit\n"); wprintw(win, " /privacy : Set group privacy state: private|public\n"); wprintw(win, " /rejoin : Rejoin the group\n"); wprintw(win, " /topic : Set group topic (show current topic if no msg)\n"); @@ -309,7 +310,7 @@ void help_onKey(ToxWindow *self, wint_t key) break; case 'r': - help_init_window(self, 13, 80); + help_init_window(self, 14, 80); self->help->type = HELP_GROUP; break; From 526bd02189800c3085c11f3264db38d53d726a93 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Tue, 26 May 2015 01:23:09 -0400 Subject: [PATCH 36/45] Add group peer kicking && update related callback --- src/execute.c | 4 +++- src/group_commands.c | 37 +++++++++++++++++++++++++++++++++++-- src/group_commands.h | 1 + src/groupchat.c | 44 +++++++++++++++++++++++--------------------- src/help.c | 3 ++- src/toxic.c | 2 +- src/toxic.h | 4 +++- src/windows.c | 22 +++++++++++----------- src/windows.h | 2 +- 9 files changed, 80 insertions(+), 39 deletions(-) diff --git a/src/execute.c b/src/execute.c index f4b4d9f..5a505f1 100644 --- a/src/execute.c +++ b/src/execute.c @@ -87,6 +87,7 @@ static struct cmd_func chat_commands[] = { static struct cmd_func group_commands[] = { { "/chatid", cmd_chatid }, { "/ignore", cmd_ignore }, + { "/kick", cmd_kick }, { "/passwd", cmd_set_passwd }, { "/peerlimit", cmd_set_peerlimit }, { "/privacy", cmd_set_privacy }, @@ -100,11 +101,12 @@ static struct cmd_func group_commands[] = { { NULL, NULL }, }; -#define NUM_SPECIAL_COMMANDS 8 +#define NUM_SPECIAL_COMMANDS 9 static const char special_commands[NUM_SPECIAL_COMMANDS][MAX_CMDNAME_SIZE] = { "/gaccept", "/group", "/ignore", + "/kick", "/nick", "/note", "/passwd", diff --git a/src/group_commands.c b/src/group_commands.c index 92cc4d2..b020b57 100644 --- a/src/group_commands.c +++ b/src/group_commands.c @@ -54,7 +54,7 @@ void cmd_chatid(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[ void cmd_ignore(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) { if (argc < 1) { - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Who do you want to ignore?"); + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Peer name must be specified."); return; } @@ -62,7 +62,7 @@ void cmd_ignore(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[ int peernum = group_get_nick_peernumber(self->num, nick); if (peernum == -1) { - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Peer '%s' does not exist", nick); + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid peer name"); return; } @@ -77,6 +77,39 @@ void cmd_ignore(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[ line_info_add(self, timefrmt, NULL, NULL, SYS_MSG, 1, BLUE, "-!- Ignoring %s", nick); } +void cmd_kick(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) +{ + if (argc < 1) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Peer name must be specified."); + return; + } + + const char *nick = argv[1]; + int peernumber = group_get_nick_peernumber(self->num, nick); + + if (peernumber == -1) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid peer name"); + return; + } + + int ret = tox_group_op_kick_peer(m, self->num, (uint32_t) peernumber); + + switch (ret) { + case 0: { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "You have kicked %s from the group.", nick); + return; + } + case -1: { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to kick %s from the group.", nick); + return; + } + case -2: { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "You do not have permission to kick %s.", nick); + return; + } + } +} + void cmd_set_passwd(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) { const char *passwd = NULL; diff --git a/src/group_commands.h b/src/group_commands.h index bd536c0..0a43291 100644 --- a/src/group_commands.h +++ b/src/group_commands.h @@ -28,6 +28,7 @@ void cmd_chatid(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_ignore(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); +void cmd_kick(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_set_passwd(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_set_peerlimit(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_set_privacy(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); diff --git a/src/groupchat.c b/src/groupchat.c index e37e565..4a0f242 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 31 +#define AC_NUM_GROUP_COMMANDS 32 #else -#define AC_NUM_GROUP_COMMANDS 27 +#define AC_NUM_GROUP_COMMANDS 28 #endif /* AUDIO */ /* groupchat command names used for tab completion. */ @@ -90,6 +90,7 @@ static const char group_cmd_list[AC_NUM_GROUP_COMMANDS][MAX_CMDNAME_SIZE] = { { "/help" }, { "/ignore" }, { "/join" }, + { "/kick" }, { "/log" }, { "/myid" }, { "/nick" }, @@ -210,9 +211,9 @@ void set_nick_all_groups(Tox *m, const char *nick, uint16_t length) int ret = tox_group_set_self_name(m, groupchats[i].groupnumber, (uint8_t *) nick, length); if (ret == -1 && groupchats[i].is_connected) - line_info_add(self, timefrmt, NULL, 0, SYS_MSG, 0, 0, "Invalid nick"); + line_info_add(self, NULL, NULL, 0, SYS_MSG, 0, 0, "Invalid nick"); else if (ret == -2) - line_info_add(self, timefrmt, NULL, 0, SYS_MSG, 0, RED, "-!- That nick is already in use"); + line_info_add(self, NULL, NULL, 0, SYS_MSG, 0, RED, "-!- That nick is already in use"); else line_info_add(self, timefrmt, NULL, nick, NAME_CHANGE, 0, MAGENTA, "You are now known as "); } @@ -571,32 +572,33 @@ static void groupchat_onGroupRejected(ToxWindow *self, Tox *m, int groupnum, uin line_info_add(self, timefrmt, NULL, NULL, SYS_MSG, 0, RED, "-!- %s", msg); } -static void groupchat_onGroupOpCertificate(ToxWindow *self, Tox *m, int groupnum, uint32_t src_peernum, - uint32_t tgt_peernum, uint8_t type) +static void groupchat_onGroupModeration(ToxWindow *self, Tox *m, int groupnum, uint32_t src_peernum, + uint32_t tgt_peernum, TOX_GROUP_MOD_TYPE type) { if (groupnum != self->num) return; char src_name[TOX_MAX_NAME_LENGTH]; - get_group_nick_truncate(m, src_name, src_peernum, groupnum); - char tgt_name[TOX_MAX_NAME_LENGTH]; - get_group_nick_truncate(m, tgt_name, tgt_peernum, groupnum); - const char *msg = NULL; + if (get_group_nick_truncate(m, src_name, src_peernum, groupnum) == -1) + return; + + if (get_group_nick_truncate(m, tgt_name, tgt_peernum, groupnum) == -1) + return; + + const char *eventstr = NULL; + int colour = RED; switch (type) { - case TOX_GC_BAN: - msg = "has banned"; + case TOX_MOD_KICK: + eventstr = "kicked"; break; - case TOX_GC_PROMOTE_OP: - msg = "has given operator status to"; + case TOX_MOD_BAN: + eventstr = "banned"; break; - case TOX_GC_REVOKE_OP: - msg = "has removed operator status from"; - break; - case TOX_GC_SILENCE: - msg = "has silenced"; + case TOX_MOD_SILENCE: + eventstr = "silenced"; break; default: return; @@ -604,7 +606,7 @@ static void groupchat_onGroupOpCertificate(ToxWindow *self, Tox *m, int groupnum char timefrmt[TIME_STR_SIZE]; get_time_str(timefrmt, sizeof(timefrmt)); - line_info_add(self, timefrmt, src_name, tgt_name, NAME_CHANGE, 0, MAGENTA, "%s", msg); + line_info_add(self, timefrmt, NULL, NULL, SYS_MSG, 1, colour, "-!- %s has been %s by %s", tgt_name, eventstr, src_name); } static void groupchat_onGroupNickChange(ToxWindow *self, Tox *m, int groupnum, uint32_t peernum, @@ -952,10 +954,10 @@ ToxWindow new_group_chat(Tox *m, int groupnum, const char *groupname, int length ret.onGroupPeerJoin = &groupchat_onGroupPeerJoin; ret.onGroupPeerExit = &groupchat_onGroupPeerExit; ret.onGroupTopicChange = &groupchat_onGroupTopicChange; - ret.onGroupOpCertificate = &groupchat_onGroupOpCertificate; ret.onGroupNickChange = &groupchat_onGroupNickChange; ret.onGroupSelfJoin = &groupchat_onGroupSelfJoin; ret.onGroupRejected = &groupchat_onGroupRejected; + ret.onGroupModeration = &groupchat_onGroupModeration; ChatContext *chatwin = calloc(1, sizeof(ChatContext)); Help *help = calloc(1, sizeof(Help)); diff --git a/src/help.c b/src/help.c index 4f0f065..21912ab 100644 --- a/src/help.c +++ b/src/help.c @@ -245,6 +245,7 @@ static void help_draw_group(ToxWindow *self) wprintw(win, " /chatid : Print the group chat id to share with others.\n"); wprintw(win, " /ignore : Ignore peer\n"); + wprintw(win, " /kick : Kick peer\n"); wprintw(win, " /passwd : Set group password (leave blank to unset)\n"); wprintw(win, " /peerlimit : Set group peer limit\n"); wprintw(win, " /privacy : Set group privacy state: private|public\n"); @@ -310,7 +311,7 @@ void help_onKey(ToxWindow *self, wint_t key) break; case 'r': - help_init_window(self, 14, 80); + help_init_window(self, 15, 80); self->help->type = HELP_GROUP; break; diff --git a/src/toxic.c b/src/toxic.c index f699450..e874925 100644 --- a/src/toxic.c +++ b/src/toxic.c @@ -571,7 +571,6 @@ static void init_tox_callbacks(Tox *m) tox_callback_group_message(m, on_group_message, NULL); tox_callback_group_action(m, on_group_action, NULL); tox_callback_group_private_message(m, on_group_private_message, NULL); - tox_callback_group_op_certificate(m, on_group_op_certificate, NULL); tox_callback_group_peerlist_update(m, on_group_namelistchange, NULL); tox_callback_group_peer_join(m, on_group_peer_join, NULL); tox_callback_group_peer_exit(m, on_group_peer_exit, NULL); @@ -579,6 +578,7 @@ static void init_tox_callbacks(Tox *m) tox_callback_group_topic_change(m, on_group_topic_change, NULL); tox_callback_group_self_join(m, on_group_self_join, NULL); tox_callback_group_rejected(m, on_group_rejected, NULL); + tox_callback_group_moderation(m, on_group_moderation, NULL); } static void init_tox_options(struct Tox_Options *tox_opts) diff --git a/src/toxic.h b/src/toxic.h index 2a7680a..de02c0b 100644 --- a/src/toxic.h +++ b/src/toxic.h @@ -125,7 +125,9 @@ void on_group_peer_join(Tox *m, int groupnumber, uint32_t peernumber, void *user void on_group_peer_exit(Tox *m, int groupnumber, uint32_t peernumber, const uint8_t *partmsg, uint16_t length, void *userdata); void on_group_topic_change(Tox *m, int groupnumber, uint32_t peernumber, const uint8_t *topic, uint16_t length, void *userdata); void on_group_nick_change(Tox *m, int groupnumber, uint32_t peernumber, const uint8_t *newname, uint16_t length, void *userdata); -void on_group_op_certificate(Tox *m, int groupnumber, uint32_t src_peernum, uint32_t tgt_peernum, uint8_t cert_type, void *userdata); void on_group_self_join(Tox *m, int groupnumber, void *userdata); void on_group_rejected(Tox *m, int groupnumber, uint8_t type, void *userdata); +void on_group_moderation(Tox *m, int groupnumber, uint32_t source_peernum, uint32_t target_peernum, + TOX_GROUP_MOD_TYPE type, void *userdata); + #endif /* #define TOXIC_H */ diff --git a/src/windows.c b/src/windows.c index 9801a1a..d7e1e95 100644 --- a/src/windows.c +++ b/src/windows.c @@ -272,17 +272,6 @@ void on_group_nick_change(Tox *m, int groupnumber, uint32_t peernumber, const ui } } -void on_group_op_certificate(Tox *m, int groupnumber, uint32_t src_peernum, uint32_t tgt_peernum, uint8_t cert_type, - void *userdata) -{ - size_t i; - - for (i = 0; i < MAX_WINDOWS_NUM; ++i) { - if (windows[i].onGroupOpCertificate != NULL) - windows[i].onGroupOpCertificate(&windows[i], m, groupnumber, src_peernum, tgt_peernum, cert_type); - } -} - void on_group_self_join(Tox *m, int groupnumber, void *userdata) { size_t i; @@ -303,6 +292,17 @@ void on_group_rejected(Tox *m, int groupnumber, uint8_t type, void *userdata) } } +void on_group_moderation(Tox *m, int groupnumber, uint32_t source_peernum, uint32_t target_peernum, + TOX_GROUP_MOD_TYPE type, void *userdata) +{ + size_t i; + + for (i = 0; i < MAX_WINDOWS_NUM; ++i) { + if (windows[i].onGroupModeration != NULL) + windows[i].onGroupModeration(&windows[i], m, groupnumber, source_peernum, target_peernum, type); + } +} + void on_file_chunk_request(Tox *m, uint32_t friendnumber, uint32_t filenumber, uint64_t position, size_t length, void *userdata) { diff --git a/src/windows.h b/src/windows.h index 9bfa502..1df5ee2 100644 --- a/src/windows.h +++ b/src/windows.h @@ -130,7 +130,6 @@ struct ToxWindow { void(*onGroupMessage)(ToxWindow *, Tox *, int, int, const char *, uint16_t); void(*onGroupAction)(ToxWindow *, Tox *, int, int, const char *, uint16_t); void(*onGroupPrivateMessage)(ToxWindow *, Tox *, int, uint32_t, const char *, uint16_t); - void(*onGroupOpCertificate)(ToxWindow *, Tox *, int, uint32_t, uint32_t, uint8_t); void(*onGroupNamelistChange)(ToxWindow *, Tox *, int); void(*onGroupPeerJoin)(ToxWindow *, Tox *, int, uint32_t); void(*onGroupPeerExit)(ToxWindow *, Tox *, int, uint32_t, const char *, uint16_t); @@ -138,6 +137,7 @@ struct ToxWindow { void(*onGroupTopicChange)(ToxWindow *, Tox *, int, uint32_t, const char *, uint16_t); void(*onGroupSelfJoin)(ToxWindow *, Tox *, int); void(*onGroupRejected)(ToxWindow *, Tox *, int, uint8_t); + void(*onGroupModeration)(ToxWindow *, Tox *, int, uint32_t, uint32_t, TOX_GROUP_MOD_TYPE); #ifdef AUDIO From 9cd8afe90a716bb1169f46a6a08a2b0473f99fe6 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Fri, 29 May 2015 02:00:18 -0400 Subject: [PATCH 37/45] add mod and unmod commands --- src/execute.c | 8 +++-- src/group_commands.c | 72 ++++++++++++++++++++++++++++++++++++++++-- src/group_commands.h | 2 ++ src/groupchat.c | 75 +++++++++++++++++++++++++++++--------------- src/toxic.h | 2 +- src/windows.c | 2 +- src/windows.h | 2 +- 7 files changed, 130 insertions(+), 33 deletions(-) diff --git a/src/execute.c b/src/execute.c index 5a505f1..9ff54c3 100644 --- a/src/execute.c +++ b/src/execute.c @@ -88,12 +88,14 @@ static struct cmd_func group_commands[] = { { "/chatid", cmd_chatid }, { "/ignore", cmd_ignore }, { "/kick", cmd_kick }, + { "/mod", cmd_mod }, { "/passwd", cmd_set_passwd }, { "/peerlimit", cmd_set_peerlimit }, { "/privacy", cmd_set_privacy }, { "/rejoin", cmd_rejoin }, { "/topic", cmd_set_topic }, { "/unignore", cmd_unignore }, + { "/unmod", cmd_unmod }, #ifdef AUDIO { "/mute", cmd_mute }, { "/sense", cmd_sense }, @@ -101,17 +103,19 @@ static struct cmd_func group_commands[] = { { NULL, NULL }, }; -#define NUM_SPECIAL_COMMANDS 9 +#define NUM_SPECIAL_COMMANDS 11 static const char special_commands[NUM_SPECIAL_COMMANDS][MAX_CMDNAME_SIZE] = { "/gaccept", "/group", "/ignore", "/kick", + "/mod", "/nick", "/note", "/passwd", "/topic", - "/unignore" + "/unignore", + "/unmod", }; /* return true if input command is in the special_commands array. False otherwise.*/ diff --git a/src/group_commands.c b/src/group_commands.c index b020b57..d6a1f38 100644 --- a/src/group_commands.c +++ b/src/group_commands.c @@ -96,7 +96,7 @@ void cmd_kick(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA switch (ret) { case 0: { - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "You have kicked %s from the group.", nick); + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 1, RED, "You have kicked %s from the group.", nick); return; } case -1: { @@ -110,6 +110,72 @@ void cmd_kick(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA } } +void cmd_mod(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) +{ + if (argc < 1) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Peer name must be specified."); + return; + } + + const char *nick = argv[1]; + int peernumber = group_get_nick_peernumber(self->num, nick); + + if (peernumber == -1) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid peer name."); + return; + } + + int ret = tox_group_set_peer_role(m, self->num, peernumber, TOX_GR_MODERATOR); + + switch (ret) { + case 0: { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 1, BLUE, "You have promoted %s to moderator.", nick); + return; + } + case -1: { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to promote peer to moderator"); + return; + } + case -2: { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "You do not have permission to promote moderators."); + return; + } + } +} + +void cmd_unmod(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) +{ + if (argc < 1) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Peer name must be specified."); + return; + } + + const char *nick = argv[1]; + int peernumber = group_get_nick_peernumber(self->num, nick); + + if (peernumber == -1) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid peer name."); + return; + } + + int ret = tox_group_set_peer_role(m, self->num, peernumber, TOX_GR_USER); + + switch (ret) { + case 0: { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 1, BLUE, "You have revoked moderator powers from %s.", nick); + return; + } + case -1: { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to revoke moderator powers from %s.", nick); + return; + } + case -2: { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Nice try."); + return; + } + } +} + void cmd_set_passwd(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) { const char *passwd = NULL; @@ -234,8 +300,10 @@ void cmd_set_privacy(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*a void cmd_rejoin(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) { - if (tox_group_reconnect(m, self->num) == -1) + if (tox_group_reconnect(m, self->num) == -1) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to rejoin group."); return; + } line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Reconnecting to group..."); } diff --git a/src/group_commands.h b/src/group_commands.h index 0a43291..477bf0e 100644 --- a/src/group_commands.h +++ b/src/group_commands.h @@ -29,11 +29,13 @@ void cmd_chatid(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_ignore(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_kick(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); +void cmd_mod(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_set_passwd(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_set_peerlimit(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_set_privacy(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_rejoin(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_set_topic(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_unignore(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); +void cmd_unmod(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); #endif /* GROUP_COMMANDS_H */ diff --git a/src/groupchat.c b/src/groupchat.c index 4a0f242..8d338cf 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 32 +#define AC_NUM_GROUP_COMMANDS 34 #else -#define AC_NUM_GROUP_COMMANDS 28 +#define AC_NUM_GROUP_COMMANDS 30 #endif /* AUDIO */ /* groupchat command names used for tab completion. */ @@ -92,6 +92,7 @@ static const char group_cmd_list[AC_NUM_GROUP_COMMANDS][MAX_CMDNAME_SIZE] = { { "/join" }, { "/kick" }, { "/log" }, + { "/mod" }, { "/myid" }, { "/nick" }, { "/note" }, @@ -104,6 +105,7 @@ static const char group_cmd_list[AC_NUM_GROUP_COMMANDS][MAX_CMDNAME_SIZE] = { { "/status" }, { "/topic" }, { "/unignore" }, + { "/unmod" }, { "/whisper" }, #ifdef AUDIO @@ -573,7 +575,7 @@ static void groupchat_onGroupRejected(ToxWindow *self, Tox *m, int groupnum, uin } static void groupchat_onGroupModeration(ToxWindow *self, Tox *m, int groupnum, uint32_t src_peernum, - uint32_t tgt_peernum, TOX_GROUP_MOD_TYPE type) + uint32_t tgt_peernum, TOX_GROUP_MOD_EVENT type) { if (groupnum != self->num) return; @@ -587,26 +589,28 @@ static void groupchat_onGroupModeration(ToxWindow *self, Tox *m, int groupnum, u if (get_group_nick_truncate(m, tgt_name, tgt_peernum, groupnum) == -1) return; - const char *eventstr = NULL; - int colour = RED; + char timefrmt[TIME_STR_SIZE]; + get_time_str(timefrmt, sizeof(timefrmt)); switch (type) { - case TOX_MOD_KICK: - eventstr = "kicked"; + case TOX_GROUP_MOD_EVENT_KICK: + line_info_add(self, timefrmt, NULL, NULL, SYS_MSG, 1, RED, "-!- %s has been kicked by %s", tgt_name, src_name); break; - case TOX_MOD_BAN: - eventstr = "banned"; + case TOX_GROUP_MOD_EVENT_BAN: + line_info_add(self, timefrmt, NULL, NULL, SYS_MSG, 1, RED, "-!- %s has been banned by %s", tgt_name, src_name); break; - case TOX_MOD_SILENCE: - eventstr = "silenced"; + case TOX_GROUP_MOD_EVENT_OBSERVER: + line_info_add(self, timefrmt, NULL, NULL, SYS_MSG, 1, BLUE, "-!- %s has been silenced by %s", tgt_name, src_name); + break; + case TOX_GROUP_MOD_EVENT_USER: + line_info_add(self, timefrmt, NULL, NULL, SYS_MSG, 1, BLUE, "-!- %s has been user'd by %s", tgt_name, src_name); + break; + case TOX_GROUP_MOD_EVENT_MODERATOR: + line_info_add(self, timefrmt, NULL, NULL, SYS_MSG, 1, BLUE, "-!- %s has been promoted to moderator by %s", tgt_name, src_name); break; default: return; } - - char timefrmt[TIME_STR_SIZE]; - get_time_str(timefrmt, sizeof(timefrmt)); - line_info_add(self, timefrmt, NULL, NULL, SYS_MSG, 1, colour, "-!- %s has been %s by %s", tgt_name, eventstr, src_name); } static void groupchat_onGroupNickChange(ToxWindow *self, Tox *m, int groupnum, uint32_t peernum, @@ -867,29 +871,48 @@ static void groupchat_onDraw(ToxWindow *self, Tox *m) wmove(ctx->sidebar, i + 2, 1); int peer = i + groupchats[self->num].side_pos; + /* TODO: Make this not poll */ + pthread_mutex_lock(&Winthread.lock); + uint8_t status = tox_group_get_status(m, self->num, i); + TOX_GROUP_ROLE role = tox_group_get_role(m, self->num, i); + pthread_mutex_unlock(&Winthread.lock); + + int maxlen_offset = role == TOX_GR_USER ? 2 : 3; + /* truncate nick to fit in side panel without modifying list */ char tmpnck[TOX_MAX_NAME_LENGTH]; - int maxlen = SIDEBAR_WIDTH - 2; + int maxlen = SIDEBAR_WIDTH - maxlen_offset; pthread_mutex_lock(&Winthread.lock); memcpy(tmpnck, &groupchats[self->num].peer_names[peer * TOX_MAX_NAME_LENGTH], maxlen); pthread_mutex_unlock(&Winthread.lock); tmpnck[maxlen] = '\0'; - /* TODO: Make this not poll */ - pthread_mutex_lock(&Winthread.lock); - uint8_t status = tox_group_get_status(m, self->num, i); - pthread_mutex_unlock(&Winthread.lock); - - int colour = WHITE; + int namecolour = WHITE; if (status == TOX_GS_AWAY) - colour = YELLOW; + namecolour = YELLOW; else if (status == TOX_GS_BUSY) - colour = RED; + namecolour = RED; - wattron(ctx->sidebar, COLOR_PAIR(colour)); + /* Signify roles (e.g. founder, moderator) */ + const char *rolesig = ""; + int rolecolour = WHITE; + + if (role == TOX_GR_FOUNDER) { + rolesig = "&"; + rolecolour = BLUE; + } else if (role == TOX_GR_MODERATOR) { + rolesig = "+"; + rolecolour = GREEN; + } + + wattron(ctx->sidebar, COLOR_PAIR(rolecolour) | A_BOLD); + wprintw(ctx->sidebar, "%s", rolesig); + wattroff(ctx->sidebar, COLOR_PAIR(rolecolour) | A_BOLD); + + wattron(ctx->sidebar, COLOR_PAIR(namecolour)); wprintw(ctx->sidebar, "%s\n", tmpnck); - wattroff(ctx->sidebar, COLOR_PAIR(colour)); + wattroff(ctx->sidebar, COLOR_PAIR(namecolour)); } } diff --git a/src/toxic.h b/src/toxic.h index de02c0b..da92087 100644 --- a/src/toxic.h +++ b/src/toxic.h @@ -128,6 +128,6 @@ void on_group_nick_change(Tox *m, int groupnumber, uint32_t peernumber, const ui void on_group_self_join(Tox *m, int groupnumber, void *userdata); void on_group_rejected(Tox *m, int groupnumber, uint8_t type, void *userdata); void on_group_moderation(Tox *m, int groupnumber, uint32_t source_peernum, uint32_t target_peernum, - TOX_GROUP_MOD_TYPE type, void *userdata); + TOX_GROUP_MOD_EVENT type, void *userdata); #endif /* #define TOXIC_H */ diff --git a/src/windows.c b/src/windows.c index d7e1e95..e59e81b 100644 --- a/src/windows.c +++ b/src/windows.c @@ -293,7 +293,7 @@ void on_group_rejected(Tox *m, int groupnumber, uint8_t type, void *userdata) } void on_group_moderation(Tox *m, int groupnumber, uint32_t source_peernum, uint32_t target_peernum, - TOX_GROUP_MOD_TYPE type, void *userdata) + TOX_GROUP_MOD_EVENT type, void *userdata) { size_t i; diff --git a/src/windows.h b/src/windows.h index 1df5ee2..c9b0291 100644 --- a/src/windows.h +++ b/src/windows.h @@ -137,7 +137,7 @@ struct ToxWindow { void(*onGroupTopicChange)(ToxWindow *, Tox *, int, uint32_t, const char *, uint16_t); void(*onGroupSelfJoin)(ToxWindow *, Tox *, int); void(*onGroupRejected)(ToxWindow *, Tox *, int, uint8_t); - void(*onGroupModeration)(ToxWindow *, Tox *, int, uint32_t, uint32_t, TOX_GROUP_MOD_TYPE); + void(*onGroupModeration)(ToxWindow *, Tox *, int, uint32_t, uint32_t, TOX_GROUP_MOD_EVENT); #ifdef AUDIO From 7e7087e94e8569e6c14e128b340c51462ed3aaeb Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Sat, 30 May 2015 23:57:30 -0400 Subject: [PATCH 38/45] add mod-list prune command --- src/execute.c | 1 + src/group_commands.c | 16 +++++++++++++++- src/group_commands.h | 1 + src/groupchat.c | 2 +- 4 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/execute.c b/src/execute.c index 9ff54c3..e23a64f 100644 --- a/src/execute.c +++ b/src/execute.c @@ -92,6 +92,7 @@ static struct cmd_func group_commands[] = { { "/passwd", cmd_set_passwd }, { "/peerlimit", cmd_set_peerlimit }, { "/privacy", cmd_set_privacy }, + { "/prune", cmd_prune }, { "/rejoin", cmd_rejoin }, { "/topic", cmd_set_topic }, { "/unignore", cmd_unignore }, diff --git a/src/group_commands.c b/src/group_commands.c index d6a1f38..c48f2d9 100644 --- a/src/group_commands.c +++ b/src/group_commands.c @@ -92,7 +92,7 @@ void cmd_kick(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA return; } - int ret = tox_group_op_kick_peer(m, self->num, (uint32_t) peernumber); + int ret = tox_group_kick_peer(m, self->num, (uint32_t) peernumber); switch (ret) { case 0: { @@ -140,9 +140,23 @@ void cmd_mod(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "You do not have permission to promote moderators."); return; } + case -3: { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Moderator list is full. Use the \"/prune\" command to remove all offline mods from the mod list."); + return; + } } } +void cmd_prune(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) +{ + if (tox_group_prune_moderator_list(m, self->num) == -1) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to prune moderator list."); + return; + } + + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Moderator list has been successfully pruned."); +} + void cmd_unmod(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) { if (argc < 1) { diff --git a/src/group_commands.h b/src/group_commands.h index 477bf0e..9276e90 100644 --- a/src/group_commands.h +++ b/src/group_commands.h @@ -30,6 +30,7 @@ void cmd_chatid(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[ void cmd_ignore(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_kick(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_mod(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); +void cmd_prune(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_set_passwd(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_set_peerlimit(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_set_privacy(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); diff --git a/src/groupchat.c b/src/groupchat.c index 8d338cf..7edb62c 100644 --- a/src/groupchat.c +++ b/src/groupchat.c @@ -603,7 +603,7 @@ static void groupchat_onGroupModeration(ToxWindow *self, Tox *m, int groupnum, u line_info_add(self, timefrmt, NULL, NULL, SYS_MSG, 1, BLUE, "-!- %s has been silenced by %s", tgt_name, src_name); break; case TOX_GROUP_MOD_EVENT_USER: - line_info_add(self, timefrmt, NULL, NULL, SYS_MSG, 1, BLUE, "-!- %s has been user'd by %s", tgt_name, src_name); + line_info_add(self, timefrmt, NULL, NULL, SYS_MSG, 1, BLUE, "-!- %s has been made a normal user by %s", tgt_name, src_name); break; case TOX_GROUP_MOD_EVENT_MODERATOR: line_info_add(self, timefrmt, NULL, NULL, SYS_MSG, 1, BLUE, "-!- %s has been promoted to moderator by %s", tgt_name, src_name); From 52a3367b5e54fe37ca7cb179ad6b807311a41b87 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Mon, 1 Jun 2015 03:12:12 -0400 Subject: [PATCH 39/45] small API fix --- src/group_commands.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/group_commands.c b/src/group_commands.c index c48f2d9..0c68e88 100644 --- a/src/group_commands.c +++ b/src/group_commands.c @@ -149,12 +149,14 @@ void cmd_mod(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX void cmd_prune(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) { - if (tox_group_prune_moderator_list(m, self->num) == -1) { + int num_pruned = tox_group_prune_moderator_list(m, self->num); + + if (num_pruned == -1) { line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to prune moderator list."); return; } - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Moderator list has been successfully pruned."); + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%d offline moderators have been pruned from the list.", num_pruned); } void cmd_unmod(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) From 928134da7a7b9e2e045a74bd18b13e899cdebc2b Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Wed, 3 Jun 2015 04:32:59 -0400 Subject: [PATCH 40/45] implement banning/unbanning --- src/execute.c | 2 + src/group_commands.c | 95 +++++++++++++++++++++++++++++++++++++++----- src/group_commands.h | 2 + src/groupchat.c | 6 ++- src/help.c | 6 ++- 5 files changed, 96 insertions(+), 15 deletions(-) diff --git a/src/execute.c b/src/execute.c index e23a64f..146d7d2 100644 --- a/src/execute.c +++ b/src/execute.c @@ -85,6 +85,7 @@ static struct cmd_func chat_commands[] = { }; static struct cmd_func group_commands[] = { + { "/ban", cmd_ban }, { "/chatid", cmd_chatid }, { "/ignore", cmd_ignore }, { "/kick", cmd_kick }, @@ -95,6 +96,7 @@ static struct cmd_func group_commands[] = { { "/prune", cmd_prune }, { "/rejoin", cmd_rejoin }, { "/topic", cmd_set_topic }, + { "/unban", cmd_unban }, { "/unignore", cmd_unignore }, { "/unmod", cmd_unmod }, #ifdef AUDIO diff --git a/src/group_commands.c b/src/group_commands.c index 0c68e88..eb3f9b1 100644 --- a/src/group_commands.c +++ b/src/group_commands.c @@ -77,14 +77,8 @@ void cmd_ignore(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[ line_info_add(self, timefrmt, NULL, NULL, SYS_MSG, 1, BLUE, "-!- Ignoring %s", nick); } -void cmd_kick(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) +static void cmd_kickban_helper(ToxWindow *self, Tox *m, const char *nick, bool set_ban) { - if (argc < 1) { - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Peer name must be specified."); - return; - } - - const char *nick = argv[1]; int peernumber = group_get_nick_peernumber(self->num, nick); if (peernumber == -1) { @@ -92,24 +86,103 @@ void cmd_kick(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA return; } - int ret = tox_group_kick_peer(m, self->num, (uint32_t) peernumber); + const char *type_str = set_ban ? "ban" : "kick"; + int ret = tox_group_remove_peer(m, self->num, (uint32_t) peernumber, set_ban); switch (ret) { case 0: { - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 1, RED, "You have kicked %s from the group.", nick); + type_str = set_ban ? "banned" : "kicked"; + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 1, RED, "You have %s %s from the group.", type_str, nick); return; } case -1: { - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to kick %s from the group.", nick); + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to %s %s from the group.", type_str, nick); return; } case -2: { - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "You do not have permission to kick %s.", nick); + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "You do not have permission to %s %s.", type_str, nick); return; } } } +void cmd_kick(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) +{ + if (argc < 1) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Peer name must be specified."); + return; + } + + cmd_kickban_helper(self, m, argv[1], false); +} + +void cmd_ban(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) +{ + if (argc < 1) { + int banlist_size = tox_group_get_ban_list_size(m, self->num); + + if (banlist_size == -1) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to get the ban list."); + return; + } + + if (banlist_size == 0) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Ban list is empty."); + return; + } + + struct Tox_Group_Ban *ban_list = malloc(banlist_size); + + if (ban_list == NULL) + return; + + int num_banned = tox_group_get_ban_list(m, self->num, ban_list); + + if (num_banned == -1) { + free(ban_list); + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to get the ban list."); + return; + } + + uint16_t i; + + for (i = 0; i < num_banned; ++i) { + struct tm tm_set = *localtime((const time_t *) &ban_list[i].time_set); + char time_str[64]; + strftime(time_str, sizeof(time_str), "%c", &tm_set); + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "[ID: %d] %s : %s : %s", ban_list[i].id, + ban_list[i].ip_address, ban_list[i].nick, time_str); + } + + free(ban_list); + return; + } + + cmd_kickban_helper(self, m, argv[1], true); +} + +void cmd_unban(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) +{ + if (argc < 1) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Ban ID must be specified."); + return; + } + + int ban_id = atoi(argv[1]); + + if (ban_id == 0 && strcmp(argv[1], "0")) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Ban ID must be a non-negative interger."); + return; + } + + if (tox_group_remove_ban_entry(m, self->num, ban_id) == -1) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Ban ID does not exist."); + return; + } + + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Ban list entry with id %d has been removed.", ban_id); +} + void cmd_mod(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) { if (argc < 1) { diff --git a/src/group_commands.h b/src/group_commands.h index 9276e90..3dcc41e 100644 --- a/src/group_commands.h +++ b/src/group_commands.h @@ -26,6 +26,7 @@ #include "windows.h" #include "toxic.h" +void cmd_ban(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_chatid(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_ignore(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_kick(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); @@ -36,6 +37,7 @@ void cmd_set_peerlimit(WINDOW *window, ToxWindow *self, Tox *m, int argc, char ( void cmd_set_privacy(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_rejoin(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_set_topic(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); +void cmd_unban(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_unignore(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_unmod(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); diff --git a/src/groupchat.c b/src/groupchat.c index 7edb62c..a926081 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 34 +#define AC_NUM_GROUP_COMMANDS 36 #else -#define AC_NUM_GROUP_COMMANDS 30 +#define AC_NUM_GROUP_COMMANDS 32 #endif /* AUDIO */ /* groupchat command names used for tab completion. */ @@ -80,6 +80,7 @@ static const char group_cmd_list[AC_NUM_GROUP_COMMANDS][MAX_CMDNAME_SIZE] = { { "/accept" }, { "/add" }, { "/avatar" }, + { "/ban" }, { "/chatid" }, { "/clear" }, { "/close" }, @@ -104,6 +105,7 @@ static const char group_cmd_list[AC_NUM_GROUP_COMMANDS][MAX_CMDNAME_SIZE] = { { "/requests" }, { "/status" }, { "/topic" }, + { "/unban" }, { "/unignore" }, { "/unmod" }, { "/whisper" }, diff --git a/src/help.c b/src/help.c index 21912ab..7bee632 100644 --- a/src/help.c +++ b/src/help.c @@ -245,13 +245,15 @@ static void help_draw_group(ToxWindow *self) wprintw(win, " /chatid : Print the group chat id to share with others.\n"); wprintw(win, " /ignore : Ignore peer\n"); + wprintw(win, " /unignore : Unignore peer \n"); wprintw(win, " /kick : Kick peer\n"); + wprintw(win, " /ban : Ban peer (leave nick blank to see ban list)\n"); + wprintw(win, " /unban : Unban entry\n"); wprintw(win, " /passwd : Set group password (leave blank to unset)\n"); wprintw(win, " /peerlimit : Set group peer limit\n"); wprintw(win, " /privacy : Set group privacy state: private|public\n"); wprintw(win, " /rejoin : Rejoin the group\n"); wprintw(win, " /topic : Set group topic (show current topic if no msg)\n"); - wprintw(win, " /unignore : Unignore peer \n"); wprintw(win, " /whisper : Send private message to nick\n\n"); #ifdef AUDIO @@ -311,7 +313,7 @@ void help_onKey(ToxWindow *self, wint_t key) break; case 'r': - help_init_window(self, 15, 80); + help_init_window(self, 17, 80); self->help->type = HELP_GROUP; break; From 9cd2158c729f3f24b9ab967cdceee1911d465b3e Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Thu, 4 Jun 2015 04:08:11 -0400 Subject: [PATCH 41/45] add group silencing and improve group help menu --- src/execute.c | 7 +++- src/group_commands.c | 88 +++++++++++++++++++++++++++++++++++++++++--- src/group_commands.h | 2 + src/groupchat.c | 11 ++++-- src/help.c | 24 ++++++++---- 5 files changed, 115 insertions(+), 17 deletions(-) diff --git a/src/execute.c b/src/execute.c index 146d7d2..8bd8ac3 100644 --- a/src/execute.c +++ b/src/execute.c @@ -95,10 +95,12 @@ static struct cmd_func group_commands[] = { { "/privacy", cmd_set_privacy }, { "/prune", cmd_prune }, { "/rejoin", cmd_rejoin }, + { "/silence", cmd_silence }, { "/topic", cmd_set_topic }, { "/unban", cmd_unban }, { "/unignore", cmd_unignore }, { "/unmod", cmd_unmod }, + { "/unsilence", cmd_unsilence }, #ifdef AUDIO { "/mute", cmd_mute }, { "/sense", cmd_sense }, @@ -106,8 +108,9 @@ static struct cmd_func group_commands[] = { { NULL, NULL }, }; -#define NUM_SPECIAL_COMMANDS 11 +#define NUM_SPECIAL_COMMANDS 14 static const char special_commands[NUM_SPECIAL_COMMANDS][MAX_CMDNAME_SIZE] = { + "/ban", "/gaccept", "/group", "/ignore", @@ -116,9 +119,11 @@ static const char special_commands[NUM_SPECIAL_COMMANDS][MAX_CMDNAME_SIZE] = { "/nick", "/note", "/passwd", + "/silence", "/topic", "/unignore", "/unmod", + "/unsilence", }; /* return true if input command is in the special_commands array. False otherwise.*/ diff --git a/src/group_commands.c b/src/group_commands.c index eb3f9b1..871c510 100644 --- a/src/group_commands.c +++ b/src/group_commands.c @@ -62,7 +62,7 @@ void cmd_ignore(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[ int peernum = group_get_nick_peernumber(self->num, nick); if (peernum == -1) { - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid peer name"); + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid peer name '%s'.", nick); return; } @@ -82,7 +82,7 @@ static void cmd_kickban_helper(ToxWindow *self, Tox *m, const char *nick, bool s int peernumber = group_get_nick_peernumber(self->num, nick); if (peernumber == -1) { - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid peer name"); + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid peer name '%s'.", nick); return; } @@ -149,7 +149,7 @@ void cmd_ban(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX for (i = 0; i < num_banned; ++i) { struct tm tm_set = *localtime((const time_t *) &ban_list[i].time_set); char time_str[64]; - strftime(time_str, sizeof(time_str), "%c", &tm_set); + strftime(time_str, sizeof(time_str), "%e %b %Y %H:%M:%S%p", &tm_set); line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "[ID: %d] %s : %s : %s", ban_list[i].id, ban_list[i].ip_address, ban_list[i].nick, time_str); } @@ -194,7 +194,7 @@ void cmd_mod(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX int peernumber = group_get_nick_peernumber(self->num, nick); if (peernumber == -1) { - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid peer name."); + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid peer name '%s'.", nick); return; } @@ -243,7 +243,12 @@ void cmd_unmod(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[M int peernumber = group_get_nick_peernumber(self->num, nick); if (peernumber == -1) { - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid peer name."); + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid peer name '%s'.", nick); + return; + } + + if (tox_group_get_peer_role(m, self->num, peernumber) != TOX_GR_MODERATOR) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s is not a moderator", nick); return; } @@ -387,6 +392,77 @@ void cmd_set_privacy(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*a } } +void cmd_silence(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) +{ + if (argc < 1) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Peer name must be specified."); + return; + } + + const char *nick = argv[1]; + int peernumber = group_get_nick_peernumber(self->num, nick); + + if (peernumber == -1) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid peer name '%s'.", nick); + return; + } + + int ret = tox_group_set_peer_role(m, self->num, peernumber, TOX_GR_OBSERVER); + + switch (ret) { + case 0: { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 1, BLUE, "You have silenced %s", nick); + return; + } + case -2: { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "You do not have permission to silence %s.", nick); + return; + } + default: { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to silence %s.", nick); + return; + } + } +} + +void cmd_unsilence(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) +{ + if (argc < 1) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Peer name must be specified."); + return; + } + + const char *nick = argv[1]; + int peernumber = group_get_nick_peernumber(self->num, nick); + + if (peernumber == -1) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid peer name '%s'.", nick); + return; + } + + if (tox_group_get_peer_role(m, self->num, peernumber) != TOX_GR_OBSERVER) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s is not silenced", nick); + return; + } + + int ret = tox_group_set_peer_role(m, self->num, peernumber, TOX_GR_USER); + + switch (ret) { + case 0: { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 1, BLUE, "You have unsilenced %s", nick); + return; + } + case -2: { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "You do not have permission to unsilence %s.", nick); + return; + } + default: { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to unsilence %s.", nick); + return; + } + } +} + void cmd_rejoin(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) { if (tox_group_reconnect(m, self->num) == -1) { @@ -447,7 +523,7 @@ void cmd_unignore(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv int peernum = group_get_nick_peernumber(self->num, nick); if (peernum == -1) { - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Peer '%s' does not exist", nick); + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid peer name '%s'.", nick); return; } diff --git a/src/group_commands.h b/src/group_commands.h index 3dcc41e..b80a4d9 100644 --- a/src/group_commands.h +++ b/src/group_commands.h @@ -37,6 +37,8 @@ void cmd_set_peerlimit(WINDOW *window, ToxWindow *self, Tox *m, int argc, char ( void cmd_set_privacy(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_rejoin(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_set_topic(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); +void cmd_silence(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); +void cmd_unsilence(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_unban(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_unignore(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_unmod(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); diff --git a/src/groupchat.c b/src/groupchat.c index a926081..b140f25 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 36 +#define AC_NUM_GROUP_COMMANDS 38 #else -#define AC_NUM_GROUP_COMMANDS 32 +#define AC_NUM_GROUP_COMMANDS 34 #endif /* AUDIO */ /* groupchat command names used for tab completion. */ @@ -103,11 +103,13 @@ static const char group_cmd_list[AC_NUM_GROUP_COMMANDS][MAX_CMDNAME_SIZE] = { { "/quit" }, { "/rejoin" }, { "/requests" }, + { "/silence" }, { "/status" }, { "/topic" }, { "/unban" }, { "/unignore" }, { "/unmod" }, + { "/unsilence" }, { "/whisper" }, #ifdef AUDIO @@ -876,7 +878,7 @@ static void groupchat_onDraw(ToxWindow *self, Tox *m) /* TODO: Make this not poll */ pthread_mutex_lock(&Winthread.lock); uint8_t status = tox_group_get_status(m, self->num, i); - TOX_GROUP_ROLE role = tox_group_get_role(m, self->num, i); + TOX_GROUP_ROLE role = tox_group_get_peer_role(m, self->num, i); pthread_mutex_unlock(&Winthread.lock); int maxlen_offset = role == TOX_GR_USER ? 2 : 3; @@ -906,6 +908,9 @@ static void groupchat_onDraw(ToxWindow *self, Tox *m) } else if (role == TOX_GR_MODERATOR) { rolesig = "+"; rolecolour = GREEN; + } else if (role == TOX_GR_OBSERVER) { + rolesig = "-"; + rolecolour = MAGENTA; } wattron(ctx->sidebar, COLOR_PAIR(rolecolour) | A_BOLD); diff --git a/src/help.c b/src/help.c index 7bee632..c073276 100644 --- a/src/help.c +++ b/src/help.c @@ -243,21 +243,31 @@ static void help_draw_group(ToxWindow *self) wprintw(win, "Group commands:\n"); wattroff(win, A_BOLD | COLOR_PAIR(RED)); - wprintw(win, " /chatid : Print the group chat id to share with others.\n"); + wprintw(win, " /chatid : Print the group chat id to share with others\n"); wprintw(win, " /ignore : Ignore peer\n"); wprintw(win, " /unignore : Unignore peer \n"); + wprintw(win, " /rejoin : Rejoin the group\n"); + wprintw(win, " /topic : Set group topic (show current topic if no msg)\n"); + wprintw(win, " /whisper : Send private message to nick\n"); + + wattron(win, A_BOLD); + wprintw(win, " Moderator commands:\n"); + wattroff(win, A_BOLD); wprintw(win, " /kick : Kick peer\n"); wprintw(win, " /ban : Ban peer (leave nick blank to see ban list)\n"); wprintw(win, " /unban : Unban entry\n"); + wprintw(win, " /silence : Silences peer for the entire group\n"); + wprintw(win, " /unsilence : Unsilences peer\n"); + + wattron(win, A_BOLD); + wprintw(win, " Founder commands:\n"); + wattroff(win, A_BOLD); + wprintw(win, " /mod : Promote peer to moderator\n"); + wprintw(win, " /unmod : Demote moderator to normal user\n"); wprintw(win, " /passwd : Set group password (leave blank to unset)\n"); wprintw(win, " /peerlimit : Set group peer limit\n"); wprintw(win, " /privacy : Set group privacy state: private|public\n"); - wprintw(win, " /rejoin : Rejoin the group\n"); - wprintw(win, " /topic : Set group topic (show current topic if no msg)\n"); - wprintw(win, " /whisper : Send private message to nick\n\n"); -#ifdef AUDIO -#endif /* AUDIO */ help_draw_bottom_menu(win); box(win, ACS_VLINE, ACS_HLINE); @@ -313,7 +323,7 @@ void help_onKey(ToxWindow *self, wint_t key) break; case 'r': - help_init_window(self, 17, 80); + help_init_window(self, 23, 80); self->help->type = HELP_GROUP; break; From b36ada0f5ba6fced75ecc2e269d99c09a4178f0f Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Thu, 4 Jun 2015 16:46:30 -0400 Subject: [PATCH 42/45] remove obsolete prune command --- src/execute.c | 1 - src/group_commands.c | 20 ++------------------ src/groupchat.c | 6 +++--- 3 files changed, 5 insertions(+), 22 deletions(-) diff --git a/src/execute.c b/src/execute.c index 8bd8ac3..9ba68c7 100644 --- a/src/execute.c +++ b/src/execute.c @@ -93,7 +93,6 @@ static struct cmd_func group_commands[] = { { "/passwd", cmd_set_passwd }, { "/peerlimit", cmd_set_peerlimit }, { "/privacy", cmd_set_privacy }, - { "/prune", cmd_prune }, { "/rejoin", cmd_rejoin }, { "/silence", cmd_silence }, { "/topic", cmd_set_topic }, diff --git a/src/group_commands.c b/src/group_commands.c index 871c510..4ffb763 100644 --- a/src/group_commands.c +++ b/src/group_commands.c @@ -205,33 +205,17 @@ void cmd_mod(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX line_info_add(self, NULL, NULL, NULL, SYS_MSG, 1, BLUE, "You have promoted %s to moderator.", nick); return; } - case -1: { - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to promote peer to moderator"); - return; - } case -2: { line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "You do not have permission to promote moderators."); return; } - case -3: { - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Moderator list is full. Use the \"/prune\" command to remove all offline mods from the mod list."); + default: { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to promote peer to moderator"); return; } } } -void cmd_prune(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) -{ - int num_pruned = tox_group_prune_moderator_list(m, self->num); - - if (num_pruned == -1) { - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to prune moderator list."); - return; - } - - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%d offline moderators have been pruned from the list.", num_pruned); -} - void cmd_unmod(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) { if (argc < 1) { diff --git a/src/groupchat.c b/src/groupchat.c index b140f25..a3a6aa7 100644 --- a/src/groupchat.c +++ b/src/groupchat.c @@ -604,13 +604,13 @@ static void groupchat_onGroupModeration(ToxWindow *self, Tox *m, int groupnum, u line_info_add(self, timefrmt, NULL, NULL, SYS_MSG, 1, RED, "-!- %s has been banned by %s", tgt_name, src_name); break; case TOX_GROUP_MOD_EVENT_OBSERVER: - line_info_add(self, timefrmt, NULL, NULL, SYS_MSG, 1, BLUE, "-!- %s has been silenced by %s", tgt_name, src_name); + line_info_add(self, timefrmt, NULL, NULL, SYS_MSG, 1, BLUE, "-!- %s has set %s's role to observer", src_name, tgt_name); break; case TOX_GROUP_MOD_EVENT_USER: - line_info_add(self, timefrmt, NULL, NULL, SYS_MSG, 1, BLUE, "-!- %s has been made a normal user by %s", tgt_name, src_name); + line_info_add(self, timefrmt, NULL, NULL, SYS_MSG, 1, BLUE, "-!- %s has set %s's role to user", src_name, tgt_name); break; case TOX_GROUP_MOD_EVENT_MODERATOR: - line_info_add(self, timefrmt, NULL, NULL, SYS_MSG, 1, BLUE, "-!- %s has been promoted to moderator by %s", tgt_name, src_name); + line_info_add(self, timefrmt, NULL, NULL, SYS_MSG, 1, BLUE, "-!- %s has set %s's role to moderator", src_name, tgt_name); break; default: return; From 1ba0891f71088bd2fb0af95a4edbd78f35e93c78 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Mon, 8 Jun 2015 21:56:32 -0400 Subject: [PATCH 43/45] fix ban API calls --- src/group_commands.c | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/src/group_commands.c b/src/group_commands.c index 4ffb763..f44b0a4 100644 --- a/src/group_commands.c +++ b/src/group_commands.c @@ -119,27 +119,21 @@ void cmd_kick(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA void cmd_ban(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) { if (argc < 1) { - int banlist_size = tox_group_get_ban_list_size(m, self->num); + int num_banned = tox_group_get_ban_list_size(m, self->num); - if (banlist_size == -1) { + if (num_banned == -1) { line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to get the ban list."); return; } - if (banlist_size == 0) { + if (num_banned == 0) { line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Ban list is empty."); return; } - struct Tox_Group_Ban *ban_list = malloc(banlist_size); + struct Tox_Group_Ban ban_list[num_banned]; - if (ban_list == NULL) - return; - - int num_banned = tox_group_get_ban_list(m, self->num, ban_list); - - if (num_banned == -1) { - free(ban_list); + if (tox_group_get_ban_list(m, self->num, ban_list) == -1) { line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to get the ban list."); return; } @@ -147,14 +141,14 @@ void cmd_ban(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX uint16_t i; for (i = 0; i < num_banned; ++i) { + ban_list[i].nick[ban_list[i].nick_len] = '\0'; struct tm tm_set = *localtime((const time_t *) &ban_list[i].time_set); char time_str[64]; strftime(time_str, sizeof(time_str), "%e %b %Y %H:%M:%S%p", &tm_set); - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "[ID: %d] %s : %s : %s", ban_list[i].id, - ban_list[i].ip_address, ban_list[i].nick, time_str); + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "ID %d : %s [Set:%s]", ban_list[i].id, + ban_list[i].nick, time_str); } - free(ban_list); return; } From 35718db46f39e85de563c4b61f8fad7fe6240707 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Wed, 10 Jun 2015 19:30:44 -0400 Subject: [PATCH 44/45] fix ban command bug --- src/group_commands.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/group_commands.c b/src/group_commands.c index f44b0a4..b7f1474 100644 --- a/src/group_commands.c +++ b/src/group_commands.c @@ -169,12 +169,22 @@ void cmd_unban(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[M return; } - if (tox_group_remove_ban_entry(m, self->num, ban_id) == -1) { - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Ban ID does not exist."); - return; - } + int ret = tox_group_remove_ban_entry(m, self->num, ban_id); - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Ban list entry with id %d has been removed.", ban_id); + switch (ret) { + case 0: { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Ban list entry with id %d has been removed.", ban_id); + return; + } + case -2: { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "You do not have permission to unban peers."); + return; + } + default: { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Ban ID does not exist."); + return; + } + } } void cmd_mod(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) From cb4a631df096231c7f9be9038550b0fe36d3da4c Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Fri, 12 Jun 2015 23:16:00 -0400 Subject: [PATCH 45/45] strcasecmp should be strcmp --- src/groupchat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/groupchat.c b/src/groupchat.c index a3a6aa7..f15540b 100644 --- a/src/groupchat.c +++ b/src/groupchat.c @@ -241,7 +241,7 @@ int group_get_nick_peernumber(int groupnum, const char *nick) int i; for (i = 0; i < groupchats[groupnum].num_peers; ++i) { - if (strcasecmp(nick, (char *) &groupchats[groupnum].peer_names[i * TOX_MAX_NAME_LENGTH]) == 0) + if (strcmp(nick, (char *) &groupchats[groupnum].peer_names[i * TOX_MAX_NAME_LENGTH]) == 0) return i; }