1
0
mirror of https://github.com/Tha14/toxic.git synced 2025-12-06 23:36:34 +01:00

Compare commits

..

41 Commits

Author SHA1 Message Date
Jfreegman
9ee7a48910 add setting to disable welcome message 2014-09-19 01:11:23 -04:00
Jfreegman
daf4614ba6 improve behaviour of misused encryption options 2014-09-19 00:29:30 -04:00
Jfreegman
919d36369c add option to unencrypt an encrypted data file 2014-09-18 23:50:51 -04:00
Jfreegman
618704df76 remove duplicate DHT node 2014-09-18 22:52:05 -04:00
Jfreegman
9a70dd9651 possibly fix display bug on some platforms 2014-09-18 13:14:15 -04:00
Sean
e2d310b10f Add TCP nodes on 443 2014-09-17 14:00:41 -07:00
Jfreegman
a1015a366a update DHTnodes, small fixes 2014-09-17 13:52:27 -04:00
mannol
913ec7b3fe Merge pull request #242 from Ansa89/trivial-fix
Usage help: add missing comma
2014-09-16 13:55:20 +02:00
Ansa89
4a52b06954 Usage help: add missing comma 2014-09-16 11:54:58 +02:00
Jfreegman
89f9c07b9e add confirmation when creating new password 2014-09-15 19:00:36 -04:00
Jfreegman
388d78d11e add option to encrypt an existing unencrypted data file 2014-09-15 16:17:58 -04:00
Jfreegman
a2a23b3932 password prompt fixes 2014-09-15 04:13:12 -04:00
Jfreegman
f405ae8b42 improvements to password entry screen 2014-09-14 21:49:38 -04:00
Jfreegman
cf3f6750eb small fix 2014-09-14 18:25:13 -04:00
JFreegman
4de22d067a Update .travis.yml 2014-09-14 18:08:42 -04:00
Jfreegman
51e274ea38 implement data file encryption 2014-09-14 17:46:28 -04:00
Jfreegman
0a6ce62363 don't write unsent messages to log 2014-09-11 01:36:33 -04:00
Jfreegman
13c5de5531 increase time between message send retries 2014-09-10 16:18:37 -04:00
Jfreegman
21f8e7f398 couple small fixes 2014-09-09 15:16:27 -04:00
Jfreegman
bcf4a5af90 message queue improvements 2014-09-09 14:06:28 -04:00
Jfreegman
09f90d095b properly flag lines with unread mark 2014-09-07 22:28:54 -04:00
Jfreegman
416ebc9ab8 another fix 2014-09-07 22:05:17 -04:00
Jfreegman
3ca22aa714 fix 2014-09-07 21:43:16 -04:00
Jfreegman
8dd25e1f0b code cleanup, add delay for unread message notification 2014-09-07 15:08:01 -04:00
Jfreegman
5b9bd603ea implement read receipts 2014-09-07 02:43:53 -04:00
Jfreegman
3c2c1f15ce message sending queue for fake offline messaging 2014-09-06 13:18:42 -04:00
JFreegman
6876df4a45 Merge pull request #240 from s3erios/master
Fix some 'clang --analyze' warnings
2014-09-05 13:16:43 -04:00
Andriy Voskoboinyk
1ff97161fb temporarily revert a862874740. 2014-09-05 14:15:25 +03:00
Andriy Voskoboinyk
667410e879 fix another potential memory leak 2014-09-05 13:17:10 +03:00
Andriy Voskoboinyk
a862874740 mark exit_toxic_* functions as noreturn 2014-09-05 13:15:56 +03:00
Andriy Voskoboinyk
79bde4e5bf fix potential memory leak and move cleanup to the end of the function 2014-09-05 13:02:26 +03:00
Jfreegman
833b724e9f fix bug 2014-09-04 18:48:55 -04:00
Jfreegman
96b68058bb code cleanup and fix bug that sometimes prevented tab notifications from working 2014-09-04 18:28:20 -04:00
JFreegman
e823233149 Merge pull request #238 from Ansa89/trivial-fix
Addition to Tox/toxic#235
2014-09-04 13:23:33 -04:00
Ansa89
3ac22fafe4 Add info about DISABLE_X11 usage 2014-09-04 19:20:51 +02:00
JFreegman
71f2ac170c Merge pull request #235 from s3erios/master_cfg
Add X11 option
2014-09-04 13:18:46 -04:00
mannol
0ef888eea3 Merge pull request #236 from s3erios/master
Some code simplification
2014-09-04 11:10:55 +02:00
Andriy Voskoboinyk
a9b0028a15 move some code inside _X11 ifdef 2014-09-04 01:41:02 +03:00
Andriy Voskoboinyk
b18e6cff5a move duplicate code into separate function 2014-09-04 01:36:37 +03:00
Andriy Voskoboinyk
424a1c94d9 Add X11 option 2014-09-04 01:19:32 +03:00
Jfreegman
009095af24 slight simplification for command list iteration 2014-09-02 02:23:44 -04:00
34 changed files with 796 additions and 280 deletions

View File

@@ -9,7 +9,7 @@ before_script:
# Installing libsodium, needed for toxcore
- git clone https://github.com/jedisct1/libsodium.git libsodium
- cd libsodium
- git checkout tags/0.4.2 > /dev/null
- git checkout tags/0.7.0 > /dev/null
- ./autogen.sh > /dev/null
- ./configure > /dev/null
- make check -j2 || make check || exit 1 > /dev/null

View File

@@ -36,6 +36,7 @@ Toxic is a [Tox](https://tox.im)-based instant messenging client which formerly
* You can add specific flags to the Makefile with `USER_CFLAGS=""` and/or `USER_LDFLAGS=""`
* You can pass your own flags to the Makefile with `CFLAGS=""` and/or `LDFLAGS=""` (this will supersede the default ones)
* Additional features are automatically enabled if all dependencies are found, but you can disable them by using special variables:
* `DISABLE_X11=1` → build toxic without X11 support (needed for focus tracking)
* `DISABLE_AV=1` → build toxic without audio call support
* `DISABLE_SOUND_NOTIFY=1` → build toxic without sound notifications support
* `DISABLE_DESKTOP_NOTIFY=1` → build toxic without desktop notifications support

View File

@@ -6,14 +6,14 @@ CFG_DIR = $(BASE_DIR)/cfg
LIBS = libtoxcore ncursesw libconfig
CFLAGS = -std=gnu99 -pthread -Wall -g
CFLAGS += -DTOXICVER="\"$(VERSION)\"" -DHAVE_WIDECHAR -D_XOPEN_SOURCE_EXTENDED
CFLAGS += '-DTOXICVER="$(VERSION)"' -DHAVE_WIDECHAR -D_XOPEN_SOURCE_EXTENDED
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 += 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
OBJ += log.o misc_tools.o prompt.o settings.o toxic.o toxic_strings.o windows.o message_queue.o
# Check on wich system we are running
UNAME_S = $(shell uname -s)

View File

@@ -1,10 +1,9 @@
CHECKS_DIR = $(CFG_DIR)/checks
# Check if we can use X11
CHECK_X11_LIBS = $(shell pkg-config --exists x11 || echo -n "error")
ifneq ($(CHECK_X11_LIBS), error)
LIBS += x11
CFLAGS += -D_X11
# Check if we want build X11 support
X11 = $(shell if [ -z "$(DISABLE_X11)" ] || [ "$(DISABLE_X11)" = "0" ] ; then echo enabled ; else echo disabled ; fi)
ifneq ($(X11), disabled)
-include $(CHECKS_DIR)/x11.mk
endif
# Check if we want build audio support

17
cfg/checks/x11.mk Normal file
View File

@@ -0,0 +1,17 @@
# Variables for X11 support
X11_LIBS = x11
X11_CFLAGS = -D_X11
# Check if we can build X11 support
CHECK_X11_LIBS = $(shell pkg-config --exists $(X11_LIBS) || echo -n "error")
ifneq ($(CHECK_X11_LIBS), error)
LIBS += $(X11_LIBS)
CFLAGS += $(X11_CFLAGS)
else
ifneq ($(MAKECMDGOALS), clean)
MISSING_X11_LIBS = $(shell for lib in $(X11_LIBS) ; do if ! pkg-config --exists $$lib ; then echo $$lib ; fi ; done)
$(warning WARNING -- Toxic will be compiled without x11 support (needed for focus tracking))
$(warning WARNING -- You need these libraries for x11 support)
$(warning WARNING -- $(MISSING_X11_LIBS))
endif
endif

View File

@@ -9,6 +9,7 @@ help:
@echo " help: This help"
@echo
@echo "-- Variables --"
@echo " DISABLE_X11: Set to \"1\" to force building without X11 support"
@echo " DISABLE_AV: Set to \"1\" to force building without audio call support"
@echo " DISABLE_SOUND_NOTIFY: Set to \"1\" to force building without sound notification support"
@echo " DISABLE_DESKTOP_NOTIFY: Set to \"1\" to force building without desktop notifications support"

View File

@@ -2,12 +2,12 @@
.\" Title: toxic
.\" Author: [see the "AUTHORS" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
.\" Date: 2014-08-21
.\" Date: 2014-09-19
.\" Manual: Toxic Manual
.\" Source: toxic __VERSION__
.\" Language: English
.\"
.TH "TOXIC" "1" "2014\-08\-21" "toxic __VERSION__" "Toxic Manual"
.TH "TOXIC" "1" "2014\-09\-19" "toxic __VERSION__" "Toxic Manual"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
@@ -55,11 +55,16 @@ instead of
\fI~/\&.config/tox/toxic\&.conf\fR
.RE
.PP
\-d, \-\-default_locale
\-d, \-\-default\-locale
.RS 4
Use default locale
.RE
.PP
\-e, \-\-encrypt\-data
.RS 4
Encrypt an unencrypted data file\&. An error will occur if this option is used with an encrypted data file\&.
.RE
.PP
\-f, \-\-file data\-file
.RS 4
Use specified
@@ -101,6 +106,11 @@ Use specified DNSservers file
Force TCP connection (use this with proxies)
.RE
.PP
\-u, \-\-unencrypt\-data
.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

View File

@@ -27,11 +27,15 @@ OPTIONS
-c, --config config-file::
Use specified 'config-file' instead of '~/.config/tox/toxic.conf'
-d, --default_locale::
-d, --default-locale::
Use default locale
-e, --encrypt-data::
Encrypt an unencrypted data file. An error will occur if this option
is used with an encrypted data file.
-f, --file data-file::
Use specified 'data-file' instead of '~/.config/tox/data'
Use specified 'data-file' instead of '~/.config/tox/data'
-h, --help::
Show help message
@@ -52,6 +56,10 @@ OPTIONS
-t, --force-tcp::
Force TCP connection (use this with proxies)
-u, --unencrypt-data::
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

View File

@@ -2,12 +2,12 @@
.\" Title: toxic.conf
.\" Author: [see the "AUTHORS" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
.\" Date: 2014-08-21
.\" Date: 2014-08-26
.\" Manual: Toxic Manual
.\" Source: toxic __VERSION__
.\" Language: English
.\"
.TH "TOXIC\&.CONF" "5" "2014\-08\-21" "toxic __VERSION__" "Toxic Manual"
.TH "TOXIC\&.CONF" "5" "2014\-08\-26" "toxic __VERSION__" "Toxic Manual"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
@@ -96,6 +96,11 @@ Show when others are typing in a 1\-on\-1 chat\&. true or false
Show others when you\(cqre typing in a 1\-on\-1 chat\&. true or false
.RE
.PP
\fBshow_welcome_msg\fR
.RS 4
Show welcome message on startup\&. true or false
.RE
.PP
\fBhistory_size\fR
.RS 4
Maximum lines for chat window history\&. Integer value\&. (for example: 700)

View File

@@ -60,6 +60,9 @@ OPTIONS
*show_typing_self*;;
Show others when you're typing in a 1-on-1 chat. true or false
*show_welcome_msg*;;
Show welcome message on startup. true or false
*history_size*;;
Maximum lines for chat window history. Integer value. (for example: 700)

View File

@@ -1,10 +1,11 @@
192.254.75.98 33445 951C88B7E75C867418ACDB5D273821372BB5BD652740BCDF623A4FA293E75D2F
37.187.46.132 33445 A9D98212B3F972BD11DA52BEB0658C326FCCC1BFD49F347F9C2D3D8B61E1B927
144.76.60.215 33445 04119E835DF3E78BACF0F84235B300546AF8B936F035185E2A8E9E0A67C8924F
23.226.230.47 33445 A09162D68618E742FFBCA1C2C70385E6679604B2D80EA6E84AD0996A1AC8A074
54.199.139.199 33445 7F9C31FE850E97CEFD4C4591DF93FC757C7C12549DDD55F8EEAECC34FE76C029
23.226.230.47 33445 A09162D68618E742FFBCA1C2C70385E6679604B2D80EA6E84AD0996A1AC8A074
54.199.139.199 33445 7F9C31FE850E97CEFD4C4591DF93FC757C7C12549DDD55F8EEAECC34FE76C029
192.210.149.121 33445 F404ABAA1C99A9D37D61AB54898F56793E1DEF8BD46B1038B9D822E8460FAB67
37.59.102.176 33445 B98A2CEAA6C6A2FADC2C3632D284318B60FE5375CCB41EFA081AB67F500C1B0B
95.85.13.245 33445 7187969BB10B54C98538BAE94C069CE5C84E650D54F7E596543D8FB1ECF4CF23
178.21.112.187 33445 4B2C19E924972CB9B57732FB172F8A8604DE13EEDA2A6234E348983344B23057
76.191.23.96 33445 4BA57660DE3E854C530EED601BF8D54B7EFAE960523B6CFC10210CC08E2CB808
107.161.17.51 33445 7BE3951B97CA4B9ECDDA768E8C52BA19E9E2690AB584787BF4C90E04DBB75111
31.7.57.236 443 2A4B50D1D525DA2E669592A20C327B5FAD6C7E5962DC69296F9FEC77C4436E4E
63.165.243.15 443 8CD087E31C67568103E8C2A28653337E90E6B8EDA0D765D57C6B5172B4F1F04C

View File

@@ -23,6 +23,9 @@ ui = {
// true to show others when you're typing a message in 1-on-1 chats
show_typing_self=true;
// true to show the welcome message on startup
show_welcome_msg=true;
// maximum lines for chat window history
history_size=700;
};

View File

@@ -43,6 +43,7 @@
#include "help.h"
#include "autocomplete.h"
#include "notify.h"
#include "message_queue.h"
#ifdef _AUDIO
#include "audio_call.h"
@@ -134,6 +135,7 @@ void kill_chat_window(ToxWindow *self, Tox *m)
close_all_file_receivers(m, self->num);
log_disable(ctx->log);
line_info_cleanup(ctx->hst);
cqueue_cleanup(ctx->cqueue);
#ifdef _AUDIO
stop_current_call(self);
@@ -144,7 +146,6 @@ void kill_chat_window(ToxWindow *self, Tox *m)
delwin(statusbar->topline);
free(ctx->log);
free(ctx->hst);
free(ctx);
free(self->help);
free(statusbar);
@@ -239,7 +240,7 @@ static void chat_onAction(ToxWindow *self, Tox *m, int32_t num, const char *acti
char timefrmt[TIME_STR_SIZE];
get_time_str(timefrmt, sizeof(timefrmt));
line_info_add(self, timefrmt, nick, NULL, ACTION, 0, 0, "%s", action);
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)
@@ -287,14 +288,17 @@ 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)
{
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)
{
if (self->num != num)
return;
const char *errmsg;
/* holds the filename appended to the user specified path */
char filename_path[MAX_STR_SIZE] = {0};
@@ -308,8 +312,7 @@ static void chat_onFileSendRequest(ToxWindow *self, Tox *m, int32_t num, uint8_t
filename_nopath, sizestr);
if (filenum >= MAX_FILES) {
errmsg = "Too many pending file requests; discarding.";
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, errmsg);
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Too many pending file requests; discarding.");
return;
}
@@ -320,8 +323,7 @@ static void chat_onFileSendRequest(ToxWindow *self, Tox *m, int32_t num, uint8_t
}
if (len >= sizeof(Friends.list[num].file_receiver[filenum].filename)) {
errmsg = "File name too long; discarding.";
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, errmsg);
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "File name too long; discarding.");
return;
}
@@ -351,8 +353,7 @@ static void chat_onFileSendRequest(ToxWindow *self, Tox *m, int32_t num, uint8_t
filename[len + d_len] = '\0';
if (count > 999) {
errmsg = "Error saving file to disk.";
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, errmsg);
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Error saving file to disk.");
return;
}
}
@@ -494,7 +495,10 @@ static void chat_onFileControl(ToxWindow *self, Tox *m, int32_t num, uint8_t rec
case TOX_FILECONTROL_FINISHED:
if (receive_send == 0) {
print_progress_bar(self, filenum, num, 100.0);
snprintf(msg, sizeof(msg), "File transfer for '%s' complete.", filename);
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);
@@ -832,13 +836,8 @@ static void send_action(ToxWindow *self, ChatContext *ctx, Tox *m, char *action)
char timefrmt[TIME_STR_SIZE];
get_time_str(timefrmt, sizeof(timefrmt));
line_info_add(self, timefrmt, selfname, NULL, ACTION, 0, 0, "%s", action);
if (tox_send_action(m, self->num, (uint8_t *) action, strlen(action)) == 0) {
line_info_add(self, NULL, selfname, NULL, SYS_MSG, 0, RED, " * Failed to send action.");
} else {
write_to_log(action, selfname, ctx->log, true);
}
line_info_add(self, timefrmt, selfname, NULL, OUT_ACTION, 0, 0, "%s", action);
cqueue_add(ctx->cqueue, action, strlen(action), OUT_ACTION, ctx->hst->line_end->id + 1);
}
static void chat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
@@ -919,12 +918,7 @@ static void chat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
get_time_str(timefrmt, sizeof(timefrmt));
line_info_add(self, timefrmt, selfname, NULL, OUT_MSG, 0, 0, "%s", line);
if (!statusbar->is_online || tox_send_message(m, self->num, (uint8_t *) line, strlen(line)) == 0) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, RED, " * Failed to send message.");
} else {
write_to_log(line, selfname, ctx->log, false);
}
cqueue_add(ctx->cqueue, line, strlen(line), OUT_MSG, ctx->hst->line_end->id + 1);
}
wclear(ctx->linewin);
@@ -1090,8 +1084,9 @@ static void chat_onInit(ToxWindow *self, Tox *m)
ctx->hst = calloc(1, sizeof(struct history));
ctx->log = calloc(1, sizeof(struct chatlog));
ctx->cqueue = calloc(1, sizeof(struct chat_queue));
if (ctx->log == NULL || ctx->hst == NULL)
if (ctx->log == NULL || ctx->hst == NULL || ctx->cqueue == NULL)
exit_toxic_err("failed in chat_onInit", FATALERR_MEMORY);
line_info_init(ctx->hst);
@@ -1127,6 +1122,7 @@ ToxWindow new_chat(Tox *m, int32_t friendnum)
ret.onFileSendRequest = &chat_onFileSendRequest;
ret.onFileControl = &chat_onFileControl;
ret.onFileData = &chat_onFileData;
ret.onReadReceipt = &chat_onReadReceipt;
#ifdef _AUDIO
ret.onInvite = &chat_onInvite;

View File

@@ -55,11 +55,11 @@ static struct cmd_func global_commands[] = {
{ "/quit", cmd_quit },
{ "/requests", cmd_requests },
{ "/status", cmd_status },
#ifdef _AUDIO
{ "/lsdev", cmd_list_devices },
{ "/sdev", cmd_change_device },
#endif /* _AUDIO */
{ NULL, NULL },
};
static struct cmd_func chat_commands[] = {
@@ -68,7 +68,6 @@ static struct cmd_func chat_commands[] = {
{ "/join", cmd_join_group },
{ "/savefile", cmd_savefile },
{ "/sendfile", cmd_sendfile },
#ifdef _AUDIO
{ "/call", cmd_call },
{ "/answer", cmd_answer },
@@ -78,6 +77,7 @@ static struct cmd_func chat_commands[] = {
{ "/mute", cmd_mute },
{ "/sense", cmd_sense },
#endif /* _AUDIO */
{ NULL, NULL },
};
/* Parses input command and puts args into arg array.
@@ -101,7 +101,7 @@ static int parse_command(WINDOW *w, ToxWindow *self, const char *input, char (*a
i = char_find(1, cmd, '\"');
if (cmd[i] == '\0') {
char *errmsg = "Invalid argument. Did you forget a closing \"?";
const char *errmsg = "Invalid argument. Did you forget a closing \"?";
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, errmsg);
free(cmd);
return -1;
@@ -118,7 +118,7 @@ static int parse_command(WINDOW *w, ToxWindow *self, const char *input, char (*a
char tmp[MAX_STR_SIZE];
snprintf(tmp, sizeof(tmp), "%s", &cmd[i + 1]);
strcpy(cmd, tmp);
strcpy(cmd, tmp); /* tmp will always fit inside cmd */
}
free(cmd);
@@ -126,12 +126,12 @@ static int parse_command(WINDOW *w, ToxWindow *self, const char *input, char (*a
}
/* Matches command to respective function. Returns 0 on match, 1 on no match */
static int do_command(WINDOW *w, ToxWindow *self, Tox *m, int num_args, int num_cmds,
struct cmd_func *commands, char (*args)[MAX_STR_SIZE])
static int do_command(WINDOW *w, ToxWindow *self, Tox *m, int num_args, struct cmd_func *commands,
char (*args)[MAX_STR_SIZE])
{
int i;
for (i = 0; i < num_cmds; ++i) {
for (i = 0; commands[i].name != NULL; ++i) {
if (strcmp(args[0], commands[i].name) == 0) {
(commands[i].func)(w, self, m, num_args - 1, args);
return 0;
@@ -158,7 +158,7 @@ void execute(WINDOW *w, ToxWindow *self, Tox *m, const char *input, int mode)
Note: Global commands must come last in case of duplicate command names */
switch (mode) {
case CHAT_COMMAND_MODE:
if (do_command(w, self, m, num_args, CHAT_NUM_COMMANDS, chat_commands, args) == 0)
if (do_command(w, self, m, num_args, chat_commands, args) == 0)
return;
break;
@@ -167,7 +167,7 @@ void execute(WINDOW *w, ToxWindow *self, Tox *m, const char *input, int mode)
break;
}
if (do_command(w, self, m, num_args, GLOBAL_NUM_COMMANDS, global_commands, args) == 0)
if (do_command(w, self, m, num_args, global_commands, args) == 0)
return;
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid command.");

View File

@@ -28,14 +28,6 @@
#define MAX_NUM_ARGS 4 /* Includes command */
#ifdef _AUDIO
#define GLOBAL_NUM_COMMANDS 18
#define CHAT_NUM_COMMANDS 12
#else
#define GLOBAL_NUM_COMMANDS 16
#define CHAT_NUM_COMMANDS 5
#endif /* _AUDIO */
enum {
GLOBAL_COMMAND_MODE,
CHAT_COMMAND_MODE,

View File

@@ -276,6 +276,7 @@ void do_file_senders(Tox *m)
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;
}

View File

@@ -130,11 +130,12 @@ static int save_blocklist(char *path)
exit_toxic_err("Failed in save_blocklist", FATALERR_MEMORY);
int i;
int ret = -1;
int count = 0;
for (i = 0; i < Blocked.max_idx; ++i) {
if (count > Blocked.num_blocked)
return -1;
goto on_error;
if (Blocked.list[i].active) {
BlockedFriend tmp;
@@ -155,17 +156,14 @@ static int save_blocklist(char *path)
FILE *fp = fopen(path, "wb");
if (fp == NULL) {
free(data);
return -1;
}
if (fp == NULL)
goto on_error;
int ret = 0;
if (fwrite(data, len, 1, fp) != 1)
ret = -1;
if (fwrite(data, len, 1, fp) == 1)
ret = 0;
fclose(fp);
on_error:
free(data);
return ret;
}
@@ -1001,7 +999,6 @@ static void friendlist_onAv(ToxWindow *self, ToxAv *av, int call_index)
{
int id = toxav_get_peer_id(av, call_index, 0);
/*id++;*/
if ( id != ErrorInternal && id >= Friends.max_idx)
return;

View File

@@ -97,7 +97,6 @@ void kill_groupchat_window(ToxWindow *self)
delwin(ctx->history);
delwin(ctx->sidebar);
free(ctx->log);
free(ctx->hst);
free(ctx);
free(self->help);
del_window(self);
@@ -198,7 +197,7 @@ static void groupchat_onGroupAction(ToxWindow *self, Tox *m, int groupnum, int p
char timefrmt[TIME_STR_SIZE];
get_time_str(timefrmt, sizeof(timefrmt));
line_info_add(self, timefrmt, nick, NULL, ACTION, 0, 0, "%s", action);
line_info_add(self, timefrmt, nick, NULL, IN_ACTION, 0, 0, "%s", action);
write_to_log(action, nick, ctx->log, true);
}

View File

@@ -31,6 +31,8 @@
#include "groupchat.h"
#include "settings.h"
#include "notify.h"
#include "message_queue.h"
#include "misc_tools.h"
extern struct user_settings *user_settings_;
@@ -89,6 +91,8 @@ void line_info_cleanup(struct history *hst)
if (hst->queue[i])
free(hst->queue[i]);
}
free(hst);
}
/* moves root forward and frees previous root */
@@ -107,15 +111,6 @@ static void line_info_root_fwd(struct history *hst)
hst->line_root = tmp;
}
/* adds a line_info line to queue */
static void line_info_add_queue(struct history *hst, struct line_info *line)
{
if (hst->queue_sz >= MAX_QUEUE)
return;
hst->queue[hst->queue_sz++] = line;
}
/* returns ptr to queue item 0 and removes it from queue */
static struct line_info *line_info_ret_queue(struct history *hst)
{
@@ -134,12 +129,15 @@ static struct line_info *line_info_ret_queue(struct history *hst)
return ret;
}
/* creates new line_info line and puts it in the queue.
SYS_MSG lines may contain an arbitrary number of arguments for string formatting */
void line_info_add(ToxWindow *self, char *tmstmp, char *name1, char *name2, uint8_t type, uint8_t bold,
/* creates new line_info line and puts it in the queue. */
void line_info_add(ToxWindow *self, char *timestr, char *name1, char *name2, uint8_t type, uint8_t bold,
uint8_t colour, const char *msg, ...)
{
struct history *hst = self->chatwin->hst;
if (hst->queue_sz >= MAX_QUEUE)
return;
struct line_info *new_line = calloc(1, sizeof(struct line_info));
if (new_line == NULL)
@@ -156,7 +154,16 @@ void line_info_add(ToxWindow *self, char *tmstmp, char *name1, char *name2, uint
/* for type-specific formatting in print function */
switch (type) {
case ACTION:
case IN_ACTION:
case OUT_ACTION:
len += 3;
break;
case IN_MSG:
case OUT_MSG:
len += 2;
break;
case CONNECTION:
len += 3;
break;
@@ -185,9 +192,9 @@ void line_info_add(ToxWindow *self, char *tmstmp, char *name1, char *name2, uint
}
}
if (tmstmp) {
snprintf(new_line->timestamp, sizeof(new_line->timestamp), "%s", tmstmp);
len += strlen(new_line->timestamp);
if (timestr) {
snprintf(new_line->timestr, sizeof(new_line->timestr), "%s", timestr);
len += strlen(new_line->timestr);
}
if (name1) {
@@ -204,8 +211,10 @@ void line_info_add(ToxWindow *self, char *tmstmp, char *name1, char *name2, uint
new_line->type = type;
new_line->bold = bold;
new_line->colour = colour;
new_line->noread_flag = false;
new_line->timestamp = get_unix_time();
line_info_add_queue(hst, new_line);
hst->queue[hst->queue_sz++] = new_line;
}
/* adds a single queue item to hst if possible. only called once per call to line_info_print() */
@@ -247,6 +256,8 @@ static void line_info_check_queue(ToxWindow *self)
}
}
#define NOREAD_FLAG_TIMEOUT 5 /* seconds before a sent message with no read receipt is flagged as unread */
void line_info_print(ToxWindow *self)
{
ChatContext *ctx = self->chatwin;
@@ -280,9 +291,10 @@ void line_info_print(ToxWindow *self)
switch (type) {
case OUT_MSG:
case OUT_MSG_READ:
case IN_MSG:
wattron(win, COLOR_PAIR(BLUE));
wprintw(win, "%s", line->timestamp);
wprintw(win, "%s", line->timestr);
wattroff(win, COLOR_PAIR(BLUE));
int nameclr = GREEN;
@@ -299,28 +311,54 @@ void line_info_print(ToxWindow *self)
if (line->msg[0] == '>')
wattron(win, COLOR_PAIR(GREEN));
wprintw(win, "%s\n", line->msg);
wprintw(win, "%s", line->msg);
if (line->msg[0] == '>')
wattroff(win, COLOR_PAIR(GREEN));
if (type == OUT_MSG && timed_out(line->timestamp, get_unix_time(), NOREAD_FLAG_TIMEOUT)) {
wattron(win, COLOR_PAIR(RED));
wprintw(win, " x", line->msg);
wattroff(win, COLOR_PAIR(RED));
if (line->noread_flag == false) {
line->noread_flag = true;
line->len += 2;
}
}
wprintw(win, "\n", line->msg);
break;
case ACTION:
case OUT_ACTION_READ:
case OUT_ACTION:
case IN_ACTION:
wattron(win, COLOR_PAIR(BLUE));
wprintw(win, "%s", line->timestamp);
wprintw(win, "%s", line->timestr);
wattroff(win, COLOR_PAIR(BLUE));
wattron(win, COLOR_PAIR(YELLOW));
wprintw(win, "* %s %s\n", line->name1, line->msg);
wprintw(win, "* %s %s", line->name1, line->msg);
wattroff(win, COLOR_PAIR(YELLOW));
if (type == OUT_ACTION && timed_out(line->timestamp, get_unix_time(), NOREAD_FLAG_TIMEOUT)) {
wattron(win, COLOR_PAIR(RED));
wprintw(win, " x", line->msg);
wattroff(win, COLOR_PAIR(RED));
if (line->noread_flag == false) {
line->noread_flag = true;
line->len += 2;
}
}
wprintw(win, "\n", line->msg);
break;
case SYS_MSG:
if (line->timestamp[0]) {
if (line->timestr[0]) {
wattron(win, COLOR_PAIR(BLUE));
wprintw(win, "%s", line->timestamp);
wprintw(win, "%s", line->timestr);
wattroff(win, COLOR_PAIR(BLUE));
}
@@ -353,7 +391,7 @@ void line_info_print(ToxWindow *self)
case CONNECTION:
wattron(win, COLOR_PAIR(BLUE));
wprintw(win, "%s", line->timestamp);
wprintw(win, "%s", line->timestr);
wattroff(win, COLOR_PAIR(BLUE));
wattron(win, COLOR_PAIR(line->colour));
@@ -367,7 +405,7 @@ void line_info_print(ToxWindow *self)
case NAME_CHANGE:
wattron(win, COLOR_PAIR(BLUE));
wprintw(win, "%s", line->timestamp);
wprintw(win, "%s", line->timestr);
wattroff(win, COLOR_PAIR(BLUE));
wattron(win, COLOR_PAIR(MAGENTA));
@@ -393,6 +431,7 @@ void line_info_print(ToxWindow *self)
line_info_print(self);
}
/* puts msg in specified line_info msg buffer */
void line_info_set(ToxWindow *self, uint32_t id, char *msg)
{
struct line_info *line = self->chatwin->hst->line_end;

View File

@@ -34,22 +34,27 @@ 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 */
IN_ACTION,
OUT_ACTION,
OUT_ACTION_READ, /* same as OUT_MSG_READ but for actions */
PROMPT,
ACTION,
CONNECTION,
NAME_CHANGE,
} LINE_TYPE;
struct line_info {
char timestamp[TIME_STR_SIZE];
char timestr[TIME_STR_SIZE];
char name1[TOXIC_MAX_NAME_LENGTH];
char name2[TOXIC_MAX_NAME_LENGTH];
char msg[TOX_MAX_MESSAGE_LENGTH];
uint64_t timestamp;
uint8_t type;
uint8_t bold;
uint8_t colour;
uint8_t noread_flag; /* true if a line should be flagged as unread */
uint32_t id;
uint16_t len; /* combined len of all strings */
uint16_t len; /* combined len of entire line */
uint8_t newlines;
struct line_info *prev;
@@ -67,9 +72,8 @@ struct history {
int queue_sz;
};
/* creates new line_info line and puts it in the queue.
SYS_MSG lines may contain an arbitrary number of arguments for string formatting */
void line_info_add(ToxWindow *self, char *tmstmp, char *name1, char *name2, uint8_t type, uint8_t bold,
/* creates new line_info line and puts it in the queue. */
void line_info_add(ToxWindow *self, char *timestr, char *name1, char *name2, uint8_t type, uint8_t bold,
uint8_t colour, const char *msg, ...);
/* Prints a section of history starting at line_start */

View File

@@ -86,6 +86,8 @@ void init_logging_session(char *name, const char *key, struct chatlog *log)
fprintf(log->file, "\n*** NEW SESSION ***\n\n");
}
#define LOG_FLUSH_LIMIT 1 /* limits calls to fflush to a max of one per LOG_FLUSH_LIMIT seconds */
void write_to_log(const char *msg, const char *name, struct chatlog *log, bool event)
{
if (!log->log_on)

View File

@@ -23,12 +23,9 @@
#ifndef _log_h
#define _log_h
#define LOG_FLUSH_LIMIT 2 /* limits calls to fflush(logfile) to a max of one per LOG_FLUSH_LIMIT seconds */
struct chatlog {
FILE *file;
uint64_t lastwrite;
int pos;
bool log_on; /* specific to current chat window */
};

156
src/message_queue.c Normal file
View File

@@ -0,0 +1,156 @@
/* message_queue.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 <http://www.gnu.org/licenses/>.
*
*/
#include <stdlib.h>
#include "toxic.h"
#include "windows.h"
#include "message_queue.h"
#include "misc_tools.h"
#include "line_info.h"
#include "log.h"
void cqueue_cleanup(struct chat_queue *q)
{
struct cqueue_msg *tmp1 = q->root;
while (tmp1) {
struct cqueue_msg *tmp2 = tmp1->next;
free(tmp1);
tmp1 = tmp2;
}
free(q);
}
void cqueue_add(struct chat_queue *q, const char *msg, int len, uint8_t type, uint32_t line_id)
{
struct cqueue_msg *new_m = malloc(sizeof(struct cqueue_msg));
if (new_m == NULL)
exit_toxic_err("failed in cqueue_message", FATALERR_MEMORY);
snprintf(new_m->message, sizeof(new_m->message), "%s", msg);
new_m->len = len;
new_m->type = type;
new_m->line_id = line_id;
new_m->last_send_try = 0;
new_m->receipt = 0;
new_m->next = NULL;
if (q->root == NULL) {
new_m->prev = NULL;
q->root = new_m;
} else {
new_m->prev = q->end;
q->end->next = new_m;
}
q->end = new_m;
}
/* update line to show receipt was received after queue removal */
static void cqueue_mark_read(ToxWindow *self, struct cqueue_msg *msg)
{
struct line_info *line = self->chatwin->hst->line_end;
while (line) {
if (line->id != msg->line_id) {
line = line->prev;
continue;
}
line->type = msg->type == OUT_ACTION ? OUT_ACTION_READ : OUT_MSG_READ;
if (line->noread_flag == true) {
line->len -= 2;
line->noread_flag = false;
}
return;
}
}
/* 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)
{
struct chat_queue *q = self->chatwin->cqueue;
struct cqueue_msg *msg = q->root;
while (msg) {
if (msg->receipt != receipt) {
msg = msg->next;
continue;
}
char selfname[TOX_MAX_NAME_LENGTH];
uint16_t len = tox_get_self_name(m, (uint8_t *) selfname);
selfname[len] = '\0';
write_to_log(msg->message, selfname, self->chatwin->log, msg->type == OUT_ACTION);
cqueue_mark_read(self, msg);
struct cqueue_msg *next = msg->next;
if (msg->prev == NULL) { /* root */
if (next)
next->prev = NULL;
free(msg);
q->root = next;
} else {
struct cqueue_msg *prev = msg->prev;
free(msg);
prev->next = next;
}
return;
}
}
#define CQUEUE_TRY_SEND_INTERVAL 10
/* Tries to send the oldest unsent message in queue. */
void cqueue_try_send(ToxWindow *self, Tox *m)
{
struct chat_queue *q = self->chatwin->cqueue;
struct cqueue_msg *msg = q->root;
uint64_t curtime = get_unix_time();
while (msg) {
if (msg->receipt != 0 && !timed_out(msg->last_send_try, curtime, CQUEUE_TRY_SEND_INTERVAL)) {
msg = msg->next;
continue;
}
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);
msg->last_send_try = curtime;
msg->receipt = receipt;
return;
}
}

46
src/message_queue.h Normal file
View File

@@ -0,0 +1,46 @@
/* message_queue.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 <http://www.gnu.org/licenses/>.
*
*/
struct cqueue_msg {
char message[MAX_STR_SIZE];
int len;
int line_id;
uint8_t type;
uint32_t receipt;
uint64_t last_send_try;
struct cqueue_msg *next;
struct cqueue_msg *prev;
};
struct chat_queue {
struct cqueue_msg *root;
struct cqueue_msg *end;
};
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);
/* Tries to send the oldest unsent message in queue. */
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);

View File

@@ -306,8 +306,8 @@ 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 *fp)
bool file_exists(const char *path)
{
struct stat s;
return stat(fp, &s) == 0;
return stat(path, &s) == 0;
}

View File

@@ -110,6 +110,6 @@ int char_rfind(const char *s, char ch, int len);
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 *fp);
bool file_exists(const char *path);
#endif /* #define _misc_tools_h */

View File

@@ -24,10 +24,12 @@
#include "device.h"
#include "settings.h"
#include "line_info.h"
#include "misc_tools.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdbool.h>
#include <unistd.h>
#include <stdarg.h>
#include <time.h>
@@ -59,6 +61,7 @@
#include <libnotify/notify.h>
#endif
#define MAX_BOX_MSG_LEN 127
#define SOUNDS_SIZE 10
#define ACTIVE_NOTIFS_MAX 50
@@ -67,14 +70,14 @@ extern struct user_settings *user_settings_;
struct _Control {
time_t cooldown;
time_t notif_timeout;
unsigned long this_window;
#ifdef _X11
Display *display;
unsigned long this_window;
#endif /* _X11 */
#if defined(_SOUND_NOTIFY) || defined(_BOX_NOTIFY)
pthread_mutex_t poll_mutex[1];
_Bool poll_active;
bool poll_active;
#endif
#ifdef _SOUND_NOTIFY
@@ -87,13 +90,13 @@ struct _ActiveNotifications {
#ifdef _SOUND_NOTIFY
uint32_t source;
uint32_t buffer;
_Bool looping;
bool looping;
#endif
_Bool active;
bool active;
int *id_indicator;
#ifdef _BOX_NOTIFY
NotifyNotification* box;
char messages[128][128];
char messages[MAX_BOX_MSG_LEN + 1][MAX_BOX_MSG_LEN + 1];
char title[24];
size_t size;
time_t n_timeout;
@@ -105,18 +108,40 @@ struct _ActiveNotifications {
/**********************************************************************************/
/**********************************************************************************/
/* coloured tab notifications: primary notification type */
static void tab_notify(ToxWindow *self, uint64_t flags)
{
if (self == NULL)
return;
if (flags & NT_WNDALERT_0)
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) )
self->alert = WINDOW_ALERT_2;
}
#ifdef _X11
long unsigned int get_focused_window_id()
{
#ifdef _X11
if (!Control.display) return 0;
Window focus;
int revert;
XGetInputFocus(Control.display, &focus, &revert);
return focus;
#else
return 0;
}
#endif /* _X11 */
static bool notifications_are_disabled(uint64_t flags)
{
bool res = flags & NT_RESTOL && Control.cooldown > get_unix_time();
#ifdef _X11
return res || (flags & NT_NOFOCUS && Control.this_window == get_focused_window_id());
#else
return res;
#endif
}
static void control_lock()
@@ -134,14 +159,14 @@ static void control_unlock()
}
#ifdef _SOUND_NOTIFY
_Bool is_playing(int source)
bool is_playing(int source)
{
int ready;
alGetSourcei(source, AL_SOURCE_STATE, &ready);
return ready == AL_PLAYING;
}
/* Terminate all sounds but wait them to finish first */
/* Terminate all sounds but wait for them to finish first */
void graceful_clear()
{
int i;
@@ -167,7 +192,6 @@ void graceful_clear()
else break;
}
}
}
if (i == ACTIVE_NOTIFS_MAX) {
@@ -224,7 +248,7 @@ void* do_playing(void* _p)
pthread_exit(NULL);
}
int play_source(uint32_t source, uint32_t buffer, _Bool looping)
int play_source(uint32_t source, uint32_t buffer, bool looping)
{
int i = 0;
for (; i < ACTIVE_NOTIFS_MAX && actives[i].active; i ++);
@@ -317,8 +341,6 @@ int init_notify(int login_cooldown, int notification_timeout)
#ifdef _X11
Control.display = XOpenDisplay(NULL);
Control.this_window = get_focused_window_id();
#else
Control.this_window = 1;
#endif /* _X11 */
@@ -365,7 +387,7 @@ int set_sound(Notification sound, const char* value)
return stat(value, &buf) == 0;
}
int play_sound_internal(Notification what, _Bool loop)
int play_sound_internal(Notification what, bool loop)
{
uint32_t source;
uint32_t buffer;
@@ -442,15 +464,9 @@ void m_notify_action(NotifyNotification *box, char *action, void* data)
int sound_notify(ToxWindow* self, Notification notif, uint64_t flags, int* id_indicator)
{
/* Consider colored notify as primary */
if (self) {
if (flags & NT_WNDALERT_0) 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) ) self->alert = WINDOW_ALERT_2;
}
if ((flags & NT_RESTOL && Control.cooldown > time(NULL)) ||
((flags & NT_NOFOCUS && Control.this_window == get_focused_window_id()) ))
tab_notify(self, flags);
if (notifications_are_disabled(flags))
return -1;
int id = -1;
@@ -486,15 +502,9 @@ 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)
{
/* Consider colored notify as primary */
if (self) {
if (flags & NT_WNDALERT_0) 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) ) self->alert = WINDOW_ALERT_2;
}
tab_notify(self, flags);
if ((flags & NT_RESTOL && Control.cooldown > time(NULL)) ||
((flags & NT_NOFOCUS && Control.this_window == get_focused_window_id()) ))
if (notifications_are_disabled(flags))
return -1;
if (id < 0 || id >= ACTIVE_NOTIFS_MAX) return -1;
@@ -532,41 +542,42 @@ int sound_notify2(ToxWindow* self, Notification notif, uint64_t flags, int id)
int box_notify(ToxWindow* self, Notification notif, uint64_t flags, int* id_indicator, char* title, const char* format, ...)
{
if ((flags & NT_RESTOL && Control.cooldown > time(NULL)) ||
((flags & NT_NOFOCUS && Control.this_window == get_focused_window_id()) ))
if (notifications_are_disabled(flags)) {
tab_notify(self, flags);
return -1;
}
#ifdef _BOX_NOTIFY
int id = sound_notify(self, notif, flags, id_indicator);
control_lock();
#ifdef _SOUND_NOTIFY
if (id == -1) { /* Could not play */
for (id = 0; id < ACTIVE_NOTIFS_MAX && actives[id].active; id ++);
if ( id == ACTIVE_NOTIFS_MAX ) {
control_unlock();
return -1; /* Full */
}
actives[id].active = 1;
actives[id].id_indicator = id_indicator;
if (id_indicator) *id_indicator = id;
}
#endif
strncpy(actives[id].title, title, 24);
if (strlen(title) > 23) strcpy(actives[id].title + 20, "...");
va_list __ARGS__; va_start (__ARGS__, format);
vsnprintf (actives[id].messages[0], 127, format, __ARGS__);
vsnprintf (actives[id].messages[0], MAX_BOX_MSG_LEN, format, __ARGS__);
va_end (__ARGS__);
if (strlen(actives[id].messages[0]) > 124)
strcpy(actives[id].messages[0] + 124, "...");
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 = time(NULL) + Control.notif_timeout / 1000;
@@ -575,7 +586,7 @@ int box_notify(ToxWindow* self, Notification notif, uint64_t flags, int* id_indi
notify_notification_set_app_name(actives[id].box, "toxic");
/*notify_notification_add_action(actives[id].box, "lel", "default", m_notify_action, self, NULL);*/
notify_notification_show(actives[id].box, NULL);
control_unlock();
return id;
#else
@@ -585,48 +596,48 @@ int box_notify(ToxWindow* self, Notification notif, uint64_t flags, int* id_indi
int box_notify2(ToxWindow* self, Notification notif, uint64_t flags, int id, const char* format, ...)
{
if ((flags & NT_RESTOL && Control.cooldown > time(NULL)) ||
((flags & NT_NOFOCUS && Control.this_window == get_focused_window_id()) ))
if (notifications_are_disabled(flags)) {
tab_notify(self, flags);
return -1;
}
#ifdef _BOX_NOTIFY
if (sound_notify2(self, notif, flags, id) == -1)
return -1;
control_lock();
if (!actives[id].box || actives[id].size >= 128 ) {
if (!actives[id].box || actives[id].size >= MAX_BOX_MSG_LEN + 1) {
control_unlock();
return -1;
}
va_list __ARGS__; va_start (__ARGS__, format);
vsnprintf (actives[id].messages[actives[id].size], 127, format, __ARGS__);
vsnprintf (actives[id].messages[actives[id].size], MAX_BOX_MSG_LEN, format, __ARGS__);
va_end (__ARGS__);
if (strlen(actives[id].messages[actives[id].size]) > 124)
strcpy(actives[id].messages[actives[id].size] + 124, "...");
if (strlen(actives[id].messages[actives[id].size]) > MAX_BOX_MSG_LEN - 3)
strcpy(actives[id].messages[actives[id].size] + MAX_BOX_MSG_LEN - 3, "...");
actives[id].size ++;
actives[id].n_timeout = time(NULL) + Control.notif_timeout / 1000;
char formated[128 * 129] = {'\0'};
int i = 0;
for (; i <actives[id].size; i ++) {
strcat(formated, actives[id].messages[i]);
strcat(formated, "\n");
}
formated[strlen(formated) - 1] = '\0';
notify_notification_update(actives[id].box, actives[id].title, formated, NULL);
notify_notification_show(actives[id].box, NULL);
control_unlock();
return id;
#else
return sound_notify2(self, notif, flags, id);
@@ -635,53 +646,47 @@ int box_notify2(ToxWindow* self, Notification notif, uint64_t flags, int id, con
int box_silent_notify(ToxWindow* self, uint64_t flags, int* id_indicator, const char* title, const char* format, ...)
{
/* Always do colored notify */
if (self) {
if (flags & NT_WNDALERT_0) 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) ) self->alert = WINDOW_ALERT_2;
}
if ((flags & NT_RESTOL && Control.cooldown > time(NULL)) ||
((flags & NT_NOFOCUS && Control.this_window == get_focused_window_id()) ))
tab_notify(self, flags);
if (notifications_are_disabled(flags))
return -1;
#ifdef _BOX_NOTIFY
control_lock();
int id;
for (id = 0; id < ACTIVE_NOTIFS_MAX && actives[id].active; id ++);
if ( id == ACTIVE_NOTIFS_MAX ) {
control_unlock();
return -1; /* Full */
}
if (id_indicator) {
actives[id].id_indicator = id_indicator;
*id_indicator = id;
}
strncpy(actives[id].title, title, 24);
if (strlen(title) > 23) strcpy(actives[id].title + 20, "...");
va_list __ARGS__; va_start (__ARGS__, format);
vsnprintf (actives[id].messages[0], 127, format, __ARGS__);
vsnprintf (actives[id].messages[0], MAX_BOX_MSG_LEN, format, __ARGS__);
va_end (__ARGS__);
if (strlen(actives[id].messages[0]) > 124)
strcpy(actives[id].messages[0] + 124, "...");
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;
actives[id].box = notify_notification_new(actives[id].title, actives[id].messages[0], NULL);
actives[id].size ++;
actives[id].n_timeout = time(NULL) + 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);*/
notify_notification_show(actives[id].box, NULL);
control_unlock();
return id;
#else
@@ -691,51 +696,45 @@ int box_silent_notify(ToxWindow* self, uint64_t flags, int* id_indicator, const
int box_silent_notify2(ToxWindow* self, uint64_t flags, int id, const char* format, ...)
{
/* Always do colored notify */
if (self) {
if (flags & NT_WNDALERT_0) 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) ) self->alert = WINDOW_ALERT_2;
}
if ((flags & NT_RESTOL && Control.cooldown > time(NULL)) ||
((flags & NT_NOFOCUS && Control.this_window == get_focused_window_id()) ))
tab_notify(self, flags);
if (notifications_are_disabled(flags))
return -1;
#ifdef _BOX_NOTIFY
control_lock();
if (id < 0 || id >= ACTIVE_NOTIFS_MAX || !actives[id].box || actives[id].size >= 128 ) {
if (id < 0 || id >= ACTIVE_NOTIFS_MAX || !actives[id].box || actives[id].size >= MAX_BOX_MSG_LEN + 1 ) {
control_unlock();
return -1;
}
va_list __ARGS__; va_start (__ARGS__, format);
vsnprintf (actives[id].messages[actives[id].size], 127, format, __ARGS__);
vsnprintf (actives[id].messages[actives[id].size], MAX_BOX_MSG_LEN, format, __ARGS__);
va_end (__ARGS__);
if (strlen(actives[id].messages[actives[id].size]) > 124)
strcpy(actives[id].messages[actives[id].size] + 124, "...");
if (strlen(actives[id].messages[actives[id].size]) > MAX_BOX_MSG_LEN - 3)
strcpy(actives[id].messages[actives[id].size] + MAX_BOX_MSG_LEN - 3, "...");
actives[id].size ++;
actives[id].n_timeout = time(NULL) + Control.notif_timeout / 1000;
char formated[128 * 129] = {'\0'};
int i = 0;
for (; i <actives[id].size; i ++) {
strcat(formated, actives[id].messages[i]);
strcat(formated, "\n");
}
formated[strlen(formated) - 1] = '\0';
notify_notification_update(actives[id].box, actives[id].title, formated, NULL);
notify_notification_show(actives[id].box, NULL);
control_unlock();
return id;
#else
return -1;

View File

@@ -88,7 +88,6 @@ void kill_prompt_window(ToxWindow *self)
delwin(statusbar->topline);
free(ctx->log);
free(ctx->hst);
free(ctx);
free(self->help);
free(statusbar);
@@ -465,7 +464,8 @@ static void prompt_onInit(ToxWindow *self, Tox *m)
scrollok(ctx->history, 0);
wmove(self->window, y2 - CURS_Y_OFFSET, 0);
print_welcome_msg(self);
if (user_settings_->show_welcome_msg == SHOW_WELCOME_MSG_ON)
print_welcome_msg(self);
}
ToxWindow new_prompt(void)

View File

@@ -54,6 +54,7 @@ static struct _ui_strings {
const char* history_size;
const char* show_typing_self;
const char* show_typing_other;
const char* show_welcome_msg;
} ui_strings = {
"ui",
"timestamps",
@@ -64,6 +65,7 @@ static struct _ui_strings {
"history_size",
"show_typing_self",
"show_typing_other",
"show_welcome_msg",
};
static void ui_defaults(struct user_settings* settings)
@@ -76,6 +78,7 @@ static void ui_defaults(struct user_settings* settings)
settings->history_size = 700;
settings->show_typing_self = SHOW_TYPING_ON;
settings->show_typing_other = SHOW_TYPING_ON;
settings->show_welcome_msg = SHOW_WELCOME_MSG_ON;
}
static const struct _keys_strings {
@@ -250,6 +253,7 @@ int settings_load(struct user_settings *s, const char *patharg)
config_setting_lookup_int(setting, ui_strings.history_size, &s->history_size);
config_setting_lookup_bool(setting, ui_strings.show_typing_self, &s->show_typing_self);
config_setting_lookup_bool(setting, ui_strings.show_typing_other, &s->show_typing_other);
config_setting_lookup_bool(setting, ui_strings.show_welcome_msg, &s->show_welcome_msg);
config_setting_lookup_int(setting, ui_strings.time_format, &s->time);
s->time = s->time == TIME_24 || s->time == TIME_12 ? s->time : TIME_24; /* Check defaults */
}

View File

@@ -35,6 +35,7 @@ struct user_settings {
int history_size; /* int between MIN_HISTORY and MAX_HISTORY */
int show_typing_self; /* boolean */
int show_typing_other; /* boolean */
int show_welcome_msg; /* boolean */
char download_path[PATH_MAX];
char chatlogs_path[PATH_MAX];
@@ -74,6 +75,9 @@ enum {
SHOW_TYPING_OFF = 0,
SHOW_TYPING_ON = 1,
SHOW_WELCOME_MSG_OFF = 0,
SHOW_WELCOME_MSG_ON = 1,
DFLT_HST_SIZE = 700,
} settings_values;

View File

@@ -38,8 +38,10 @@
#include <sys/socket.h>
#include <unistd.h>
#include <limits.h>
#include <termios.h>
#include <tox/tox.h>
#include <tox/toxencryptsave.h>
#include "configdir.h"
#include "toxic.h"
@@ -53,6 +55,7 @@
#include "log.h"
#include "notify.h"
#include "device.h"
#include "message_queue.h"
#ifdef _AUDIO
#include "audio_call.h"
@@ -74,9 +77,19 @@ ToxWindow *prompt = NULL;
#define AUTOSAVE_FREQ 60
struct _Winthread Winthread;
struct _cqueue_thread cqueue_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;
char pass[MAX_PASSWORD_LEN + 1];
int len;
} user_password;
static void catch_SIGINT(int sig)
{
Winthread.sig_exit_toxic = true;
@@ -105,6 +118,7 @@ static void init_signal_catchers(void)
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);
@@ -182,8 +196,15 @@ static struct _init_messages {
} init_messages;
/* One-time queue for messages created during init. Do not use after program init. */
static void queue_init_message(const char *msg)
static void queue_init_message(const char *msg, ...)
{
char frmt_msg[MAX_STR_SIZE] = {0};
va_list args;
va_start(args, msg);
vsnprintf(frmt_msg, sizeof(frmt_msg), msg, args);
va_end(args);
int i = init_messages.num;
++init_messages.num;
@@ -197,7 +218,7 @@ static void queue_init_message(const char *msg)
if (new_msgs[i] == NULL)
exit_toxic_err("Failed in queue_init_message", FATALERR_MEMORY);
snprintf(new_msgs[i], MAX_STR_SIZE, "%s", msg);
snprintf(new_msgs[i], MAX_STR_SIZE, "%s", frmt_msg);
init_messages.msgs = new_msgs;
}
@@ -237,16 +258,16 @@ static Tox *init_tox(void)
char tmp[48];
snprintf(tmp, sizeof(tmp), "Using proxy %s : %d",
arg_opts.proxy_address, arg_opts.proxy_port);
queue_init_message(tmp);
queue_init_message("%s", tmp);
}
if (tox_opts.udp_disabled) {
queue_init_message("UDP disabled");
} else if (tox_opts.proxy_enabled) {
const char *msg = "WARNING: Using a proxy without disabling UDP may leak your real IP address.";
queue_init_message(msg);
queue_init_message("%s", msg);
msg = "Use the -t option to disable UDP.";
queue_init_message(msg);
queue_init_message("%s", msg);
}
/* Init core */
@@ -283,6 +304,7 @@ static Tox *init_tox(void)
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);
#ifdef __linux__
tox_set_name(m, (uint8_t *) "Cool dude", strlen("Cool dude"));
@@ -456,6 +478,104 @@ static void load_friendlist(Tox *m)
sort_friendlist_index();
}
/* return length of password on success, 0 on failure */
static int password_prompt(char *buf, int size)
{
buf[0] = '\0';
/* disable terminal echo */
struct termios oflags, nflags;
tcgetattr(fileno(stdin), &oflags);
nflags = oflags;
nflags.c_lflag &= ~ECHO;
nflags.c_lflag |= ECHONL;
if (tcsetattr(fileno(stdin), TCSANOW, &nflags) != 0)
return 0;
const char *p = fgets(buf, size, stdin);
int len = strlen(buf);
/* re-enable terminal echo */
tcsetattr(fileno(stdin), TCSANOW, &oflags);
if (p == NULL || len <= 1)
return 0;
/* eat overflowed stdin and return error */
if (buf[--len] != '\n') {
int ch;
while ((ch = getchar()) != '\n' && ch > 0)
;
return 0;
}
buf[len] = '\0';
return len;
}
/* Ask user if they would like to encrypt the data file and set password */
static void first_time_encrypt(const char *msg)
{
char ch[256] = {0};
do {
system("clear");
printf("%s ", msg);
if (!strcasecmp(ch, "y\n") || !strcasecmp(ch, "n\n") || !strcasecmp(ch, "yes\n")
|| !strcasecmp(ch, "no\n") || !strcasecmp(ch, "q\n"))
break;
} while (fgets(ch, sizeof(ch), stdin));
printf("\n");
if (ch[0] == 'q' || ch[0] == 'Q')
exit(0);
if (ch[0] == 'y' || ch[0] == 'Y') {
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) {
len = password_prompt(user_password.pass, sizeof(user_password.pass));
user_password.len = len;
if (strcasecmp(user_password.pass, "q") == 0)
exit(0);
if (string_is_empty(passconfirm) && (len < MIN_PASSWORD_LEN || len > MAX_PASSWORD_LEN)) {
printf("Password must be between %d and %d characters long. ", MIN_PASSWORD_LEN, MAX_PASSWORD_LEN);
continue;
}
if (string_is_empty(passconfirm)) {
printf("Enter password again ");
snprintf(passconfirm, sizeof(passconfirm), "%s", user_password.pass);
continue;
}
if (strcmp(user_password.pass, passconfirm) != 0) {
memset(passconfirm, 0, sizeof(passconfirm));
memset(user_password.pass, 0, sizeof(user_password.pass));
printf("Passwords don't match. Try again. ");
continue;
}
valid_password = true;
}
queue_init_message("Data file '%s' has been encrypted", DATA_FILE);
memset(passconfirm, 0, sizeof(passconfirm));
user_password.data_is_encrypted = true;
}
system("clear");
}
/*
* Store Messenger to given location
* Return 0 stored successfully or ignoring data file
@@ -464,7 +584,7 @@ static void load_friendlist(Tox *m)
* Return -3 opening path failed
* Return -4 fwrite failed
*/
int store_data(Tox *m, char *path)
int store_data(Tox *m, const char *path)
{
if (arg_opts.ignore_data_file)
return 0;
@@ -472,13 +592,16 @@ int store_data(Tox *m, char *path)
if (path == NULL)
return -1;
int len = tox_size(m);
int len = user_password.data_is_encrypted ? tox_encrypted_size(m) : tox_size(m);
char *buf = malloc(len);
if (buf == NULL)
return -2;
tox_save(m, (uint8_t *) buf);
if (user_password.data_is_encrypted && !arg_opts.unencrypt_data)
tox_encrypted_save(m, (uint8_t *) buf, (uint8_t *) user_password.pass, user_password.len);
else
tox_save(m, (uint8_t *) buf);
FILE *fd = fopen(path, "wb");
@@ -523,7 +646,51 @@ static void load_data(Tox *m, char *path)
exit_toxic_err("failed in load_data", FATALERR_FREAD);
}
tox_load(m, (uint8_t *) buf, len);
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);
if (arg_opts.unencrypt_data && is_encrypted)
queue_init_message("Data file '%s' has been unencrypted", path);
else if (arg_opts.unencrypt_data)
queue_init_message("Warning: passed --unencrypt-data option with unencrypted data file '%s'", path);
if (is_encrypted) {
if (!arg_opts.unencrypt_data)
user_password.data_is_encrypted = true;
int pwlen = 0;
system("clear");
printf("Enter password (q to quit) ");
while (true) {
pwlen = password_prompt(user_password.pass, sizeof(user_password.pass));
user_password.len = pwlen;
if (strcasecmp(user_password.pass, "q") == 0)
exit(0);
if (pwlen < MIN_PASSWORD_LEN) {
system("clear");
sleep(1);
printf("Invalid password. Try again. ");
continue;
}
if (tox_encrypted_load(m, (uint8_t *) buf, len, (uint8_t *) user_password.pass, pwlen) == 0) {
break;
} else {
system("clear");
sleep(1);
printf("Invalid password. Try again. ");
}
}
} else {
tox_load(m, (uint8_t *) buf, len);
}
load_friendlist(m);
load_blocklist(BLOCK_FILE);
@@ -573,13 +740,34 @@ void *thread_winref(void *data)
}
}
void *thread_cqueue(void *data)
{
Tox *m = (Tox *) data;
while (true) {
pthread_mutex_lock(&Winthread.lock);
int 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)
cqueue_try_send(toxwin, m);
}
pthread_mutex_unlock(&Winthread.lock);
usleep(7000);
}
}
static void print_usage(void)
{
fprintf(stderr, "usage: toxic [OPTION] [FILE ...]\n");
fprintf(stderr, " -4, --ipv4 Force IPv4 connection\n");
fprintf(stderr, " -b --debug Enable stderr for debugging\n");
fprintf(stderr, " -b, --debug Enable stderr for debugging\n");
fprintf(stderr, " -c, --config Use specified config file\n");
fprintf(stderr, " -d, --default-locale Use default POSIX locale\n");
fprintf(stderr, " -e, --encrypt-data Encrypt an unencrypted data file\n");
fprintf(stderr, " -f, --file Use specified data file\n");
fprintf(stderr, " -h, --help Show this message and exit\n");
fprintf(stderr, " -n, --nodes Use specified DHTnodes file\n");
@@ -587,19 +775,15 @@ static void print_usage(void)
fprintf(stderr, " -p, --proxy Use proxy: Requires [IP] [port]\n");
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)
{
arg_opts.use_ipv4 = 0;
arg_opts.ignore_data_file = 0;
arg_opts.debug = 0;
arg_opts.default_locale = 0;
arg_opts.use_custom_data = 0;
arg_opts.no_connect = 0;
arg_opts.force_tcp = 0;
arg_opts.use_proxy = 0;
memset(&arg_opts, 0, sizeof(struct arg_opts));
/* set any non-zero defaults here*/
}
static void parse_args(int argc, char *argv[])
@@ -613,16 +797,18 @@ static void parse_args(int argc, char *argv[])
{"debug", no_argument, 0, 'b'},
{"default-locale", no_argument, 0, 'd'},
{"config", required_argument, 0, 'c'},
{"encrypt-data", no_argument, 0, 'e'},
{"nodes", required_argument, 0, 'n'},
{"help", no_argument, 0, 'h'},
{"noconnect", no_argument, 0, 'o'},
{"dnslist", required_argument, 0, 'r'},
{"force-tcp", no_argument, 0, 't'},
{"proxy", required_argument, 0, 'p'},
{"unencrypt-data", no_argument, 0, 'u'},
{NULL, no_argument, NULL, 0},
};
const char *opts_str = "4bdhotxc:f:n:r:p:";
const char *opts_str = "4bdehotuxc:f:n:r:p:";
int opt, indexptr;
while ((opt = getopt_long(argc, argv, opts_str, long_opts, &indexptr)) != -1) {
@@ -649,6 +835,10 @@ static void parse_args(int argc, char *argv[])
queue_init_message("Using default POSIX locale");
break;
case 'e':
arg_opts.encrypt_data = 1;
break;
case 'f':
arg_opts.use_custom_data = 1;
DATA_FILE = strdup(optarg);
@@ -660,9 +850,8 @@ static void parse_args(int argc, char *argv[])
strcpy(BLOCK_FILE, optarg);
strcat(BLOCK_FILE, "-blocklist");
char tmp[PATH_MAX];
snprintf(tmp, sizeof(tmp), "Using '%s' data file", DATA_FILE);
queue_init_message(tmp);
queue_init_message("Using '%s' data file", DATA_FILE);
break;
case 'n':
@@ -700,6 +889,10 @@ static void parse_args(int argc, char *argv[])
arg_opts.force_tcp = 1;
break;
case 'u':
arg_opts.unencrypt_data = 1;
break;
case 'x':
arg_opts.ignore_data_file = 1;
queue_init_message("Ignoring data file");
@@ -715,7 +908,7 @@ static void parse_args(int argc, char *argv[])
#define DATANAME "data"
#define BLOCKNAME "data-blocklist"
static int init_data_files(void)
static int init_default_data_files(void)
{
if (arg_opts.use_custom_data)
return 0;
@@ -723,28 +916,26 @@ static int init_data_files(void)
char *user_config_dir = get_user_config_dir();
int config_err = create_user_config_dirs(user_config_dir);
if (DATA_FILE == NULL ) {
if (config_err) {
DATA_FILE = strdup(DATANAME);
BLOCK_FILE = strdup(BLOCKNAME);
if (config_err) {
DATA_FILE = strdup(DATANAME);
BLOCK_FILE = strdup(BLOCKNAME);
if (DATA_FILE == NULL || BLOCK_FILE == NULL)
exit_toxic_err("failed in load_data_structures", FATALERR_MEMORY);
} else {
DATA_FILE = malloc(strlen(user_config_dir) + strlen(CONFIGDIR) + strlen(DATANAME) + 1);
BLOCK_FILE = malloc(strlen(user_config_dir) + strlen(CONFIGDIR) + strlen(BLOCKNAME) + 1);
if (DATA_FILE == NULL || BLOCK_FILE == NULL)
exit_toxic_err("failed in load_data_structures", FATALERR_MEMORY);
} else {
DATA_FILE = malloc(strlen(user_config_dir) + strlen(CONFIGDIR) + strlen(DATANAME) + 1);
BLOCK_FILE = malloc(strlen(user_config_dir) + strlen(CONFIGDIR) + strlen(BLOCKNAME) + 1);
if (DATA_FILE == NULL || BLOCK_FILE == NULL)
exit_toxic_err("failed in load_data_structures", FATALERR_MEMORY);
if (DATA_FILE == NULL || BLOCK_FILE == NULL)
exit_toxic_err("failed in load_data_structures", FATALERR_MEMORY);
strcpy(DATA_FILE, user_config_dir);
strcat(DATA_FILE, CONFIGDIR);
strcat(DATA_FILE, DATANAME);
strcpy(DATA_FILE, user_config_dir);
strcat(DATA_FILE, CONFIGDIR);
strcat(DATA_FILE, DATANAME);
strcpy(BLOCK_FILE, user_config_dir);
strcat(BLOCK_FILE, CONFIGDIR);
strcat(BLOCK_FILE, BLOCKNAME);
}
strcpy(BLOCK_FILE, user_config_dir);
strcat(BLOCK_FILE, CONFIGDIR);
strcat(BLOCK_FILE, BLOCKNAME);
}
free(user_config_dir);
@@ -775,9 +966,28 @@ int main(int argc, char *argv[])
init_signal_catchers();
parse_args(argc, argv);
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_data_files();
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)");
}
/* init user_settings struct and load settings from conf file */
user_settings_ = calloc(1, sizeof(struct user_settings));
@@ -785,22 +995,23 @@ int main(int argc, char *argv[])
if (user_settings_ == NULL)
exit_toxic_err("failed in main", FATALERR_MEMORY);
char *p = arg_opts.config_path[0] ? arg_opts.config_path : NULL;
const char *p = arg_opts.config_path[0] ? arg_opts.config_path : NULL;
int settings_err = settings_load(user_settings_, p);
Tox *m = init_tox();
init_term();
/* enable stderr for debugging */
if (!arg_opts.debug)
freopen("/dev/null", "w", stderr);
if (m == NULL)
exit_toxic_err("failed in main", FATALERR_NETWORKINIT);
if (!arg_opts.ignore_data_file)
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);
@@ -811,11 +1022,14 @@ int main(int argc, char *argv[])
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);
set_primary_device(input, user_settings_->audio_in_dev);
set_primary_device(output, user_settings_->audio_out_dev);
@@ -835,7 +1049,7 @@ int main(int argc, char *argv[])
if (config_err) {
msg = "Unable to determine configuration directory. Defaulting to 'data' for data file...";
queue_init_message(msg);
queue_init_message("%s", msg);
}
if (settings_err == -1)

View File

@@ -79,6 +79,7 @@ typedef enum _FATAL_ERRS {
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 */
} FATAL_ERRS;
/* Fixes text color problem on some terminals.
@@ -88,7 +89,7 @@ typedef enum _FATAL_ERRS {
void exit_toxic_success(Tox *m);
void exit_toxic_err(const char *errmsg, int errcode);
int store_data(Tox *m, char *path);
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);
@@ -108,5 +109,6 @@ void on_file_control(Tox *m, int32_t friendnumber, uint8_t receive_send, uint8_t
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);
#endif /* #define _toxic_h */

View File

@@ -219,6 +219,15 @@ void on_file_data(Tox *m, int32_t friendnumber, uint8_t filenumber, const uint8_
}
}
void on_read_receipt(Tox *m, int32_t friendnumber, uint32_t receipt, void *userdata)
{
int i;
for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
if (windows[i].onReadReceipt != NULL)
windows[i].onReadReceipt(&windows[i], m, friendnumber, receipt);
}
}
/* CALLBACKS END */
int add_window(Tox *m, ToxWindow w)

View File

@@ -71,6 +71,10 @@ struct _Winthread {
bool flag_resize;
};
struct _cqueue_thread {
pthread_t tid;
};
struct arg_opts {
int ignore_data_file;
int use_ipv4;
@@ -79,7 +83,8 @@ struct arg_opts {
int default_locale;
int use_custom_data;
int no_connect;
int encrypt_data;
int unencrypt_data;
char dns_path[MAX_STR_SIZE];
char config_path[MAX_STR_SIZE];
char nodes_path[MAX_STR_SIZE];
@@ -115,6 +120,7 @@ struct ToxWindow {
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);
#ifdef _AUDIO
@@ -208,6 +214,7 @@ struct ChatContext {
struct history *hst;
struct chatlog *log;
struct chat_queue *cqueue;
#ifdef _AUDIO
struct infobox infobox;