1
0
mirror of https://github.com/profanity-im/profanity.git synced 2024-11-03 19:37:16 -05:00

fix conflicts

This commit is contained in:
Will Song 2015-05-29 19:53:37 -05:00
commit 9463c67190
No known key found for this signature in database
GPG Key ID: AF0CA153EA5D9C7C
138 changed files with 7452 additions and 6201 deletions

7
.gitignore vendored
View File

@ -5,6 +5,7 @@
# *.[oa]
# *~
profanity
profanity.sh
*.o
*.log
*.swp
@ -25,7 +26,7 @@ configure.scan
stamp-h1
*~
*dirstamp
valgrind.out
valgrind*.out*
core
bugs/
TODO
@ -64,3 +65,7 @@ profanity.workspace
m4/
test.sh
clean-test.sh
callgrind.out.*
gen_docs.sh
main_fragment.html
toc_fragment.html

View File

@ -1,7 +1,7 @@
language: c
install:
- sudo apt-get update
- sudo apt-get -y install libssl-dev libexpat1-dev libncursesw5-dev libglib2.0-dev libnotify-dev libcurl3-dev libxss-dev libotr2-dev
- sudo apt-get -y install libssl-dev libexpat1-dev libncursesw5-dev libglib2.0-dev libnotify-dev libcurl3-dev libxss-dev libotr2-dev uuid-dev
- git clone git://github.com/strophe/libstrophe.git
- cd libstrophe
- mkdir m4
@ -11,15 +11,15 @@ install:
- sudo make install
- cd ..
- rm -rf libstrophe
- wget https://open.cryptomilk.org/attachments/download/42/cmocka-0.4.1.tar.xz
- tar -xvf cmocka-0.4.1.tar.xz
- cd cmocka-0.4.1
- wget https://cmocka.org/files/1.0/cmocka-1.0.0.tar.xz
- tar -xvf cmocka-1.0.0.tar.xz
- cd cmocka-1.0.0
- mkdir build
- cd build
- cmake -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Debug ..
- make
- sudo make install
- cd ../..
- rm -rf cmocka-0.4.1
- rm -rf cmocka-1.0.0
- ./bootstrap.sh
script: ./configure && make && make check

View File

@ -1,16 +1,26 @@
0.4.7
=====
- GNU Readline
- Message Carbons (xep-0280)
- Message Delivery Receipts (xep-0184)
- MUC Mediated Invitation support
0.4.6
=====
- 16 colour support
- 16 colour support (/theme colours)
- UI preferences included in themes
- Word wrapping (/wrap)
- Show hide time (/time)
- Show or hide and customise roster panel (/roster)
- /wrap - Word wrapping
- /time - Show/hide time in main window, and configure precision
- /roster - Show/hide and customise roster panel
- /roster and /occupants panel size settings (% of screen width)
- /account default - Set default account for /connect
- /account remove
- Added default account for /connect
- Additional readline style shortcuts
- Improved chat session handling
- Override resource during chat and resource display settings (/resource)
- Disable terminal title by default, additonal title on exit
- Dynamic input blocking timeout to use less CPU
- eval_password property on accounts for retrieving password from keyring/keychain
- /presence - Show/hide contact presence in titlebar
- /resource - Override resource during chat, resource display settings
- Improved chat session handling <http://xmpp.org/rfcs/rfc6121.html#message-chat>
- Lower CPU usage with dynamic input blocking timeout
- Keychain/keyring integration using account eval_password property
- Disable term window title by default
- Fixed remote code execution bug on OSX when desktop notifications configured to show message text

View File

@ -1,5 +1,5 @@
Profanity
Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
Profanity is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@ -13,7 +13,9 @@ core_sources = \
src/xmpp/roster.c src/xmpp/roster.h \
src/xmpp/bookmark.c src/xmpp/bookmark.h \
src/xmpp/form.c src/xmpp/form.h \
src/server_events.c src/server_events.h \
src/event/server_events.c src/event/server_events.h \
src/event/client_events.c src/event/client_events.h \
src/event/ui_events.c src/event/ui_events.h \
src/ui/ui.h src/ui/window.c src/ui/window.h src/ui/core.c \
src/ui/titlebar.c src/ui/statusbar.c src/ui/inputwin.c \
src/ui/titlebar.h src/ui/statusbar.h src/ui/inputwin.h \
@ -27,7 +29,6 @@ core_sources = \
src/tools/parser.h \
src/tools/p_sha1.h src/tools/p_sha1.c \
src/tools/autocomplete.c src/tools/autocomplete.h \
src/tools/history.c src/tools/history.h \
src/tools/tinyurl.c src/tools/tinyurl.h \
src/config/accounts.c src/config/accounts.h \
src/config/account.c src/config/account.h \
@ -44,13 +45,13 @@ tests_sources = \
src/roster_list.c src/roster_list.h \
src/xmpp/xmpp.h src/xmpp/form.c \
src/ui/ui.h \
src/otr/otr.h \
src/command/command.h src/command/command.c \
src/command/commands.h src/command/commands.c \
src/tools/parser.c \
src/tools/parser.h \
src/tools/p_sha1.h src/tools/p_sha1.c \
src/tools/autocomplete.c src/tools/autocomplete.h \
src/tools/history.c src/tools/history.h \
src/tools/tinyurl.c src/tools/tinyurl.h \
src/config/accounts.h \
src/config/account.c src/config/account.h \
@ -61,9 +62,10 @@ tests_sources = \
src/ui/buffer.c \
src/ui/titlebar.c src/ui/statusbar.c src/ui/inputwin.c \
src/ui/titlebar.h src/ui/statusbar.h src/ui/inputwin.h \
src/server_events.c src/server_events.h \
src/event/server_events.c src/event/server_events.h \
src/event/client_events.c src/event/client_events.h \
src/event/ui_events.c src/event/ui_events.h \
tests/xmpp/stub_xmpp.c \
tests/otr/stub_otr.c \
tests/ui/stub_ui.c \
tests/log/stub_log.c \
tests/config/stub_accounts.c \
@ -78,12 +80,10 @@ tests_sources = \
tests/test_cmd_roster.c tests/test_cmd_roster.h \
tests/test_cmd_statuses.c tests/test_cmd_statuses.h \
tests/test_cmd_sub.c tests/test_cmd_sub.h \
tests/test_cmd_win.c tests/test_cmd_win.h \
tests/test_cmd_disconnect.c tests/test_cmd_disconnect.h \
tests/test_common.c tests/test_common.h \
tests/test_contact.c tests/test_contact.h \
tests/test_form.c tests/test_form.h \
tests/test_history.c tests/test_history.h \
tests/test_jid.c tests/test_jid.h \
tests/test_muc.c tests/test_muc.h \
tests/test_parser.c tests/test_parser.h \
@ -104,6 +104,9 @@ otr3_sources = \
otr4_sources = \
src/otr/otrlib.h src/otr/otrlibv4.c src/otr/otr.h src/otr/otr.c
otr_test_sources = \
tests/otr/stub_otr.c
themes_sources = themes/*
script_sources = bootstrap.sh configure-debug install-all.sh
@ -111,6 +114,7 @@ script_sources = bootstrap.sh configure-debug install-all.sh
man_sources = docs/profanity.1
if BUILD_OTR
tests_sources += $(otr_test_sources)
if BUILD_OTR3
core_sources += $(otr3_sources)
endif

View File

@ -1,7 +1,7 @@
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
AC_INIT([profanity], [0.4.6], [boothj5web@gmail.com])
AC_INIT([profanity], [0.4.7], [boothj5web@gmail.com])
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_SRCDIR([src/main.c])
AC_CONFIG_HEADERS([src/config.h])
@ -34,6 +34,8 @@ AC_DEFINE_UNQUOTED([PACKAGE_STATUS], ["$PACKAGE_STATUS"], [Status of this build]
AS_IF([test "x$PLATFORM" = xcygwin],
[AC_DEFINE([PLATFORM_CYGWIN], [1], [Cygwin])])
AS_IF([test "x$PLATFORM" = xosx],
[AC_DEFINE([PLATFORM_OSX], [1], [OSx])])
### Options
AC_ARG_ENABLE([notifications],
@ -134,10 +136,23 @@ PKG_CHECK_MODULES([glib], [glib-2.0 >= 2.26], [],
PKG_CHECK_MODULES([curl], [libcurl], [],
[AC_MSG_ERROR([libcurl is required for profanity])])
AS_IF([test "x$PLATFORM" != xosx],
[AC_CHECK_LIB([readline], [main], [],
[AC_MSG_ERROR([libreadline is required for profanity])])],
[AC_CHECK_FILE([/usr/local/opt/readline/lib],
[LIBS="-lreadline $LIBS"
AM_CPPFLAGS="-I/usr/local/opt/readline/include $AM_CPPFLAGS"
AM_LDFLAGS="-L/usr/local/opt/readline/lib $AM_LDFLAGS"
AC_SUBST(AM_LDFLAGS)],
[AC_MSG_ERROR([libreadline is required for profanity])])])
AC_CHECK_LIB([uuid], [uuid_generate], [],
[AC_MSG_ERROR([libuuid is required for profanity])])
AS_IF([test "x$PLATFORM" = xosx], [LIBS="-lcurl $LIBS"])
### Check for desktop notification support
### Linux requires libnotify
### Linux/FreeBSD require libnotify
### Windows uses native OS calls
### OSX requires terminal-notifier
@ -150,7 +165,7 @@ AS_IF([test "x$PLATFORM" = xosx],
[AC_MSG_ERROR([terminal-notifier not found, required for desktop notifications.])],
[AC_MSG_NOTICE([Desktop notifications not supported.])])],
[AC_DEFINE([HAVE_OSXNOTIFY], [1], [terminal notifier])])])],
[test "x$PLATFORM" = xnix],
[test "x$PLATFORM" = xnix -o "x$PLATFORM" = xfreebsd],
[AS_IF([test "x$enable_notifications" != xno],
[PKG_CHECK_MODULES([libnotify], [libnotify],
[AC_DEFINE([HAVE_LIBNOTIFY], [1], [libnotify module])],

View File

@ -1,9 +1,9 @@
.TH Profanity 1 "March 2014" "Profanity XMPP client"
.TH Profanity 1 "February 2015" "Profanity XMPP client"
.SH NAME
Profanity \- a simple console based XMPP chat client.
.SH SYNOPSIS
.B profanity
[\-vhd] [\-l level]
[\-vhd] [\-l level] [\-a account]
.SH DESCRIPTION
.B Profanity
is a simple lightweight console based XMPP chat client. Its emphasis is
@ -15,19 +15,21 @@ at:
.SH OPTIONS
.TP
.BI "\-v, \-\-version"
Show version information.
Show version and build information.
.TP
.BI "\-h, \-\-help"
Show help on command line arguments.
.TP
.BI "\-a, \-\-account"
Auto connect to an account on startup.
.BI "\-a, \-\-account "ACCOUNT
Auto connect to an account on startup,
.I ACCOUNT
must be an existing account.
.TP
.BI "\-d, \-\-disable\-tls"
Disable TLS for servers that either don't support it, or claim to but do not
complete the handshake.
.TP
.BI "\-l, \-\-log="LEVEL
.BI "\-l, \-\-log "LEVEL
Set the logging level,
.I LEVEL
may be set to DEBUG, INFO (the default), WARN or ERROR.
@ -45,10 +47,10 @@ is stored in
, details on configuring Profanity can be found at <http://www.profanity.im/configuration.html>.
.PP
.SH BUGS
Bugs can either be reported by sending a mail directly to:
Bugs can either be reported by raising an issue at the Github issue tracker:
.br
.PP
<boothj5web@gmail.com>
<https://github.com/boothj5/profanity/issues>
.br
.PP
or to the mailing list at:
@ -57,12 +59,14 @@ or to the mailing list at:
<https://groups.google.com/forum/#!forum/profanitydev>
.br
.PP
or with a Github account by logging issues on the issue tracker at:
or by sending a mail directly to:
.br
.PP
<boothj5web@gmail.com>
.br
.PP
<https://github.com/boothj5/profanity>
.SH LICENSE
Copyright (C) 2012 \- 2014 James Booth <boothj5web@gmail.com>.
Copyright (C) 2012 \- 2015 James Booth <boothj5web@gmail.com>.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

View File

@ -24,7 +24,7 @@ debian_prepare()
echo
echo Profanity installer... installing dependencies
echo
sudo apt-get -y install git automake autoconf libssl-dev libexpat1-dev libncursesw5-dev libglib2.0-dev libnotify-dev libcurl3-dev libxss-dev libotr5-dev libtool
sudo apt-get -y install git automake autoconf libssl-dev libexpat1-dev libncursesw5-dev libglib2.0-dev libnotify-dev libcurl3-dev libxss-dev libotr5-dev libreadline-dev libtool uuid-dev
}
@ -36,7 +36,7 @@ fedora_prepare()
ARCH=`arch`
sudo yum -y install gcc git autoconf automake openssl-devel.$ARCH expat-devel.$ARCH ncurses-devel.$ARCH glib2-devel.$ARCH libnotify-devel.$ARCH libcurl-devel.$ARCH libXScrnSaver-devel.$ARCH libotr3-devel.$ARCH libtool
sudo yum -y install gcc git autoconf automake openssl-devel.$ARCH expat-devel.$ARCH ncurses-devel.$ARCH glib2-devel.$ARCH libnotify-devel.$ARCH libcurl-devel.$ARCH libXScrnSaver-devel.$ARCH libotr3-devel.$ARCH readline-devel.$ARCH libtool uuid-devel.$ARCH
}
opensuse_prepare()
@ -44,7 +44,7 @@ opensuse_prepare()
echo
echo Profanity installer...installing dependencies
echo
sudo zypper -n in gcc git automake make autoconf libopenssl-devel expat libexpat-devel ncurses-devel glib2-devel libnotify-devel libcurl-devel libXScrnSaver-devel libotr-devel libtool
sudo zypper -n in gcc git automake make autoconf libopenssl-devel expat libexpat-devel ncurses-devel glib2-devel libnotify-devel libcurl-devel libXScrnSaver-devel libotr-devel readline-devel libtool libuuid-devel
}
cygwin_prepare()
@ -60,9 +60,9 @@ cygwin_prepare()
mv apt-cyg /usr/local/bin/
if [ -n "$CYG_MIRROR" ]; then
apt-cyg -m $CYG_MIRROR install git make gcc-core m4 automake autoconf pkg-config openssl-devel libexpat-devel zlib-devel libncursesw-devel libglib2.0-devel libcurl-devel libidn-devel libssh2-devel libkrb5-devel openldap-devel libgcrypt-devel libtool
apt-cyg -m $CYG_MIRROR install git make gcc-core m4 automake autoconf pkg-config openssl-devel libexpat-devel zlib-devel libncursesw-devel libglib2.0-devel libcurl-devel libidn-devel libssh2-devel libkrb5-devel openldap-devel libgcrypt-devel libreadline-devel libtool libuuid-devel
else
apt-cyg install git make gcc-core m4 automake autoconf pkg-config openssl-devel libexpat-devel zlib-devel libncursesw-devel libglib2.0-devel libcurl-devel libidn-devel libssh2-devel libkrb5-devel openldap-devel libgcrypt-devel libtool
apt-cyg install git make gcc-core m4 automake autoconf pkg-config openssl-devel libexpat-devel zlib-devel libncursesw-devel libglib2.0-devel libcurl-devel libidn-devel libssh2-devel libkrb5-devel openldap-devel libgcrypt-devel libreadline-devel libtool libuuid-devel
fi
}

View File

@ -1,7 +1,7 @@
/*
* chat_session.c
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*
@ -64,7 +64,7 @@ _chat_session_new(const char * const barejid, const char * const resource,
static void
_chat_session_free(ChatSession *session)
{
if (session != NULL) {
if (session) {
free(session->barejid);
free(session->resource);
free(session);
@ -81,7 +81,7 @@ chat_sessions_init(void)
void
chat_sessions_clear(void)
{
if (sessions != NULL)
if (sessions)
g_hash_table_remove_all(sessions);
}
@ -141,7 +141,7 @@ chat_session_recipient_active(const char * const barejid, const char * const res
// session exists with resource, update chat_states
if (g_strcmp0(session->resource, resource) == 0) {
session->send_states = send_states;
// session exists with differet resource and no override, replace
// session exists with different resource and no override, replace
} else if (!session->resource_override) {
_chat_session_new(barejid, resource, FALSE, send_states);
}

View File

@ -1,7 +1,7 @@
/*
* chat_session.h
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*

View File

@ -1,7 +1,7 @@
/*
* chat_state.c
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*

View File

@ -1,7 +1,7 @@
/*
* chat_state.h
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
/*
* command.h
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*
@ -66,4 +66,6 @@ void cmd_history_append(char *inp);
char *cmd_history_previous(char *inp);
char *cmd_history_next(char *inp);
void command_docgen(void);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
/*
* commands.h
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*
@ -62,6 +62,9 @@ typedef struct cmd_t {
CommandHelp help;
} Command;
gboolean cmd_execute_alias(const char * const inp, gboolean *ran);
gboolean cmd_execute_default(const char * inp);
gboolean cmd_about(gchar **args, struct cmd_help_t help);
gboolean cmd_account(gchar **args, struct cmd_help_t help);
gboolean cmd_autoaway(gchar **args, struct cmd_help_t help);
@ -85,6 +88,8 @@ gboolean cmd_grlog(gchar **args, struct cmd_help_t help);
gboolean cmd_group(gchar **args, struct cmd_help_t help);
gboolean cmd_help(gchar **args, struct cmd_help_t help);
gboolean cmd_history(gchar **args, struct cmd_help_t help);
gboolean cmd_carbons(gchar **args, struct cmd_help_t help);
gboolean cmd_receipts(gchar **args, struct cmd_help_t help);
gboolean cmd_info(gchar **args, struct cmd_help_t help);
gboolean cmd_intype(gchar **args, struct cmd_help_t help);
gboolean cmd_invite(gchar **args, struct cmd_help_t help);

View File

@ -1,7 +1,7 @@
/*
* common.c
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*
@ -202,6 +202,33 @@ str_contains(const char str[], int size, char ch)
return 0;
}
gboolean
strtoi_range(char *str, int *saveptr, int min, int max, char **err_msg)
{
char *ptr;
int val;
errno = 0;
val = (int)strtol(str, &ptr, 0);
if (errno != 0 || *str == '\0' || *ptr != '\0') {
GString *err_str = g_string_new("");
g_string_printf(err_str, "Could not convert \"%s\" to a number.", str);
*err_msg = err_str->str;
g_string_free(err_str, FALSE);
return FALSE;
} else if (val < min || val > max) {
GString *err_str = g_string_new("");
g_string_printf(err_str, "Value %s out of range. Must be in %d..%d.", str, min, max);
*err_msg = err_str->str;
g_string_free(err_str, FALSE);
return FALSE;
}
*saveptr = val;
return TRUE;
}
int
utf8_display_len(const char * const str)
{
@ -224,6 +251,18 @@ utf8_display_len(const char * const str)
return len;
}
gboolean
utf8_is_printable(const wint_t ch)
{
char bytes[MB_CUR_MAX+1];
size_t utf_len = wcrtomb(bytes, ch, NULL);
bytes[utf_len] = '\0';
gunichar unichar = g_utf8_get_char(bytes);
return g_unichar_isprint(unichar) && (ch != KEY_MOUSE);
}
char *
prof_getline(FILE *stream)
{
@ -248,7 +287,7 @@ prof_getline(FILE *stream)
result = (char *)realloc(s, s_size + buf_size);
if (result == NULL) {
if (s != NULL) {
if (s) {
free(s);
s = NULL;
}
@ -286,7 +325,7 @@ release_get_latest()
curl_easy_perform(handle);
curl_easy_cleanup(handle);
if (output.buffer != NULL) {
if (output.buffer) {
output.buffer[output.size++] = '\0';
return output.buffer;
} else {
@ -393,10 +432,10 @@ gchar *
xdg_get_config_home(void)
{
gchar *xdg_config_home = getenv("XDG_CONFIG_HOME");
if (xdg_config_home != NULL)
if (xdg_config_home)
g_strstrip(xdg_config_home);
if ((xdg_config_home != NULL) && (strcmp(xdg_config_home, "") != 0)) {
if (xdg_config_home && (strcmp(xdg_config_home, "") != 0)) {
return strdup(xdg_config_home);
} else {
GString *default_path = g_string_new(getenv("HOME"));
@ -412,10 +451,10 @@ gchar *
xdg_get_data_home(void)
{
gchar *xdg_data_home = getenv("XDG_DATA_HOME");
if (xdg_data_home != NULL)
if (xdg_data_home)
g_strstrip(xdg_data_home);
if ((xdg_data_home != NULL) && (strcmp(xdg_data_home, "") != 0)) {
if (xdg_data_home && (strcmp(xdg_data_home, "") != 0)) {
return strdup(xdg_data_home);
} else {
GString *default_path = g_string_new(getenv("HOME"));
@ -435,7 +474,7 @@ create_unique_id(char *prefix)
GString *result_str = g_string_new("");
unique_id++;
if (prefix != NULL) {
if (prefix) {
g_string_printf(result_str, "prof_%s_%lu", prefix, unique_id);
} else {
g_string_printf(result_str, "prof_%lu", unique_id);
@ -488,25 +527,34 @@ cmp_win_num(gconstpointer a, gconstpointer b)
int
get_next_available_win_num(GList *used)
{
used = g_list_sort(used, cmp_win_num);
// only console used
if (g_list_length(used) == 1) {
return 2;
} else {
GList *sorted = NULL;
GList *curr = used;
while (curr) {
sorted = g_list_insert_sorted(sorted, curr->data, cmp_win_num);
curr = g_list_next(curr);
}
int result = 0;
int last_num = 1;
GList *curr = used;
curr = sorted;
// skip console
curr = g_list_next(curr);
while (curr != NULL) {
while (curr) {
int curr_num = GPOINTER_TO_INT(curr->data);
if (((last_num != 9) && ((last_num + 1) != curr_num)) ||
((last_num == 9) && (curr_num != 0))) {
result = last_num + 1;
if (result == 10) {
result = 0;
}
g_list_free(sorted);
return (result);
} else {
last_num = curr_num;
if (last_num == 0) {
@ -520,6 +568,7 @@ get_next_available_win_num(GList *used)
result = 0;
}
g_list_free(sorted);
return result;
}
}
@ -566,3 +615,25 @@ get_file_or_linked(char *loc, char *basedir)
return true_loc;
}
char *
strip_arg_quotes(const char * const input)
{
char *unquoted = strdup(input);
// Remove starting quote if it exists
if(strchr(unquoted, '"')) {
if(strchr(unquoted, ' ') + 1 == strchr(unquoted, '"')) {
memmove(strchr(unquoted, '"'), strchr(unquoted, '"')+1, strchr(unquoted, '\0') - strchr(unquoted, '"'));
}
}
// Remove ending quote if it exists
if(strchr(unquoted, '"')) {
if(strchr(unquoted, '\0') - 1 == strchr(unquoted, '"')) {
memmove(strchr(unquoted, '"'), strchr(unquoted, '"')+1, strchr(unquoted, '\0') - strchr(unquoted, '"'));
}
}
return unquoted;
}

View File

@ -1,7 +1,7 @@
/*
* common.h
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*
@ -36,6 +36,13 @@
#define COMMON_H
#include <stdio.h>
#include <wchar.h>
#ifdef HAVE_NCURSESW_NCURSES_H
#include <ncursesw/ncurses.h>
#elif HAVE_NCURSES_H
#include <ncurses.h>
#endif
#include <glib.h>
@ -104,7 +111,9 @@ gboolean mkdir_recursive(const char *dir);
char * str_replace(const char *string, const char *substr,
const char *replacement);
int str_contains(const char str[], int size, char ch);
gboolean strtoi_range(char *str, int *saveptr, int min, int max, char **err_msg);
int utf8_display_len(const char * const str);
gboolean utf8_is_printable(const wint_t ch);
char * prof_getline(FILE *stream);
char* release_get_latest(void);
gboolean release_is_new(char *found_version);
@ -123,5 +132,6 @@ int cmp_win_num(gconstpointer a, gconstpointer b);
int get_next_available_win_num(GList *used);
char* get_file_or_linked(char *loc, char *basedir);
char * strip_arg_quotes(const char * const input);
#endif

View File

@ -1,7 +1,7 @@
/*
* account.c
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*
@ -34,12 +34,14 @@
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <glib.h>
#include "jid.h"
#include "config/account.h"
#include "common.h"
#include "log.h"
ProfAccount*
account_new(const gchar * const name, const gchar * const jid,
@ -55,19 +57,19 @@ account_new(const gchar * const name, const gchar * const jid,
new_account->name = strdup(name);
if (jid != NULL) {
if (jid) {
new_account->jid = strdup(jid);
} else {
new_account->jid = strdup(name);
}
if (password != NULL) {
if (password) {
new_account->password = strdup(password);
} else {
new_account->password = NULL;
}
if (eval_password != NULL) {
if (eval_password) {
new_account->eval_password = strdup(eval_password);
} else {
new_account->eval_password = NULL;
@ -75,13 +77,13 @@ account_new(const gchar * const name, const gchar * const jid,
new_account->enabled = enabled;
if (server != NULL) {
if (server) {
new_account->server = strdup(server);
} else {
new_account->server = NULL;
}
if (resource != NULL) {
if (resource) {
new_account->resource = strdup(resource);
} else {
new_account->resource = NULL;
@ -132,7 +134,7 @@ account_new(const gchar * const name, const gchar * const jid,
new_account->muc_nick = strdup(muc_nick);
}
if (otr_policy != NULL) {
if (otr_policy) {
new_account->otr_policy = strdup(otr_policy);
} else {
new_account->otr_policy = NULL;
@ -148,17 +150,55 @@ account_new(const gchar * const name, const gchar * const jid,
char *
account_create_full_jid(ProfAccount *account)
{
if (account->resource != NULL) {
if (account->resource) {
return create_fulljid(account->jid, account->resource);
} else {
return strdup(account->jid);
}
}
gboolean
account_eval_password(ProfAccount *account)
{
assert(account != NULL);
assert(account->eval_password != NULL);
// Evaluate as shell command to retrieve password
GString *cmd = g_string_new("");
g_string_append_printf(cmd, "%s 2>/dev/null", account->eval_password);
FILE *stream = popen(cmd->str, "r");
g_string_free(cmd, TRUE);
if (stream) {
// Limit to READ_BUF_SIZE bytes to prevent overflows in the case of a poorly chosen command
account->password = g_malloc(READ_BUF_SIZE);
if (!account->password) {
log_error("Failed to allocate enough memory to read eval_password output");
return FALSE;
}
account->password = fgets(account->password, READ_BUF_SIZE, stream);
pclose(stream);
if (!account->password) {
log_error("No result from eval_password.");
return FALSE;
}
// strip trailing newline
if (g_str_has_suffix(account->password, "\n")) {
account->password[strlen(account->password)-1] = '\0';
}
} else {
log_error("popen failed when running eval_password.");
return FALSE;
}
return TRUE;
}
void
account_free(ProfAccount *account)
{
if (account != NULL) {
if (account) {
free(account->name);
free(account->jid);
free(account->password);

View File

@ -1,7 +1,7 @@
/*
* account.h
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*
@ -69,9 +69,8 @@ ProfAccount* account_new(const gchar * const name, const gchar * const jid,
const gchar * const muc_service, const gchar * const muc_nick,
const gchar * const otr_policy, GList *otr_manual, GList *otr_opportunistic,
GList *otr_always);
char* account_create_full_jid(ProfAccount *account);
gboolean account_eval_password(ProfAccount *account);
void account_free(ProfAccount *account);
#endif

View File

@ -1,7 +1,7 @@
/*
* accounts.c
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*
@ -147,9 +147,9 @@ accounts_add(const char *account_name, const char *altdomain, const int port)
const char *barejid = account_name;
const char *resource = "profanity";
Jid *jid = jid_create(account_name);
if (jid != NULL) {
if (jid) {
barejid = jid->barejid;
if (jid->resourcepart != NULL) {
if (jid->resourcepart) {
resource = jid->resourcepart;
}
}
@ -159,7 +159,7 @@ accounts_add(const char *account_name, const char *altdomain, const int port)
g_key_file_set_boolean(accounts, account_name, "enabled", TRUE);
g_key_file_set_string(accounts, account_name, "jid", barejid);
g_key_file_set_string(accounts, account_name, "resource", resource);
if (altdomain != NULL) {
if (altdomain) {
g_key_file_set_string(accounts, account_name, "server", altdomain);
}
if (port != 0) {
@ -252,7 +252,7 @@ accounts_get_account(const char * const name)
gsize length;
GList *otr_manual = NULL;
gchar **manual = g_key_file_get_string_list(accounts, name, "otr.manual", &length, NULL);
if (manual != NULL) {
if (manual) {
int i = 0;
for (i = 0; i < length; i++) {
otr_manual = g_list_append(otr_manual, strdup(manual[i]));
@ -262,7 +262,7 @@ accounts_get_account(const char * const name)
GList *otr_opportunistic = NULL;
gchar **opportunistic = g_key_file_get_string_list(accounts, name, "otr.opportunistic", &length, NULL);
if (opportunistic != NULL) {
if (opportunistic) {
int i = 0;
for (i = 0; i < length; i++) {
otr_opportunistic = g_list_append(otr_opportunistic, strdup(opportunistic[i]));
@ -272,7 +272,7 @@ accounts_get_account(const char * const name)
GList *otr_always = NULL;
gchar **always = g_key_file_get_string_list(accounts, name, "otr.always", &length, NULL);
if (always != NULL) {
if (always) {
int i = 0;
for (i = 0; i < length; i++) {
otr_always = g_list_append(otr_always, strdup(always[i]));
@ -356,7 +356,7 @@ accounts_rename(const char * const account_name, const char * const new_name)
int i;
for (i = 0; i < ARRAY_SIZE(string_keys); i++) {
char *value = g_key_file_get_string(accounts, account_name, string_keys[i], NULL);
if (value != NULL) {
if (value) {
g_key_file_set_string(accounts, new_name, string_keys[i], value);
g_free(value);
}
@ -386,10 +386,10 @@ void
accounts_set_jid(const char * const account_name, const char * const value)
{
Jid *jid = jid_create(value);
if (jid != NULL) {
if (jid) {
if (accounts_account_exists(account_name)) {
g_key_file_set_string(accounts, account_name, "jid", jid->barejid);
if (jid->resourcepart != NULL) {
if (jid->resourcepart) {
g_key_file_set_string(accounts, account_name, "resource", jid->resourcepart);
}
@ -509,7 +509,7 @@ accounts_add_otr_policy(const char * const account_name, const char * const cont
GList *glist = NULL;
// list found
if (list != NULL) {
if (list) {
int i = 0;
for (i = 0; i < length; i++) {
// item already in list, exit function
@ -529,7 +529,7 @@ accounts_add_otr_policy(const char * const account_name, const char * const cont
const gchar* new_list[g_list_length(glist)+1];
GList *curr = glist;
i = 0;
while (curr != NULL) {
while (curr) {
new_list[i++] = strdup(curr->data);
curr = g_list_next(curr);
}
@ -572,7 +572,7 @@ _remove_from_list(GKeyFile *accounts, const char * const account_name, const cha
gsize length;
gchar **list = g_key_file_get_string_list(accounts, account_name, key, &length, NULL);
if (list != NULL) {
if (list) {
int i = 0;
GList *glist = NULL;
gboolean deleted = FALSE;
@ -595,7 +595,7 @@ _remove_from_list(GKeyFile *accounts, const char * const account_name, const cha
const gchar* new_list[g_list_length(glist)+1];
GList *curr = glist;
i = 0;
while (curr != NULL) {
while (curr) {
new_list[i++] = strdup(curr->data);
curr = g_list_next(curr);
}
@ -766,7 +766,7 @@ accounts_get_last_presence(const char * const account_name)
result = RESOURCE_ONLINE;
}
if (setting != NULL) {
if (setting) {
g_free(setting);
}
return result;
@ -796,7 +796,7 @@ accounts_get_login_presence(const char * const account_name)
result = RESOURCE_ONLINE;
}
if (setting != NULL) {
if (setting) {
g_free(setting);
}
return result;
@ -809,9 +809,9 @@ _fix_legacy_accounts(const char * const account_name)
const char *barejid = account_name;
const char *resource = "profanity";
Jid *jid = jid_create(account_name);
if (jid != NULL) {
if (jid) {
barejid = jid->barejid;
if (jid->resourcepart != NULL) {
if (jid->resourcepart) {
resource = jid->resourcepart;
}
}
@ -828,7 +828,7 @@ _fix_legacy_accounts(const char * const account_name)
_save_accounts();
}
// acounts with no muc service or nick
// accounts with no muc service or nick
if (!g_key_file_has_key(accounts, account_name, "muc.service", NULL)) {
gchar *account_jid = g_key_file_get_string(accounts, account_name, "jid", NULL);
Jid *jidp = jid_create(account_jid);

View File

@ -1,7 +1,7 @@
/*
* accounts.h
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*

View File

@ -1,7 +1,7 @@
/*
* preferences.c
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*
@ -62,7 +62,7 @@
#define PREF_GROUP_ALIAS "alias"
#define PREF_GROUP_OTR "otr"
#define INPBLOCK_DEFAULT 20
#define INPBLOCK_DEFAULT 1000
static gchar *prefs_loc;
static GKeyFile *prefs;
@ -95,35 +95,17 @@ prefs_load(void)
err = NULL;
log_maxsize = g_key_file_get_integer(prefs, PREF_GROUP_LOGGING, "maxsize", &err);
if (err != NULL) {
if (err) {
log_maxsize = 0;
g_error_free(err);
}
// move pre 0.4.1 OTR preferences to [otr] group
// move pre 0.4.6 OTR warn preferences to [ui] group
err = NULL;
gboolean ui_otr_warn = g_key_file_get_boolean(prefs, PREF_GROUP_UI, "otr.warn", &err);
gboolean otr_warn = g_key_file_get_boolean(prefs, PREF_GROUP_OTR, "warn", &err);
if (err == NULL) {
g_key_file_set_boolean(prefs, PREF_GROUP_OTR, _get_key(PREF_OTR_WARN), ui_otr_warn);
g_key_file_remove_key(prefs, PREF_GROUP_UI, "otr.warn", NULL);
} else {
g_error_free(err);
}
err = NULL;
gchar *ui_otr_log = g_key_file_get_string(prefs, PREF_GROUP_LOGGING, "otr", &err);
if (err == NULL) {
g_key_file_set_string(prefs, PREF_GROUP_OTR, _get_key(PREF_OTR_LOG), ui_otr_log);
g_key_file_remove_key(prefs, PREF_GROUP_LOGGING, "otr", NULL);
} else {
g_error_free(err);
}
err = NULL;
gchar *ui_otr_policy = g_key_file_get_string(prefs, "policy", "otr.policy", &err);
if (err == NULL) {
g_key_file_set_string(prefs, PREF_GROUP_OTR, _get_key(PREF_OTR_POLICY), ui_otr_policy);
g_key_file_remove_group(prefs, "policy", NULL);
g_key_file_set_boolean(prefs, PREF_GROUP_UI, _get_key(PREF_OTR_WARN), otr_warn);
g_key_file_remove_key(prefs, PREF_GROUP_OTR, "warn", NULL);
} else {
g_error_free(err);
}
@ -198,7 +180,7 @@ prefs_get_string(preference_t pref)
char *result = g_key_file_get_string(prefs, group, key, NULL);
if (result == NULL) {
if (def != NULL) {
if (def) {
return strdup(def);
} else {
return NULL;
@ -211,7 +193,7 @@ prefs_get_string(preference_t pref)
void
prefs_free_string(char *pref)
{
if (pref != NULL) {
if (pref) {
free(pref);
}
pref = NULL;
@ -358,7 +340,7 @@ prefs_get_occupants_size(void)
gint result = g_key_file_get_integer(prefs, PREF_GROUP_UI, "occupants.size", NULL);
if (result > 99 || result < 1) {
return 20;
return 15;
} else {
return result;
}
@ -377,7 +359,7 @@ prefs_get_roster_size(void)
gint result = g_key_file_get_integer(prefs, PREF_GROUP_UI, "roster.size", NULL);
if (result > 99 || result < 1) {
return 20;
return 25;
} else {
return result;
}
@ -437,7 +419,7 @@ prefs_get_aliases(void)
char *name = keys[i];
char *value = g_key_file_get_string(prefs, PREF_GROUP_ALIAS, name, NULL);
if (value != NULL) {
if (value) {
ProfAlias *alias = malloc(sizeof(struct prof_alias_t));
alias->name = strdup(name);
alias->value = strdup(value);
@ -517,6 +499,7 @@ _get_group(preference_t pref)
case PREF_HISTORY:
case PREF_MOUSE:
case PREF_OCCUPANTS:
case PREF_OCCUPANTS_JID:
case PREF_STATUSES:
case PREF_STATUSES_CONSOLE:
case PREF_STATUSES_CHAT:
@ -525,12 +508,14 @@ _get_group(preference_t pref)
case PREF_PRESENCE:
case PREF_WRAP:
case PREF_TIME:
case PREF_TIME_STATUSBAR:
case PREF_ROSTER:
case PREF_ROSTER_OFFLINE:
case PREF_ROSTER_RESOURCE:
case PREF_ROSTER_BY:
case PREF_RESOURCE_TITLE:
case PREF_RESOURCE_MESSAGE:
case PREF_OTR_WARN:
case PREF_INPBLOCK_DYNAMIC:
return PREF_GROUP_UI;
case PREF_STATES:
@ -558,8 +543,10 @@ _get_group(preference_t pref)
return PREF_GROUP_PRESENCE;
case PREF_CONNECT_ACCOUNT:
case PREF_DEFAULT_ACCOUNT:
case PREF_CARBONS:
case PREF_RECEIPTS_SEND:
case PREF_RECEIPTS_REQUEST:
return PREF_GROUP_CONNECTION;
case PREF_OTR_WARN:
case PREF_OTR_LOG:
case PREF_OTR_POLICY:
return PREF_GROUP_OTR;
@ -593,10 +580,18 @@ _get_key(preference_t pref)
return "intype";
case PREF_HISTORY:
return "history";
case PREF_CARBONS:
return "carbons";
case PREF_RECEIPTS_SEND:
return "receipts.send";
case PREF_RECEIPTS_REQUEST:
return "receipts.request";
case PREF_MOUSE:
return "mouse";
case PREF_OCCUPANTS:
return "occupants";
case PREF_OCCUPANTS_JID:
return "occupants.jid";
case PREF_MUC_PRIVILEGES:
return "privileges";
case PREF_STATUSES:
@ -648,7 +643,7 @@ _get_key(preference_t pref)
case PREF_OTR_LOG:
return "log";
case PREF_OTR_WARN:
return "warn";
return "otr.warn";
case PREF_OTR_POLICY:
return "policy";
case PREF_LOG_ROTATE:
@ -661,6 +656,8 @@ _get_key(preference_t pref)
return "wrap";
case PREF_TIME:
return "time";
case PREF_TIME_STATUSBAR:
return "time.statusbar";
case PREF_ROSTER:
return "roster";
case PREF_ROSTER_OFFLINE:
@ -691,15 +688,24 @@ _get_default_boolean(preference_t pref)
case PREF_AUTOAWAY_CHECK:
case PREF_LOG_ROTATE:
case PREF_LOG_SHARED:
case PREF_NOTIFY_MESSAGE:
case PREF_NOTIFY_MESSAGE_CURRENT:
case PREF_NOTIFY_ROOM_CURRENT:
case PREF_NOTIFY_TYPING:
case PREF_NOTIFY_TYPING_CURRENT:
case PREF_NOTIFY_SUB:
case PREF_NOTIFY_INVITE:
case PREF_SPLASH:
case PREF_OCCUPANTS:
case PREF_MUC_PRIVILEGES:
case PREF_PRESENCE:
case PREF_WRAP:
case PREF_INPBLOCK_DYNAMIC:
case PREF_RESOURCE_TITLE:
case PREF_RESOURCE_MESSAGE:
case PREF_ROSTER:
case PREF_ROSTER_OFFLINE:
case PREF_ROSTER_RESOURCE:
return TRUE;
default:
return FALSE;
@ -715,7 +721,7 @@ _get_default_string(preference_t pref)
{
case PREF_AUTOAWAY_MODE:
case PREF_NOTIFY_ROOM:
return "off";
return "on";
case PREF_OTR_LOG:
return "redact";
case PREF_OTR_POLICY:
@ -725,9 +731,11 @@ _get_default_string(preference_t pref)
case PREF_STATUSES_MUC:
return "all";
case PREF_ROSTER_BY:
return "none";
return "presence";
case PREF_TIME:
return "%H:%M:%S";
case PREF_TIME_STATUSBAR:
return "%H:%M";
default:
return NULL;
}

View File

@ -1,7 +1,7 @@
/*
* preferences.h
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*
@ -59,9 +59,13 @@ typedef enum {
PREF_FLASH,
PREF_INTYPE,
PREF_HISTORY,
PREF_CARBONS,
PREF_RECEIPTS_SEND,
PREF_RECEIPTS_REQUEST,
PREF_MOUSE,
PREF_OCCUPANTS,
PREF_OCCUPANTS_SIZE,
PREF_OCCUPANTS_JID,
PREF_ROSTER,
PREF_ROSTER_SIZE,
PREF_ROSTER_OFFLINE,
@ -71,6 +75,7 @@ typedef enum {
PREF_PRESENCE,
PREF_WRAP,
PREF_TIME,
PREF_TIME_STATUSBAR,
PREF_STATUSES,
PREF_STATUSES_CONSOLE,
PREF_STATUSES_CHAT,

View File

@ -1,7 +1,7 @@
/*
* theme.c
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*
@ -121,6 +121,7 @@ static struct colours_t {
NCURSES_COLOR_T otruntrusted;
NCURSES_COLOR_T rosterheader;
NCURSES_COLOR_T occupantsheader;
NCURSES_COLOR_T receiptsent;
} colour_prefs;
static NCURSES_COLOR_T _lookup_colour(const char * const colour);
@ -159,7 +160,7 @@ _theme_load_file(const char * const theme_name)
{
// use default theme
if (theme_name == NULL || strcmp(theme_name, "default") == 0) {
if (theme != NULL) {
if (theme) {
g_key_file_free(theme);
}
theme = g_key_file_new();
@ -172,12 +173,12 @@ _theme_load_file(const char * const theme_name)
return FALSE;
}
if (theme_loc != NULL) {
if (theme_loc) {
g_string_free(theme_loc, TRUE);
}
theme_loc = new_theme_file;
log_info("Loading theme \"%s\"", theme_name);
if (theme != NULL) {
if (theme) {
g_key_file_free(theme);
}
theme = g_key_file_new();
@ -192,7 +193,9 @@ GSList *
theme_list(void)
{
GSList *result = NULL;
_theme_list_dir(_get_themes_dir(), &result);
char *themes_dir = _get_themes_dir();
_theme_list_dir(themes_dir, &result);
free(themes_dir);
#ifdef THEMES_PATH
_theme_list_dir(THEMES_PATH, &result);
#endif
@ -202,10 +205,10 @@ theme_list(void)
void
theme_close(void)
{
if (theme != NULL) {
if (theme) {
g_key_file_free(theme);
}
if (theme_loc != NULL) {
if (theme_loc) {
g_string_free(theme_loc, TRUE);
}
if (bold_items) {
@ -249,47 +252,48 @@ theme_init_colours(void)
// chat
init_pair(25, colour_prefs.me, colour_prefs.bkgnd);
init_pair(26, colour_prefs.them, colour_prefs.bkgnd);
init_pair(27, colour_prefs.receiptsent, colour_prefs.bkgnd);
// room chat
init_pair(27, colour_prefs.roominfo, colour_prefs.bkgnd);
init_pair(28, colour_prefs.roommention, colour_prefs.bkgnd);
init_pair(28, colour_prefs.roominfo, colour_prefs.bkgnd);
init_pair(29, colour_prefs.roommention, colour_prefs.bkgnd);
// statuses
init_pair(29, colour_prefs.online, colour_prefs.bkgnd);
init_pair(30, colour_prefs.offline, colour_prefs.bkgnd);
init_pair(31, colour_prefs.away, colour_prefs.bkgnd);
init_pair(32, colour_prefs.chat, colour_prefs.bkgnd);
init_pair(33, colour_prefs.dnd, colour_prefs.bkgnd);
init_pair(34, colour_prefs.xa, colour_prefs.bkgnd);
init_pair(30, colour_prefs.online, colour_prefs.bkgnd);
init_pair(31, colour_prefs.offline, colour_prefs.bkgnd);
init_pair(32, colour_prefs.away, colour_prefs.bkgnd);
init_pair(33, colour_prefs.chat, colour_prefs.bkgnd);
init_pair(34, colour_prefs.dnd, colour_prefs.bkgnd);
init_pair(35, colour_prefs.xa, colour_prefs.bkgnd);
// states
init_pair(35, colour_prefs.typing, colour_prefs.bkgnd);
init_pair(36, colour_prefs.gone, colour_prefs.bkgnd);
init_pair(36, colour_prefs.typing, colour_prefs.bkgnd);
init_pair(37, colour_prefs.gone, colour_prefs.bkgnd);
// subscription status
init_pair(37, colour_prefs.subscribed, colour_prefs.bkgnd);
init_pair(38, colour_prefs.unsubscribed, colour_prefs.bkgnd);
init_pair(38, colour_prefs.subscribed, colour_prefs.bkgnd);
init_pair(39, colour_prefs.unsubscribed, colour_prefs.bkgnd);
// otr messages
init_pair(39, colour_prefs.otrstartedtrusted, colour_prefs.bkgnd);
init_pair(40, colour_prefs.otrstarteduntrusted, colour_prefs.bkgnd);
init_pair(41, colour_prefs.otrended, colour_prefs.bkgnd);
init_pair(42, colour_prefs.otrtrusted, colour_prefs.bkgnd);
init_pair(43, colour_prefs.otruntrusted, colour_prefs.bkgnd);
init_pair(40, colour_prefs.otrstartedtrusted, colour_prefs.bkgnd);
init_pair(41, colour_prefs.otrstarteduntrusted, colour_prefs.bkgnd);
init_pair(42, colour_prefs.otrended, colour_prefs.bkgnd);
init_pair(43, colour_prefs.otrtrusted, colour_prefs.bkgnd);
init_pair(44, colour_prefs.otruntrusted, colour_prefs.bkgnd);
// subwin headers
init_pair(44, colour_prefs.rosterheader, colour_prefs.bkgnd);
init_pair(45, colour_prefs.occupantsheader, colour_prefs.bkgnd);
init_pair(45, colour_prefs.rosterheader, colour_prefs.bkgnd);
init_pair(46, colour_prefs.occupantsheader, colour_prefs.bkgnd);
// raw
init_pair(46, COLOR_WHITE, colour_prefs.bkgnd);
init_pair(47, COLOR_GREEN, colour_prefs.bkgnd);
init_pair(48, COLOR_RED, colour_prefs.bkgnd);
init_pair(49, COLOR_YELLOW, colour_prefs.bkgnd);
init_pair(50, COLOR_BLUE, colour_prefs.bkgnd);
init_pair(51, COLOR_CYAN, colour_prefs.bkgnd);
init_pair(52, COLOR_BLACK, colour_prefs.bkgnd);
init_pair(53, COLOR_MAGENTA, colour_prefs.bkgnd);
init_pair(47, COLOR_WHITE, colour_prefs.bkgnd);
init_pair(48, COLOR_GREEN, colour_prefs.bkgnd);
init_pair(49, COLOR_RED, colour_prefs.bkgnd);
init_pair(50, COLOR_YELLOW, colour_prefs.bkgnd);
init_pair(51, COLOR_BLUE, colour_prefs.bkgnd);
init_pair(52, COLOR_CYAN, colour_prefs.bkgnd);
init_pair(53, COLOR_BLACK, colour_prefs.bkgnd);
init_pair(54, COLOR_MAGENTA, colour_prefs.bkgnd);
}
static NCURSES_COLOR_T
@ -395,6 +399,7 @@ _load_colours(void)
_set_colour("them", &colour_prefs.them, COLOR_GREEN, THEME_THEM);
_set_colour("roster.header", &colour_prefs.rosterheader, COLOR_YELLOW, THEME_ROSTER_HEADER);
_set_colour("occupants.header", &colour_prefs.occupantsheader, COLOR_YELLOW, THEME_OCCUPANTS_HEADER);
_set_colour("receipt.sent", &colour_prefs.receiptsent, COLOR_RED, THEME_RECEIPT_SENT);
}
static void
@ -419,20 +424,22 @@ _set_boolean_preference(char *prefstr, preference_t pref)
static void
_load_preferences(void)
{
_set_boolean_preference("intype", PREF_INTYPE);
_set_boolean_preference("beep", PREF_BEEP);
_set_boolean_preference("flash", PREF_FLASH);
_set_boolean_preference("privileges", PREF_MUC_PRIVILEGES);
_set_boolean_preference("presence", PREF_PRESENCE);
_set_boolean_preference("splash", PREF_SPLASH);
_set_boolean_preference("wrap", PREF_WRAP);
_set_string_preference("time", PREF_TIME);
_set_string_preference("statuses.muc", PREF_STATUSES_MUC);
_set_string_preference("time.statusbar", PREF_TIME_STATUSBAR);
_set_boolean_preference("resource.title", PREF_RESOURCE_TITLE);
_set_boolean_preference("resource.message", PREF_RESOURCE_MESSAGE);
_set_string_preference("statuses.console", PREF_STATUSES_CONSOLE);
_set_string_preference("statuses.chat", PREF_STATUSES_CHAT);
_set_string_preference("statuses.muc", PREF_STATUSES_MUC);
_set_boolean_preference("occupants", PREF_OCCUPANTS);
_set_boolean_preference("occupants.jid", PREF_OCCUPANTS_JID);
if (g_key_file_has_key(theme, "ui", "occupants.size", NULL)) {
gint occupants_size = g_key_file_get_integer(theme, "ui", "occupants.size", NULL);
prefs_set_occupants_size(occupants_size);
@ -442,12 +449,16 @@ _load_preferences(void)
_set_boolean_preference("roster.offline", PREF_ROSTER_OFFLINE);
_set_boolean_preference("roster.resource", PREF_ROSTER_RESOURCE);
_set_string_preference("roster.by", PREF_ROSTER_BY);
if (g_key_file_has_key(theme, "ui", "roster.size", NULL)) {
gint roster_size = g_key_file_get_integer(theme, "ui", "roster.size", NULL);
prefs_set_roster_size(roster_size);
}
_set_boolean_preference("privileges", PREF_MUC_PRIVILEGES);
_set_boolean_preference("presence", PREF_PRESENCE);
_set_boolean_preference("intype", PREF_INTYPE);
_set_boolean_preference("otr.warn", PREF_OTR_WARN);
}
@ -465,9 +476,9 @@ void
_theme_list_dir(const gchar * const dir, GSList **result)
{
GDir *themes = g_dir_open(dir, 0, NULL);
if (themes != NULL) {
if (themes) {
const gchar *theme = g_dir_read_name(themes);
while (theme != NULL) {
while (theme) {
*result = g_slist_append(*result, strdup(theme));
theme = g_dir_read_name(themes);
}
@ -481,7 +492,7 @@ _theme_find(const char * const theme_name)
GString *path = NULL;
gchar *themes_dir = _get_themes_dir();
if (themes_dir != NULL) {
if (themes_dir) {
path = g_string_new(themes_dir);
g_free(themes_dir);
g_string_append(path, "/");
@ -557,42 +568,43 @@ theme_attrs(theme_item_t attrs)
case THEME_STATUS_NEW: result = COLOR_PAIR(24); break;
case THEME_ME: result = COLOR_PAIR(25); break;
case THEME_THEM: result = COLOR_PAIR(26); break;
case THEME_ROOMINFO: result = COLOR_PAIR(27); break;
case THEME_ROOMMENTION: result = COLOR_PAIR(28); break;
case THEME_ONLINE: result = COLOR_PAIR(29); break;
case THEME_OFFLINE: result = COLOR_PAIR(30); break;
case THEME_AWAY: result = COLOR_PAIR(31); break;
case THEME_CHAT: result = COLOR_PAIR(32); break;
case THEME_DND: result = COLOR_PAIR(33); break;
case THEME_XA: result = COLOR_PAIR(34); break;
case THEME_TYPING: result = COLOR_PAIR(35); break;
case THEME_GONE: result = COLOR_PAIR(36); break;
case THEME_SUBSCRIBED: result = COLOR_PAIR(37); break;
case THEME_UNSUBSCRIBED: result = COLOR_PAIR(38); break;
case THEME_OTR_STARTED_TRUSTED: result = COLOR_PAIR(39); break;
case THEME_OTR_STARTED_UNTRUSTED: result = COLOR_PAIR(40); break;
case THEME_OTR_ENDED: result = COLOR_PAIR(41); break;
case THEME_OTR_TRUSTED: result = COLOR_PAIR(42); break;
case THEME_OTR_UNTRUSTED: result = COLOR_PAIR(43); break;
case THEME_ROSTER_HEADER: result = COLOR_PAIR(44); break;
case THEME_OCCUPANTS_HEADER: result = COLOR_PAIR(45); break;
case THEME_WHITE: result = COLOR_PAIR(46); break;
case THEME_WHITE_BOLD: result = COLOR_PAIR(46); break;
case THEME_GREEN: result = COLOR_PAIR(47); break;
case THEME_GREEN_BOLD: result = COLOR_PAIR(47); break;
case THEME_RED: result = COLOR_PAIR(48); break;
case THEME_RED_BOLD: result = COLOR_PAIR(48); break;
case THEME_YELLOW: result = COLOR_PAIR(49); break;
case THEME_YELLOW_BOLD: result = COLOR_PAIR(49); break;
case THEME_BLUE: result = COLOR_PAIR(50); break;
case THEME_BLUE_BOLD: result = COLOR_PAIR(50); break;
case THEME_CYAN: result = COLOR_PAIR(51); break;
case THEME_CYAN_BOLD: result = COLOR_PAIR(51); break;
case THEME_BLACK: result = COLOR_PAIR(52); break;
case THEME_BLACK_BOLD: result = COLOR_PAIR(52); break;
case THEME_MAGENTA: result = COLOR_PAIR(53); break;
case THEME_MAGENTA_BOLD: result = COLOR_PAIR(53); break;
default: break;
case THEME_RECEIPT_SENT: result = COLOR_PAIR(27); break;
case THEME_ROOMINFO: result = COLOR_PAIR(28); break;
case THEME_ROOMMENTION: result = COLOR_PAIR(29); break;
case THEME_ONLINE: result = COLOR_PAIR(30); break;
case THEME_OFFLINE: result = COLOR_PAIR(31); break;
case THEME_AWAY: result = COLOR_PAIR(32); break;
case THEME_CHAT: result = COLOR_PAIR(33); break;
case THEME_DND: result = COLOR_PAIR(34); break;
case THEME_XA: result = COLOR_PAIR(35); break;
case THEME_TYPING: result = COLOR_PAIR(36); break;
case THEME_GONE: result = COLOR_PAIR(37); break;
case THEME_SUBSCRIBED: result = COLOR_PAIR(38); break;
case THEME_UNSUBSCRIBED: result = COLOR_PAIR(39); break;
case THEME_OTR_STARTED_TRUSTED: result = COLOR_PAIR(40); break;
case THEME_OTR_STARTED_UNTRUSTED: result = COLOR_PAIR(41); break;
case THEME_OTR_ENDED: result = COLOR_PAIR(42); break;
case THEME_OTR_TRUSTED: result = COLOR_PAIR(43); break;
case THEME_OTR_UNTRUSTED: result = COLOR_PAIR(44); break;
case THEME_ROSTER_HEADER: result = COLOR_PAIR(45); break;
case THEME_OCCUPANTS_HEADER: result = COLOR_PAIR(46); break;
case THEME_WHITE: result = COLOR_PAIR(47); break;
case THEME_WHITE_BOLD: result = COLOR_PAIR(47); break;
case THEME_GREEN: result = COLOR_PAIR(48); break;
case THEME_GREEN_BOLD: result = COLOR_PAIR(48); break;
case THEME_RED: result = COLOR_PAIR(49); break;
case THEME_RED_BOLD: result = COLOR_PAIR(49); break;
case THEME_YELLOW: result = COLOR_PAIR(50); break;
case THEME_YELLOW_BOLD: result = COLOR_PAIR(50); break;
case THEME_BLUE: result = COLOR_PAIR(51); break;
case THEME_BLUE_BOLD: result = COLOR_PAIR(51); break;
case THEME_CYAN: result = COLOR_PAIR(52); break;
case THEME_CYAN_BOLD: result = COLOR_PAIR(52); break;
case THEME_BLACK: result = COLOR_PAIR(53); break;
case THEME_BLACK_BOLD: result = COLOR_PAIR(53); break;
case THEME_MAGENTA: result = COLOR_PAIR(54); break;
case THEME_MAGENTA_BOLD: result = COLOR_PAIR(54); break;
default: break;
}
if (g_hash_table_lookup(bold_items, GINT_TO_POINTER(attrs))) {

View File

@ -1,7 +1,7 @@
/*
* theme.h
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*
@ -90,6 +90,7 @@ typedef enum {
THEME_OTR_UNTRUSTED,
THEME_OCCUPANTS_HEADER,
THEME_ROSTER_HEADER,
THEME_RECEIPT_SENT,
THEME_NONE,
THEME_WHITE,
THEME_WHITE_BOLD,

View File

@ -1,7 +1,7 @@
/*
* contact.c
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*
@ -45,7 +45,9 @@
struct p_contact_t {
char *barejid;
gchar *barejid_collate_key;
char *name;
gchar *name_collate_key;
GSList *groups;
char *subscription;
char *offline_message;
@ -62,21 +64,24 @@ p_contact_new(const char * const barejid, const char * const name,
{
PContact contact = malloc(sizeof(struct p_contact_t));
contact->barejid = strdup(barejid);
contact->barejid_collate_key = g_utf8_collate_key(contact->barejid, -1);
if (name != NULL) {
if (name) {
contact->name = strdup(name);
contact->name_collate_key = g_utf8_collate_key(contact->name, -1);
} else {
contact->name = NULL;
contact->name_collate_key = NULL;
}
contact->groups = groups;
if (subscription != NULL)
if (subscription)
contact->subscription = strdup(subscription);
else
contact->subscription = strdup("none");
if (offline_message != NULL)
if (offline_message)
contact->offline_message = strdup(offline_message);
else
contact->offline_message = NULL;
@ -96,15 +101,17 @@ void
p_contact_set_name(const PContact contact, const char * const name)
{
FREE_SET_NULL(contact->name);
if (name != NULL) {
FREE_SET_NULL(contact->name_collate_key);
if (name) {
contact->name = strdup(name);
contact->name_collate_key = g_utf8_collate_key(contact->name, -1);
}
}
void
p_contact_set_groups(const PContact contact, GSList *groups)
{
if (contact->groups != NULL) {
if (contact->groups) {
g_slist_free_full(contact->groups, g_free);
contact->groups = NULL;
}
@ -116,7 +123,7 @@ gboolean
p_contact_in_group(const PContact contact, const char * const group)
{
GSList *groups = contact->groups;
while (groups != NULL) {
while (groups) {
if (strcmp(groups->data, group) == 0) {
return TRUE;
}
@ -144,17 +151,19 @@ p_contact_remove_resource(PContact contact, const char * const resource)
void
p_contact_free(PContact contact)
{
if (contact != NULL) {
if (contact) {
free(contact->barejid);
free(contact->barejid_collate_key);
free(contact->name);
free(contact->name_collate_key);
free(contact->subscription);
free(contact->offline_message);
if (contact->groups != NULL) {
if (contact->groups) {
g_slist_free_full(contact->groups, g_free);
}
if (contact->last_activity != NULL) {
if (contact->last_activity) {
g_date_time_unref(contact->last_activity);
}
@ -170,16 +179,28 @@ p_contact_barejid(const PContact contact)
return contact->barejid;
}
const char *
p_contact_barejid_collate_key(const PContact contact)
{
return contact->barejid_collate_key;
}
const char *
p_contact_name(const PContact contact)
{
return contact->name;
}
const char *
p_contact_name_collate_key(const PContact contact)
{
return contact->name_collate_key;
}
const char *
p_contact_name_or_jid(const PContact contact)
{
if (contact->name != NULL) {
if (contact->name) {
return contact->name;
} else {
return contact->barejid;
@ -247,7 +268,7 @@ _get_most_available_resource(PContact contact)
Resource *current = curr->data;
Resource *highest = current;
curr = g_list_next(curr);
while (curr != NULL) {
while (curr) {
current = curr->data;
// priority is same as current highest, choose presence
@ -381,14 +402,14 @@ void
p_contact_set_presence(const PContact contact, Resource *resource)
{
g_hash_table_replace(contact->available_resources, strdup(resource->name), resource);
autocomplete_add(contact->resource_ac, strdup(resource->name));
autocomplete_add(contact->resource_ac, resource->name);
}
void
p_contact_set_subscription(const PContact contact, const char * const subscription)
{
FREE_SET_NULL(contact->subscription);
if (subscription != NULL) {
if (subscription) {
contact->subscription = strdup(subscription);
}
}
@ -402,12 +423,12 @@ p_contact_set_pending_out(const PContact contact, gboolean pending_out)
void
p_contact_set_last_activity(const PContact contact, GDateTime *last_activity)
{
if (contact->last_activity != NULL) {
if (contact->last_activity) {
g_date_time_unref(contact->last_activity);
contact->last_activity = NULL;
}
if (last_activity != NULL) {
if (last_activity) {
contact->last_activity = g_date_time_ref(last_activity);
}
}

View File

@ -1,7 +1,7 @@
/*
* contact.h
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*
@ -47,7 +47,9 @@ void p_contact_add_resource(PContact contact, Resource *resource);
gboolean p_contact_remove_resource(PContact contact, const char * const resource);
void p_contact_free(PContact contact);
const char* p_contact_barejid(PContact contact);
const char* p_contact_barejid_collate_key(PContact contact);
const char* p_contact_name(PContact contact);
const char* p_contact_name_collate_key(PContact contact);
const char* p_contact_name_or_jid(const PContact contact);
const char* p_contact_presence(PContact contact);
const char* p_contact_status(PContact contact);

95
src/event/client_events.c Normal file
View File

@ -0,0 +1,95 @@
/*
* client_events.c
*
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*
* Profanity 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.
*
* Profanity 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 Profanity. If not, see <http://www.gnu.org/licenses/>.
*
* In addition, as a special exception, the copyright holders give permission to
* link the code of portions of this program with the OpenSSL library under
* certain conditions as described in each individual source file, and
* distribute linked combinations including the two.
*
* You must obey the GNU General Public License in all respects for all of the
* code used other than OpenSSL. If you modify file(s) with this exception, you
* may extend this exception to your version of the file(s), but you are not
* obligated to do so. If you do not wish to do so, delete this exception
* statement from your version. If you delete this exception statement from all
* source files in the program, then also delete it here.
*
*/
#include <glib.h>
#include "config.h"
#include "log.h"
#include "ui/ui.h"
#include "ui/windows.h"
#include "xmpp/xmpp.h"
#ifdef HAVE_LIBOTR
#include "otr/otr.h"
#endif
jabber_conn_status_t
cl_ev_connect_jid(const char * const jid, const char * const passwd, const char * const altdomain, const int port)
{
cons_show("Connecting as %s", jid);
return jabber_connect_with_details(jid, passwd, altdomain, port);
}
jabber_conn_status_t
cl_ev_connect_account(ProfAccount *account)
{
char *jid = account_create_full_jid(account);
cons_show("Connecting with account %s as %s", account->name, jid);
free(jid);
return jabber_connect_with_account(account);
}
void
cl_ev_presence_send(const resource_presence_t presence_type, const char * const msg, const int idle)
{
presence_send(presence_type, msg, idle);
}
void
cl_ev_send_msg(ProfChatWin *chatwin, const char * const msg)
{
chat_state_active(chatwin->state);
#ifdef HAVE_LIBOTR
otr_on_message_send(chatwin, msg);
#else
char *id = message_send_chat(chatwin->barejid, msg);
chat_log_msg_out(chatwin->barejid, msg);
ui_outgoing_chat_msg(chatwin, msg, id);
free(id);
#endif
}
void
cl_ev_send_muc_msg(ProfMucWin *mucwin, const char * const msg)
{
message_send_groupchat(mucwin->roomjid, msg);
}
void
cl_ev_send_priv_msg(ProfPrivateWin *privwin, const char * const msg)
{
message_send_private(privwin->fulljid, msg);
ui_outgoing_private_msg(privwin, msg);
}

47
src/event/client_events.h Normal file
View File

@ -0,0 +1,47 @@
/*
* client_events.h
*
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*
* Profanity 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.
*
* Profanity 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 Profanity. If not, see <http://www.gnu.org/licenses/>.
*
* In addition, as a special exception, the copyright holders give permission to
* link the code of portions of this program with the OpenSSL library under
* certain conditions as described in each individual source file, and
* distribute linked combinations including the two.
*
* You must obey the GNU General Public License in all respects for all of the
* code used other than OpenSSL. If you modify file(s) with this exception, you
* may extend this exception to your version of the file(s), but you are not
* obligated to do so. If you do not wish to do so, delete this exception
* statement from your version. If you delete this exception statement from all
* source files in the program, then also delete it here.
*
*/
#ifndef CLIENT_EVENTS_H
#define CLIENT_EVENTS_H
jabber_conn_status_t cl_ev_connect_jid(const char * const jid, const char * const passwd, const char * const altdomain, const int port);
jabber_conn_status_t cl_ev_connect_account(ProfAccount *account);
void cl_ev_presence_send(const resource_presence_t presence_type, const char * const msg, const int idle);
void cl_ev_send_msg(ProfChatWin *chatwin, const char * const msg);
void cl_ev_send_muc_msg(ProfMucWin *mucwin, const char * const msg);
void cl_ev_send_priv_msg(ProfPrivateWin *privwin, const char * const msg);
#endif

522
src/event/server_events.c Normal file
View File

@ -0,0 +1,522 @@
/*
* server_events.c
*
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*
* Profanity 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.
*
* Profanity 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 Profanity. If not, see <http://www.gnu.org/licenses/>.
*
* In addition, as a special exception, the copyright holders give permission to
* link the code of portions of this program with the OpenSSL library under
* certain conditions as described in each individual source file, and
* distribute linked combinations including the two.
*
* You must obey the GNU General Public License in all respects for all of the
* code used other than OpenSSL. If you modify file(s) with this exception, you
* may extend this exception to your version of the file(s), but you are not
* obligated to do so. If you do not wish to do so, delete this exception
* statement from your version. If you delete this exception statement from all
* source files in the program, then also delete it here.
*
*/
#include <string.h>
#include <stdlib.h>
#include "config.h"
#include "chat_session.h"
#include "log.h"
#include "muc.h"
#include "config/preferences.h"
#include "config/account.h"
#include "roster_list.h"
#ifdef HAVE_LIBOTR
#include "otr/otr.h"
#endif
#include "ui/ui.h"
void
sv_ev_login_account_success(char *account_name)
{
ProfAccount *account = accounts_get_account(account_name);
#ifdef HAVE_LIBOTR
otr_on_connect(account);
#endif
ui_handle_login_account_success(account);
// attempt to rejoin rooms with passwords
GList *curr = muc_rooms();
while (curr) {
char *password = muc_password(curr->data);
if (password) {
char *nick = muc_nick(curr->data);
presence_join_room(curr->data, nick, password);
}
curr = g_list_next(curr);
}
g_list_free(curr);
log_info("%s logged in successfully", account->jid);
account_free(account);
}
void
sv_ev_roster_received(void)
{
if (prefs_get_boolean(PREF_ROSTER)) {
ui_show_roster();
}
}
void
sv_ev_lost_connection(void)
{
cons_show_error("Lost connection.");
roster_clear();
muc_invites_clear();
chat_sessions_clear();
ui_disconnected();
}
void
sv_ev_failed_login(void)
{
cons_show_error("Login failed.");
log_info("Login failed");
}
void
sv_ev_room_invite(jabber_invite_t invite_type,
const char * const invitor, const char * const room,
const char * const reason, const char * const password)
{
if (!muc_active(room) && !muc_invites_contain(room)) {
cons_show_room_invite(invitor, room, reason);
muc_invites_add(room, password);
}
}
void
sv_ev_room_broadcast(const char *const room_jid,
const char * const message)
{
if (muc_roster_complete(room_jid)) {
ui_room_broadcast(room_jid, message);
} else {
muc_pending_broadcasts_add(room_jid, message);
}
}
void
sv_ev_room_subject(const char * const room, const char * const nick, const char * const subject)
{
muc_set_subject(room, subject);
if (muc_roster_complete(room)) {
ui_room_subject(room, nick, subject);
}
}
void
sv_ev_room_history(const char * const room_jid, const char * const nick,
GTimeVal tv_stamp, const char * const message)
{
ui_room_history(room_jid, nick, tv_stamp, message);
}
void
sv_ev_room_message(const char * const room_jid, const char * const nick,
const char * const message)
{
ui_room_message(room_jid, nick, message);
if (prefs_get_boolean(PREF_GRLOG)) {
Jid *jid = jid_create(jabber_get_fulljid());
groupchat_log_chat(jid->barejid, room_jid, nick, message);
jid_destroy(jid);
}
}
void
sv_ev_incoming_private_message(const char * const fulljid, char *message)
{
ui_incoming_private_msg(fulljid, message, NULL);
}
void
sv_ev_carbon(char *barejid, char *message)
{
ui_outgoing_chat_msg_carbon(barejid, message);
}
void
sv_ev_incoming_message(char *barejid, char *resource, char *message)
{
#ifdef HAVE_LIBOTR
otr_on_message_recv(barejid, resource, message);
#else
ui_incoming_msg(barejid, resource, message, NULL);
chat_log_msg_in(barejid, message);
#endif
}
void
sv_ev_delayed_private_message(const char * const fulljid, char *message, GTimeVal tv_stamp)
{
ui_incoming_private_msg(fulljid, message, &tv_stamp);
}
void
sv_ev_delayed_message(char *barejid, char *message, GTimeVal tv_stamp)
{
ui_incoming_msg(barejid, NULL, message, &tv_stamp);
chat_log_msg_in_delayed(barejid, message, &tv_stamp);
}
void
sv_ev_message_receipt(char *barejid, char *id)
{
ui_message_receipt(barejid, id);
}
void
sv_ev_typing(char *barejid, char *resource)
{
ui_contact_typing(barejid, resource);
if (ui_chat_win_exists(barejid)) {
chat_session_recipient_typing(barejid, resource);
}
}
void
sv_ev_paused(char *barejid, char *resource)
{
if (ui_chat_win_exists(barejid)) {
chat_session_recipient_paused(barejid, resource);
}
}
void
sv_ev_inactive(char *barejid, char *resource)
{
if (ui_chat_win_exists(barejid)) {
chat_session_recipient_inactive(barejid, resource);
}
}
void
sv_ev_gone(const char * const barejid, const char * const resource)
{
ui_recipient_gone(barejid, resource);
if (ui_chat_win_exists(barejid)) {
chat_session_recipient_gone(barejid, resource);
}
}
void
sv_ev_activity(const char * const barejid, const char * const resource, gboolean send_states)
{
if (ui_chat_win_exists(barejid)) {
chat_session_recipient_active(barejid, resource, send_states);
}
}
void
sv_ev_subscription(const char *barejid, jabber_subscr_t type)
{
switch (type) {
case PRESENCE_SUBSCRIBE:
/* TODO: auto-subscribe if needed */
cons_show("Received authorization request from %s", barejid);
log_info("Received authorization request from %s", barejid);
ui_print_system_msg_from_recipient(barejid, "Authorization request, type '/sub allow' to accept or '/sub deny' to reject");
if (prefs_get_boolean(PREF_NOTIFY_SUB)) {
notify_subscription(barejid);
}
break;
case PRESENCE_SUBSCRIBED:
cons_show("Subscription received from %s", barejid);
log_info("Subscription received from %s", barejid);
ui_print_system_msg_from_recipient(barejid, "Subscribed");
break;
case PRESENCE_UNSUBSCRIBED:
cons_show("%s deleted subscription", barejid);
log_info("%s deleted subscription", barejid);
ui_print_system_msg_from_recipient(barejid, "Unsubscribed");
break;
default:
/* unknown type */
break;
}
}
void
sv_ev_contact_offline(char *barejid, char *resource, char *status)
{
gboolean updated = roster_contact_offline(barejid, resource, status);
if (resource && updated) {
ui_contact_offline(barejid, resource, status);
}
rosterwin_roster();
chat_session_remove(barejid);
}
void
sv_ev_contact_online(char *barejid, Resource *resource, GDateTime *last_activity)
{
gboolean updated = roster_update_presence(barejid, resource, last_activity);
if (updated) {
ui_contact_online(barejid, resource, last_activity);
}
rosterwin_roster();
chat_session_remove(barejid);
}
void
sv_ev_leave_room(const char * const room)
{
muc_leave(room);
ui_leave_room(room);
}
void
sv_ev_room_destroy(const char * const room)
{
muc_leave(room);
ui_room_destroy(room);
}
void
sv_ev_room_destroyed(const char * const room, const char * const new_jid, const char * const password,
const char * const reason)
{
muc_leave(room);
ui_room_destroyed(room, reason, new_jid, password);
}
void
sv_ev_room_kicked(const char * const room, const char * const actor, const char * const reason)
{
muc_leave(room);
ui_room_kicked(room, actor, reason);
}
void
sv_ev_room_banned(const char * const room, const char * const actor, const char * const reason)
{
muc_leave(room);
ui_room_banned(room, actor, reason);
}
void
sv_ev_room_occupant_offline(const char * const room, const char * const nick,
const char * const show, const char * const status)
{
muc_roster_remove(room, nick);
char *muc_status_pref = prefs_get_string(PREF_STATUSES_MUC);
if (g_strcmp0(muc_status_pref, "none") != 0) {
ui_room_member_offline(room, nick);
}
prefs_free_string(muc_status_pref);
occupantswin_occupants(room);
}
void
sv_ev_room_occupent_kicked(const char * const room, const char * const nick, const char * const actor,
const char * const reason)
{
muc_roster_remove(room, nick);
ui_room_member_kicked(room, nick, actor, reason);
occupantswin_occupants(room);
}
void
sv_ev_room_occupent_banned(const char * const room, const char * const nick, const char * const actor,
const char * const reason)
{
muc_roster_remove(room, nick);
ui_room_member_banned(room, nick, actor, reason);
occupantswin_occupants(room);
}
void
sv_ev_roster_update(const char * const barejid, const char * const name,
GSList *groups, const char * const subscription, gboolean pending_out)
{
roster_update(barejid, name, groups, subscription, pending_out);
rosterwin_roster();
}
void
sv_ev_xmpp_stanza(const char * const msg)
{
ui_handle_stanza(msg);
}
void
sv_ev_muc_self_online(const char * const room, const char * const nick, gboolean config_required,
const char * const role, const char * const affiliation, const char * const actor, const char * const reason,
const char * const jid, const char * const show, const char * const status)
{
muc_roster_add(room, nick, jid, role, affiliation, show, status);
char *old_role = muc_role_str(room);
char *old_affiliation = muc_affiliation_str(room);
muc_set_role(room, role);
muc_set_affiliation(room, affiliation);
// handle self nick change
if (muc_nick_change_pending(room)) {
muc_nick_change_complete(room, nick);
ui_room_nick_change(room, nick);
// handle roster complete
} else if (!muc_roster_complete(room)) {
if (muc_autojoin(room)) {
ui_room_join(room, FALSE);
} else {
ui_room_join(room, TRUE);
}
iq_room_info_request(room, FALSE);
muc_invites_remove(room);
muc_roster_set_complete(room);
// show roster if occupants list disabled by default
if (!prefs_get_boolean(PREF_OCCUPANTS)) {
GList *occupants = muc_roster(room);
ui_room_roster(room, occupants, NULL);
g_list_free(occupants);
}
char *subject = muc_subject(room);
if (subject) {
ui_room_subject(room, NULL, subject);
}
GList *pending_broadcasts = muc_pending_broadcasts(room);
if (pending_broadcasts) {
GList *curr = pending_broadcasts;
while (curr) {
ui_room_broadcast(room, curr->data);
curr = g_list_next(curr);
}
}
// room configuration required
if (config_required) {
muc_set_requires_config(room, TRUE);
ui_room_requires_config(room);
}
// check for change in role/affiliation
} else {
if (prefs_get_boolean(PREF_MUC_PRIVILEGES)) {
// both changed
if ((g_strcmp0(role, old_role) != 0) && (g_strcmp0(affiliation, old_affiliation) != 0)) {
ui_room_role_and_affiliation_change(room, role, affiliation, actor, reason);
// role changed
} else if (g_strcmp0(role, old_role) != 0) {
ui_room_role_change(room, role, actor, reason);
// affiliation changed
} else if (g_strcmp0(affiliation, old_affiliation) != 0) {
ui_room_affiliation_change(room, affiliation, actor, reason);
}
}
}
occupantswin_occupants(room);
}
void
sv_ev_muc_occupant_online(const char * const room, const char * const nick, const char * const jid,
const char * const role, const char * const affiliation, const char * const actor, const char * const reason,
const char * const show, const char * const status)
{
Occupant *occupant = muc_roster_item(room, nick);
const char *old_role = NULL;
const char *old_affiliation = NULL;
if (occupant) {
old_role = muc_occupant_role_str(occupant);
old_affiliation = muc_occupant_affiliation_str(occupant);
}
gboolean updated = muc_roster_add(room, nick, jid, role, affiliation, show, status);
// not yet finished joining room
if (!muc_roster_complete(room)) {
return;
}
// handle nickname change
char *old_nick = muc_roster_nick_change_complete(room, nick);
if (old_nick) {
ui_room_member_nick_change(room, old_nick, nick);
free(old_nick);
occupantswin_occupants(room);
return;
}
// joined room
if (!occupant) {
char *muc_status_pref = prefs_get_string(PREF_STATUSES_MUC);
if (g_strcmp0(muc_status_pref, "none") != 0) {
ui_room_member_online(room, nick, role, affiliation, show, status);
}
prefs_free_string(muc_status_pref);
occupantswin_occupants(room);
return;
}
// presence updated
if (updated) {
char *muc_status_pref = prefs_get_string(PREF_STATUSES_MUC);
if (g_strcmp0(muc_status_pref, "all") == 0) {
ui_room_member_presence(room, nick, show, status);
}
prefs_free_string(muc_status_pref);
occupantswin_occupants(room);
// presence unchanged, check for role/affiliation change
} else {
if (prefs_get_boolean(PREF_MUC_PRIVILEGES)) {
// both changed
if ((g_strcmp0(role, old_role) != 0) && (g_strcmp0(affiliation, old_affiliation) != 0)) {
ui_room_occupant_role_and_affiliation_change(room, nick, role, affiliation, actor, reason);
// role changed
} else if (g_strcmp0(role, old_role) != 0) {
ui_room_occupant_role_change(room, nick, role, actor, reason);
// affiliation changed
} else if (g_strcmp0(affiliation, old_affiliation) != 0) {
ui_room_occupant_affiliation_change(room, nick, affiliation, actor, reason);
}
}
occupantswin_occupants(room);
}
}

91
src/event/server_events.h Normal file
View File

@ -0,0 +1,91 @@
/*
* server_events.h
*
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*
* Profanity 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.
*
* Profanity 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 Profanity. If not, see <http://www.gnu.org/licenses/>.
*
* In addition, as a special exception, the copyright holders give permission to
* link the code of portions of this program with the OpenSSL library under
* certain conditions as described in each individual source file, and
* distribute linked combinations including the two.
*
* You must obey the GNU General Public License in all respects for all of the
* code used other than OpenSSL. If you modify file(s) with this exception, you
* may extend this exception to your version of the file(s), but you are not
* obligated to do so. If you do not wish to do so, delete this exception
* statement from your version. If you delete this exception statement from all
* source files in the program, then also delete it here.
*
*/
#ifndef SERVER_EVENTS_H
#define SERVER_EVENTS_H
#include "xmpp/xmpp.h"
void sv_ev_login_account_success(char *account_name);
void sv_ev_lost_connection(void);
void sv_ev_failed_login(void);
void sv_ev_room_invite(jabber_invite_t invite_type,
const char * const invitor, const char * const room,
const char * const reason, const char * const password);
void sv_ev_room_broadcast(const char *const room_jid,
const char * const message);
void sv_ev_room_subject(const char * const room, const char * const nick, const char * const subject);
void sv_ev_room_history(const char * const room_jid, const char * const nick,
GTimeVal tv_stamp, const char * const message);
void sv_ev_room_message(const char * const room_jid, const char * const nick,
const char * const message);
void sv_ev_incoming_message(char *barejid, char *resource, char *message);
void sv_ev_incoming_private_message(const char * const fulljid, char *message);
void sv_ev_delayed_message(char *fulljid, char *message, GTimeVal tv_stamp);
void sv_ev_delayed_private_message(const char * const fulljid, char *message, GTimeVal tv_stamp);
void sv_ev_typing(char *barejid, char *resource);
void sv_ev_paused(char *barejid, char *resource);
void sv_ev_inactive(char *barejid, char *resource);
void sv_ev_activity(char *barejid, char *resource, gboolean send_states);
void sv_ev_gone(const char * const barejid, const char * const resource);
void sv_ev_subscription(const char *from, jabber_subscr_t type);
void sv_ev_message_receipt(char *barejid, char *id);
void sv_ev_contact_offline(char *contact, char *resource, char *status);
void sv_ev_contact_online(char *contact, Resource *resource,
GDateTime *last_activity);
void sv_ev_leave_room(const char * const room);
void sv_ev_room_destroy(const char * const room);
void sv_ev_room_occupant_offline(const char * const room, const char * const nick,
const char * const show, const char * const status);
void sv_ev_room_destroyed(const char * const room, const char * const new_jid, const char * const password,
const char * const reason);
void sv_ev_room_kicked(const char * const room, const char * const actor, const char * const reason);
void sv_ev_room_occupent_kicked(const char * const room, const char * const nick, const char * const actor,
const char * const reason);
void sv_ev_room_banned(const char * const room, const char * const actor, const char * const reason);
void sv_ev_room_occupent_banned(const char * const room, const char * const nick, const char * const actor,
const char * const reason);
void sv_ev_carbon(char *barejid, char *message);
void sv_ev_xmpp_stanza(const char * const msg);
void sv_ev_muc_self_online(const char * const room, const char * const nick, gboolean config_required,
const char * const role, const char * const affiliation, const char * const actor, const char * const reason,
const char * const jid, const char * const show, const char * const status);
void sv_ev_muc_occupant_online(const char * const room, const char * const nick, const char * const jid,
const char * const role, const char * const affiliation, const char * const actor, const char * const reason,
const char * const show_str, const char * const status_str);
void sv_ev_roster_update(const char * const barejid, const char * const name,
GSList *groups, const char * const subscription, gboolean pending_out);
void sv_ev_roster_received(void);
#endif

56
src/event/ui_events.c Normal file
View File

@ -0,0 +1,56 @@
/*
* ui_events.c
*
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*
* Profanity 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.
*
* Profanity 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 Profanity. If not, see <http://www.gnu.org/licenses/>.
*
* In addition, as a special exception, the copyright holders give permission to
* link the code of portions of this program with the OpenSSL library under
* certain conditions as described in each individual source file, and
* distribute linked combinations including the two.
*
* You must obey the GNU General Public License in all respects for all of the
* code used other than OpenSSL. If you modify file(s) with this exception, you
* may extend this exception to your version of the file(s), but you are not
* obligated to do so. If you do not wish to do so, delete this exception
* statement from your version. If you delete this exception statement from all
* source files in the program, then also delete it here.
*
*/
#include "ui/ui.h"
#include "ui/windows.h"
void
ui_ev_focus_win(ProfWin *win)
{
if (!wins_is_current(win)) {
ui_switch_win(win);
}
}
ProfChatWin*
ui_ev_new_chat_win(const char * const barejid)
{
return ui_new_chat_win(barejid);
}
ProfPrivateWin*
ui_ev_new_private_win(const char * const fulljid)
{
return ui_new_private_win(fulljid);
}

View File

@ -1,7 +1,7 @@
/*
* history.h
* ui_events.h
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*
@ -32,14 +32,11 @@
*
*/
#ifndef HISTORY_H
#define HISTORY_H
#ifndef UI_EVENTS_H
#define UI_EVENTS_H
typedef struct history_t *History;
void ui_ev_focus_win(ProfWin *win);
ProfChatWin* ui_ev_new_chat_win(const char * const barejid);
ProfPrivateWin* ui_ev_new_private_win(const char * const fulljid);
History history_new(unsigned int size);
char * history_previous(History history, char *item);
char * history_next(History history, char *item);
void history_append(History history, char *item);
#endif
#endif

View File

@ -1,7 +1,7 @@
/*
* jid.c
*
* Copyright (C) 2012 -2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*
@ -80,19 +80,20 @@ jid_create(const gchar * const str)
gchar *domain_start = trimmed;
if (atp != NULL) {
if (atp) {
result->localpart = g_utf8_substring(trimmed, 0, g_utf8_pointer_to_offset(trimmed, atp));
domain_start = atp + 1;
}
if (slashp != NULL) {
if (slashp) {
result->resourcepart = g_strdup(slashp + 1);
result->domainpart = g_utf8_substring(domain_start, 0, g_utf8_pointer_to_offset(domain_start, slashp));
result->barejid = g_utf8_substring(trimmed, 0, g_utf8_pointer_to_offset(trimmed, slashp));
char *barejidraw = g_utf8_substring(trimmed, 0, g_utf8_pointer_to_offset(trimmed, slashp));
result->barejid = g_utf8_strdown(barejidraw, -1);
result->fulljid = g_strdup(trimmed);
} else {
result->domainpart = g_strdup(domain_start);
result->barejid = g_strdup(trimmed);
result->barejid = g_utf8_strdown(trimmed, -1);
}
if (result->domainpart == NULL) {
@ -119,7 +120,7 @@ jid_create_from_bare_and_resource(const char * const room, const char * const ni
void
jid_destroy(Jid *jid)
{
if (jid != NULL) {
if (jid) {
g_free(jid->str);
g_free(jid->localpart);
g_free(jid->domainpart);
@ -144,7 +145,9 @@ jid_is_valid_room_form(Jid *jid)
char *
create_fulljid(const char * const barejid, const char * const resource)
{
GString *full_jid = g_string_new(barejid);
gchar *barejidlower = g_utf8_strdown(barejid, -1);
GString *full_jid = g_string_new(barejidlower);
g_free(barejidlower);
g_string_append(full_jid, "/");
g_string_append(full_jid, resource);
@ -166,8 +169,8 @@ get_nick_from_full_jid(const char * const full_room_jid)
char **tokens = g_strsplit(full_room_jid, "/", 0);
char *nick_part = NULL;
if (tokens != NULL) {
if (tokens[0] != NULL && tokens[1] != NULL) {
if (tokens) {
if (tokens[0] && tokens[1]) {
nick_part = strdup(tokens[1]);
}

View File

@ -1,7 +1,7 @@
/*
* jid.h
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*

104
src/log.c
View File

@ -1,7 +1,7 @@
/*
* log.c
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*
@ -46,6 +46,7 @@
#include "common.h"
#include "config/preferences.h"
#include "xmpp/xmpp.h"
#define PROF "prof"
@ -66,7 +67,7 @@ struct dated_chat_log {
};
static gboolean _log_roll_needed(struct dated_chat_log *dated_log);
static struct dated_chat_log * _create_log(char *other, const char * const login);
static struct dated_chat_log * _create_log(const char * const other, const char * const login);
static struct dated_chat_log * _create_groupchat_log(char *room, const char * const login);
static void _free_chat_log(struct dated_chat_log *dated_log);
static gboolean _key_equals(void *key1, void *key2);
@ -78,6 +79,8 @@ static gchar * _get_chatlog_dir(void);
static gchar * _get_main_log_file(void);
static void _rotate_log_file(void);
static char* _log_string_from_level(log_level_t level);
static void _chat_log_chat(const char * const login, const char * const other,
const gchar * const msg, chat_log_direction_t direction, GTimeVal *tv_stamp);
void
log_debug(const char * const msg, ...)
@ -163,7 +166,7 @@ log_close(void)
{
g_string_free(mainlogfile, TRUE);
g_time_zone_unref(tz);
if (logp != NULL) {
if (logp) {
fclose(logp);
}
}
@ -171,7 +174,7 @@ log_close(void)
void
log_msg(log_level_t level, const char * const area, const char * const msg)
{
if (level >= level_filter && logp != NULL) {
if (level >= level_filter && logp) {
dt = g_date_time_new_now(tz);
char *level_str = _log_string_from_level(level);
@ -236,7 +239,7 @@ chat_log_init(void)
{
session_started = g_date_time_new_now_local();
log_info("Initialising chat logs");
logs = g_hash_table_new_full(g_str_hash, (GEqualFunc) _key_equals, g_free,
logs = g_hash_table_new_full(g_str_hash, (GEqualFunc) _key_equals, free,
(GDestroyNotify)_free_chat_log);
}
@ -244,13 +247,80 @@ void
groupchat_log_init(void)
{
log_info("Initialising groupchat logs");
groupchat_logs = g_hash_table_new_full(g_str_hash, (GEqualFunc) _key_equals, g_free,
groupchat_logs = g_hash_table_new_full(g_str_hash, (GEqualFunc) _key_equals, free,
(GDestroyNotify)_free_chat_log);
}
void
chat_log_chat(const gchar * const login, gchar *other,
const gchar * const msg, chat_log_direction_t direction, GTimeVal *tv_stamp)
chat_log_msg_out(const char * const barejid, const char * const msg)
{
if (prefs_get_boolean(PREF_CHLOG)) {
const char *jid = jabber_get_fulljid();
Jid *jidp = jid_create(jid);
_chat_log_chat(jidp->barejid, barejid, msg, PROF_OUT_LOG, NULL);
jid_destroy(jidp);
}
}
void
chat_log_otr_msg_out(const char * const barejid, const char * const msg)
{
if (prefs_get_boolean(PREF_CHLOG)) {
const char *jid = jabber_get_fulljid();
Jid *jidp = jid_create(jid);
char *pref_otr_log = prefs_get_string(PREF_OTR_LOG);
if (strcmp(pref_otr_log, "on") == 0) {
_chat_log_chat(jidp->barejid, barejid, msg, PROF_OUT_LOG, NULL);
} else if (strcmp(pref_otr_log, "redact") == 0) {
_chat_log_chat(jidp->barejid, barejid, "[redacted]", PROF_OUT_LOG, NULL);
}
prefs_free_string(pref_otr_log);
jid_destroy(jidp);
}
}
void
chat_log_otr_msg_in(const char * const barejid, const char * const msg, gboolean was_decrypted)
{
if (prefs_get_boolean(PREF_CHLOG)) {
const char *jid = jabber_get_fulljid();
Jid *jidp = jid_create(jid);
char *pref_otr_log = prefs_get_string(PREF_OTR_LOG);
if (!was_decrypted || (strcmp(pref_otr_log, "on") == 0)) {
_chat_log_chat(jidp->barejid, barejid, msg, PROF_IN_LOG, NULL);
} else if (strcmp(pref_otr_log, "redact") == 0) {
_chat_log_chat(jidp->barejid, barejid, "[redacted]", PROF_IN_LOG, NULL);
}
prefs_free_string(pref_otr_log);
jid_destroy(jidp);
}
}
void
chat_log_msg_in(const char * const barejid, const char * const msg)
{
if (prefs_get_boolean(PREF_CHLOG)) {
const char *jid = jabber_get_fulljid();
Jid *jidp = jid_create(jid);
_chat_log_chat(jidp->barejid, barejid, msg, PROF_IN_LOG, NULL);
jid_destroy(jidp);
}
}
void
chat_log_msg_in_delayed(const char * const barejid, const char * msg, GTimeVal *tv_stamp)
{
if (prefs_get_boolean(PREF_CHLOG)) {
const char *jid = jabber_get_fulljid();
Jid *jidp = jid_create(jid);
_chat_log_chat(jidp->barejid, barejid, msg, PROF_IN_LOG, tv_stamp);
jid_destroy(jidp);
}
}
static void
_chat_log_chat(const char * const login, const char * const other,
const char * const msg, chat_log_direction_t direction, GTimeVal *tv_stamp)
{
struct dated_chat_log *dated_log = g_hash_table_lookup(logs, other);
@ -277,7 +347,7 @@ chat_log_chat(const gchar * const login, gchar *other,
FILE *logp = fopen(dated_log->filename, "a");
g_chmod(dated_log->filename, S_IRUSR | S_IWUSR);
if (logp != NULL) {
if (logp) {
if (direction == PROF_IN_LOG) {
if (strncmp(msg, "/me ", 4) == 0) {
fprintf(logp, "%s - *%s %s\n", date_fmt, other, msg + 4);
@ -326,7 +396,7 @@ groupchat_log_chat(const gchar * const login, const gchar * const room,
FILE *logp = fopen(dated_log->filename, "a");
g_chmod(dated_log->filename, S_IRUSR | S_IWUSR);
if (logp != NULL) {
if (logp) {
if (strncmp(msg, "/me ", 4) == 0) {
fprintf(logp, "%s - *%s %s\n", date_fmt, nick, msg + 4);
} else {
@ -363,7 +433,7 @@ chat_log_get_previous(const gchar * const login, const gchar * const recipient)
char *filename = _get_log_filename(recipient, login, log_date, FALSE);
FILE *logp = fopen(filename, "r");
if (logp != NULL) {
if (logp) {
GString *header = g_string_new("");
g_string_append_printf(header, "%d/%d/%d:",
g_date_time_get_day_of_month(log_date),
@ -396,13 +466,13 @@ chat_log_get_previous(const gchar * const login, const gchar * const recipient)
void
chat_log_close(void)
{
g_hash_table_remove_all(logs);
g_hash_table_remove_all(groupchat_logs);
g_hash_table_destroy(logs);
g_hash_table_destroy(groupchat_logs);
g_date_time_unref(session_started);
}
static struct dated_chat_log *
_create_log(char *other, const char * const login)
_create_log(const char * const other, const char * const login)
{
GDateTime *now = g_date_time_new_now_local();
char *filename = _get_log_filename(other, login, now, TRUE);
@ -448,12 +518,12 @@ _log_roll_needed(struct dated_chat_log *dated_log)
static void
_free_chat_log(struct dated_chat_log *dated_log)
{
if (dated_log != NULL) {
if (dated_log->filename != NULL) {
if (dated_log) {
if (dated_log->filename) {
g_free(dated_log->filename);
dated_log->filename = NULL;
}
if (dated_log->date != NULL) {
if (dated_log->date) {
g_date_time_unref(dated_log->date);
dated_log->date = NULL;
}

View File

@ -1,7 +1,7 @@
/*
* log.h
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*
@ -64,8 +64,14 @@ void log_msg(log_level_t level, const char * const area,
log_level_t log_level_from_string(char *log_level);
void chat_log_init(void);
void chat_log_chat(const gchar * const login, gchar *other,
const gchar * const msg, chat_log_direction_t direction, GTimeVal *tv_stamp);
void chat_log_msg_out(const char * const barejid, const char * const msg);
void chat_log_otr_msg_out(const char * const barejid, const char * const msg);
void chat_log_msg_in(const char * const barejid, const char * const msg);
void chat_log_msg_in_delayed(const char * const barejid, const char * msg, GTimeVal *tv_stamp);
void chat_log_otr_msg_in(const char * const barejid, const char * const msg, gboolean was_decrypted);
void chat_log_close(void);
GSList * chat_log_get_previous(const gchar * const login,
const gchar * const recipient);

View File

@ -1,7 +1,7 @@
/*
* main.c
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*
@ -40,13 +40,7 @@
#endif
#include "profanity.h"
#ifdef HAVE_LIBOTR
#include "otr/otr.h"
#endif
#include "xmpp/xmpp.h"
#include "ui/ui.h"
#include "command/command.h"
static gboolean disable_tls = FALSE;
static gboolean version = FALSE;
@ -56,6 +50,11 @@ static char *account_name = NULL;
int
main(int argc, char **argv)
{
if (argc == 2 && g_strcmp0(argv[1], "docgen") == 0 && g_strcmp0(PACKAGE_STATUS, "development") == 0) {
command_docgen();
return 0;
}
static GOptionEntry entries[] =
{
{ "version", 'v', 0, G_OPTION_ARG_NONE, &version, "Show version information", NULL },
@ -90,7 +89,7 @@ main(int argc, char **argv)
g_print("Profanity, version %s\n", PACKAGE_VERSION);
}
g_print("Copyright (C) 2012 - 2014 James Booth <%s>.\n", PACKAGE_BUGREPORT);
g_print("Copyright (C) 2012 - 2015 James Booth <%s>.\n", PACKAGE_BUGREPORT);
g_print("License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>\n");
g_print("\n");
g_print("This is free software; you are free to change and redistribute it.\n");

View File

@ -1,7 +1,7 @@
/*
* muc.c
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*
@ -62,9 +62,11 @@ typedef struct _muc_room_t {
Autocomplete jid_ac;
GHashTable *nick_changes;
gboolean roster_received;
muc_member_type_t member_type;
} ChatRoom;
GHashTable *rooms = NULL;
GHashTable *invite_passwords = NULL;
Autocomplete invite_ac;
static void _free_room(ChatRoom *room);
@ -82,6 +84,7 @@ muc_init(void)
{
invite_ac = autocomplete_new();
rooms = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify)_free_room);
invite_passwords = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
}
void
@ -89,19 +92,25 @@ muc_close(void)
{
autocomplete_free(invite_ac);
g_hash_table_destroy(rooms);
g_hash_table_destroy(invite_passwords);
rooms = NULL;
invite_passwords = NULL;
}
void
muc_invites_add(const char * const room)
muc_invites_add(const char * const room, const char * const password)
{
autocomplete_add(invite_ac, room);
if (password) {
g_hash_table_replace(invite_passwords, strdup(room), strdup(password));
}
}
void
muc_invites_remove(const char * const room)
{
autocomplete_remove(invite_ac, room);
g_hash_table_remove(invite_passwords, room);
}
gint
@ -116,6 +125,12 @@ muc_invites(void)
return autocomplete_create_list(invite_ac);
}
char *
muc_invite_password(const char * const room)
{
return g_hash_table_lookup(invite_passwords, room);
}
gboolean
muc_invites_contain(const char * const room)
{
@ -150,6 +165,7 @@ void
muc_invites_clear(void)
{
autocomplete_clear(invite_ac);
g_hash_table_remove_all(invite_passwords);
}
void
@ -177,6 +193,7 @@ muc_join(const char * const room, const char * const nick,
new_room->roster_received = FALSE;
new_room->pending_nick_change = FALSE;
new_room->autojoin = autojoin;
new_room->member_type = MUC_MEMBER_TYPE_UNKNOWN;
g_hash_table_insert(rooms, strdup(room), new_room);
}
@ -208,6 +225,19 @@ muc_set_requires_config(const char * const room, gboolean val)
}
}
void
muc_set_features(const char * const room, GSList *features)
{
ChatRoom *chat_room = g_hash_table_lookup(rooms, room);
if (chat_room && features) {
if (g_slist_find_custom(features, "muc_membersonly", (GCompareFunc)g_strcmp0)) {
chat_room->member_type = MUC_MEMBER_TYPE_MEMBERS_ONLY;
} else {
chat_room->member_type = MUC_MEMBER_TYPE_PUBLIC;
}
}
}
/*
* Returns TRUE if the user is currently in the room
*/
@ -315,7 +345,7 @@ muc_nick_change_pending(const char * const room)
}
/*
* Change the current nuck name for the room, call once
* Change the current nick name for the room, call once
* the service has responded
*/
void
@ -763,6 +793,18 @@ muc_set_affiliation(const char * const room, const char * const affiliation)
}
}
muc_member_type_t
muc_member_type(const char * const room)
{
ChatRoom *chat_room = g_hash_table_lookup(rooms, room);
if (chat_room) {
return chat_room->member_type;
} else {
return MUC_MEMBER_TYPE_UNKNOWN;
}
}
static void
_free_room(ChatRoom *room)
{
@ -790,16 +832,10 @@ _free_room(ChatRoom *room)
static
gint _compare_occupants(Occupant *a, Occupant *b)
{
const char * utf8_str_a = a->nick;
const char * utf8_str_b = b->nick;
const char * utf8_str_a = a->nick_collate_key;
const char * utf8_str_b = b->nick_collate_key;
gchar *key_a = g_utf8_collate_key(utf8_str_a, -1);
gchar *key_b = g_utf8_collate_key(utf8_str_b, -1);
gint result = g_strcmp0(key_a, key_b);
g_free(key_a);
g_free(key_b);
gint result = g_strcmp0(utf8_str_a, utf8_str_b);
return result;
}
@ -905,8 +941,10 @@ _muc_occupant_new(const char *const nick, const char * const jid, muc_role_t rol
if (nick) {
occupant->nick = strdup(nick);
occupant->nick_collate_key = g_utf8_collate_key(occupant->nick, -1);
} else {
occupant->nick = NULL;
occupant->nick_collate_key = NULL;
}
if (jid) {
@ -934,6 +972,7 @@ _occupant_free(Occupant *occupant)
{
if (occupant) {
free(occupant->nick);
free(occupant->nick_collate_key);
free(occupant->jid);
free(occupant->status);
free(occupant);

View File

@ -1,7 +1,7 @@
/*
* muc.h
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*
@ -56,8 +56,15 @@ typedef enum {
MUC_AFFILIATION_OWNER
} muc_affiliation_t;
typedef enum {
MUC_MEMBER_TYPE_UNKNOWN,
MUC_MEMBER_TYPE_PUBLIC,
MUC_MEMBER_TYPE_MEMBERS_ONLY
} muc_member_type_t;
typedef struct _muc_occupant_t {
char *nick;
gchar *nick_collate_key;
char *jid;
muc_role_t role;
muc_affiliation_t affiliation;
@ -76,6 +83,8 @@ gboolean muc_autojoin(const char * const room);
GList* muc_rooms(void);
void muc_set_features(const char * const room, GSList *features);
char* muc_nick(const char * const room);
char* muc_password(const char * const room);
@ -108,7 +117,7 @@ GSList * muc_occupants_by_affiliation(const char * const room, muc_affiliation_t
void muc_occupant_nick_change_start(const char * const room, const char * const new_nick, const char * const old_nick);
char* muc_roster_nick_change_complete(const char * const room, const char * const nick);
void muc_invites_add(const char * const room);
void muc_invites_add(const char * const room, const char * const password);
void muc_invites_remove(const char * const room);
gint muc_invites_count(void);
GSList* muc_invites(void);
@ -116,6 +125,7 @@ gboolean muc_invites_contain(const char * const room);
void muc_invites_reset_ac(void);
char* muc_invites_find(const char * const search_str);
void muc_invites_clear(void);
char* muc_invite_password(const char * const room);
void muc_set_subject(const char * const room, const char * const subject);
char* muc_subject(const char * const room);
@ -134,4 +144,6 @@ void muc_set_affiliation(const char * const room, const char * const affiliation
char *muc_role_str(const char * const room);
char *muc_affiliation_str(const char * const room);
muc_member_type_t muc_member_type(const char * const room);
#endif

View File

@ -1,7 +1,7 @@
/*
* otr.c
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*
@ -110,7 +110,7 @@ static void
cb_inject_message(void *opdata, const char *accountname,
const char *protocol, const char *recipient, const char *message)
{
message_send_chat(recipient, message);
message_send_chat_encrypted(recipient, message);
}
static void
@ -179,7 +179,7 @@ otr_init(void)
void
otr_shutdown(void)
{
if (jid != NULL) {
if (jid) {
free(jid);
}
}
@ -193,7 +193,7 @@ otr_poll(void)
void
otr_on_connect(ProfAccount *account)
{
if (jid != NULL) {
if (jid) {
free(jid);
}
jid = strdup(account->jid);
@ -269,6 +269,89 @@ otr_on_connect(ProfAccount *account)
return;
}
void
otr_on_message_recv(const char * const barejid, const char * const resource, const char * const message)
{
gboolean was_decrypted = FALSE;
char *decrypted;
prof_otrpolicy_t policy = otr_get_policy(barejid);
char *whitespace_base = strstr(message, OTRL_MESSAGE_TAG_BASE);
//check for OTR whitespace (opportunistic or always)
if (policy == PROF_OTRPOLICY_OPPORTUNISTIC || policy == PROF_OTRPOLICY_ALWAYS) {
if (whitespace_base) {
if (strstr(message, OTRL_MESSAGE_TAG_V2) || strstr(message, OTRL_MESSAGE_TAG_V1)) {
// Remove whitespace pattern for proper display in UI
// Handle both BASE+TAGV1/2(16+8) and BASE+TAGV1+TAGV2(16+8+8)
int tag_length = 24;
if (strstr(message, OTRL_MESSAGE_TAG_V2) && strstr(message, OTRL_MESSAGE_TAG_V1)) {
tag_length = 32;
}
memmove(whitespace_base, whitespace_base+tag_length, tag_length);
char *otr_query_message = otr_start_query();
cons_show("OTR Whitespace pattern detected. Attempting to start OTR session...");
message_send_chat_encrypted(barejid, otr_query_message);
}
}
}
decrypted = otr_decrypt_message(barejid, message, &was_decrypted);
// internal OTR message
if (decrypted == NULL) {
return;
}
if (policy == PROF_OTRPOLICY_ALWAYS && !was_decrypted && !whitespace_base) {
char *otr_query_message = otr_start_query();
cons_show("Attempting to start OTR session...");
message_send_chat_encrypted(barejid, otr_query_message);
}
ui_incoming_msg(barejid, resource, decrypted, NULL);
chat_log_otr_msg_in(barejid, decrypted, was_decrypted);
otr_free_message(decrypted);
}
void
otr_on_message_send(ProfChatWin *chatwin, const char * const message)
{
char *id = NULL;
prof_otrpolicy_t policy = otr_get_policy(chatwin->barejid);
if (otr_is_secure(chatwin->barejid)) {
char *encrypted = otr_encrypt_message(chatwin->barejid, message);
if (encrypted) {
id = message_send_chat_encrypted(chatwin->barejid, encrypted);
chat_log_otr_msg_out(chatwin->barejid, message);
ui_outgoing_chat_msg(chatwin, message, id);
otr_free_message(encrypted);
} else {
ui_win_error_line((ProfWin*)chatwin, "Failed to encrypt and send message.");
return;
}
} else if (policy == PROF_OTRPOLICY_ALWAYS) {
ui_win_error_line((ProfWin*)chatwin, "Failed to send message. OTR policy set to: always");
return;
} else if (policy == PROF_OTRPOLICY_OPPORTUNISTIC) {
char *otr_tagged_msg = otr_tag_message(message);
id = message_send_chat_encrypted(chatwin->barejid, otr_tagged_msg);
ui_outgoing_chat_msg(chatwin, message, id);
chat_log_msg_out(chatwin->barejid, message);
free(otr_tagged_msg);
} else {
id = message_send_chat(chatwin->barejid, message);
ui_outgoing_chat_msg(chatwin, message, id);
chat_log_msg_out(chatwin->barejid, message);
}
free(id);
}
void
otr_keygen(ProfAccount *account)
{
@ -277,7 +360,7 @@ otr_keygen(ProfAccount *account)
return;
}
if (jid != NULL) {
if (jid) {
free(jid);
}
jid = strdup(account->jid);
@ -365,6 +448,18 @@ otr_key_loaded(void)
return data_loaded;
}
char *
otr_tag_message(const char * const msg)
{
GString *otr_message = g_string_new(msg);
g_string_append(otr_message, OTRL_MESSAGE_TAG_BASE);
g_string_append(otr_message, OTRL_MESSAGE_TAG_V2);
char *result = otr_message->str;
g_string_free(otr_message, FALSE);
return result;
}
gboolean
otr_is_secure(const char * const recipient)
{
@ -421,7 +516,7 @@ otr_trust(const char * const recipient)
}
if (context->active_fingerprint) {
if (context->active_fingerprint->trust != NULL) {
if (context->active_fingerprint->trust) {
free(context->active_fingerprint->trust);
}
context->active_fingerprint->trust = strdup("trusted");
@ -445,7 +540,7 @@ otr_untrust(const char * const recipient)
}
if (context->active_fingerprint) {
if (context->active_fingerprint->trust != NULL) {
if (context->active_fingerprint->trust) {
free(context->active_fingerprint->trust);
}
context->active_fingerprint->trust = NULL;
@ -534,7 +629,7 @@ otr_get_their_fingerprint(const char * const recipient)
{
ConnContext *context = otrlib_context_find(user_state, recipient, jid);
if (context != NULL) {
if (context) {
Fingerprint *fingerprint = context->active_fingerprint;
char readable[45];
otrl_privkey_hash_to_human(readable, fingerprint->fingerprint);
@ -563,7 +658,7 @@ otr_get_policy(const char * const recipient)
}
// check default account setting
if (account->otr_policy != NULL) {
if (account->otr_policy) {
prof_otrpolicy_t result;
if (g_strcmp0(account->otr_policy, "manual") == 0) {
result = PROF_OTRPOLICY_MANUAL;
@ -625,7 +720,7 @@ otr_decrypt_message(const char * const from, const char * const message, gboolea
OtrlTLV *tlv = otrl_tlv_find(tlvs, OTRL_TLV_DISCONNECTED);
if (tlv) {
if (context != NULL) {
if (context) {
otrl_context_force_plaintext(context);
ui_gone_insecure(from);
}
@ -637,7 +732,7 @@ otr_decrypt_message(const char * const from, const char * const message, gboolea
return NULL;
// message was decrypted, return to user
} else if (decrypted != NULL) {
} else if (decrypted) {
*was_decrypted = TRUE;
return decrypted;

View File

@ -1,7 +1,7 @@
/*
* otr.h
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*
@ -39,6 +39,7 @@
#include <libotr/message.h>
#include "config/accounts.h"
#include "ui/window.h"
typedef enum {
PROF_OTRPOLICY_MANUAL,
@ -56,8 +57,14 @@ char* otr_libotr_version(void);
char* otr_start_query(void);
void otr_poll(void);
void otr_on_connect(ProfAccount *account);
void otr_on_message_recv(const char * const barejid, const char * const resource, const char * const message);
void otr_on_message_send(ProfChatWin *chatwin, const char * const message);
void otr_keygen(ProfAccount *account);
char* otr_tag_message(const char * const msg);
gboolean otr_key_loaded(void);
gboolean otr_is_secure(const char * const recipient);

View File

@ -1,7 +1,7 @@
/*
* otrlib.h
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*

View File

@ -1,7 +1,7 @@
/*
* otrlibv3.c
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*
@ -87,7 +87,7 @@ otrlib_end_session(OtrlUserState user_state, const char * const recipient, char
ConnContext *context = otrl_context_find(user_state, recipient, jid, "xmpp",
0, NULL, NULL, NULL);
if (context != NULL) {
if (context) {
otrl_message_disconnect(user_state, ops, NULL, jid, "xmpp", recipient);
}
}
@ -171,7 +171,7 @@ otrlib_handle_tlvs(OtrlUserState user_state, OtrlMessageAppOps *ops, ConnContext
} else {
context->smstate->nextExpected = OTRL_SMP_EXPECT1;
if (context->smstate->received_question == 0) {
if ((context->active_fingerprint->trust != NULL) && (context->active_fingerprint->trust[0] != '\0')) {
if (context->active_fingerprint->trust && (context->active_fingerprint->trust[0] != '\0')) {
ui_smp_successful(context->username);
ui_trust(context->username);
} else {
@ -193,7 +193,7 @@ otrlib_handle_tlvs(OtrlUserState user_state, OtrlMessageAppOps *ops, ConnContext
otrl_message_abort_smp(user_state, ops, NULL, context);
} else {
context->smstate->nextExpected = OTRL_SMP_EXPECT1;
if ((context->active_fingerprint->trust != NULL) && (context->active_fingerprint->trust[0] != '\0')) {
if (context->active_fingerprint->trust && (context->active_fingerprint->trust[0] != '\0')) {
ui_smp_successful(context->username);
ui_trust(context->username);
} else {

View File

@ -1,7 +1,7 @@
/*
* otrlibv4.c
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*
@ -113,12 +113,57 @@ cb_handle_msg_event(void *opdata, OtrlMessageEvent msg_event,
ConnContext *context, const char *message,
gcry_error_t err)
{
if (err != 0) {
if (message != NULL) {
cons_show_error("%s", message);
} else {
cons_show_error("OTR error event with no message.");
}
GString *err_msg;
switch (msg_event)
{
case OTRL_MSGEVENT_ENCRYPTION_REQUIRED:
ui_handle_otr_error(context->username, "OTR: Policy requires encryption, but attempting to send an unencrypted message.");
break;
case OTRL_MSGEVENT_ENCRYPTION_ERROR:
ui_handle_otr_error(context->username, "OTR: Error occured while encrypting a message, message not sent.");
break;
case OTRL_MSGEVENT_CONNECTION_ENDED:
ui_handle_otr_error(context->username, "OTR: Message not sent because contact has ended the private conversation.");
break;
case OTRL_MSGEVENT_SETUP_ERROR:
ui_handle_otr_error(context->username, "OTR: A private conversation could not be set up.");
break;
case OTRL_MSGEVENT_MSG_REFLECTED:
ui_handle_otr_error(context->username, "OTR: Received our own OTR message.");
break;
case OTRL_MSGEVENT_MSG_RESENT:
ui_handle_otr_error(context->username, "OTR: The previous message was resent.");
break;
case OTRL_MSGEVENT_RCVDMSG_NOT_IN_PRIVATE:
ui_handle_otr_error(context->username, "OTR: Received an encrypted message but no private connection established.");
break;
case OTRL_MSGEVENT_RCVDMSG_UNREADABLE:
ui_handle_otr_error(context->username, "OTR: Cannot read the received message.");
break;
case OTRL_MSGEVENT_RCVDMSG_MALFORMED:
ui_handle_otr_error(context->username, "OTR: The message received contains malformed data.");
break;
case OTRL_MSGEVENT_RCVDMSG_GENERAL_ERR:
err_msg = g_string_new("OTR: Received error: ");
g_string_append(err_msg, message);
g_string_append(err_msg, ".");
ui_handle_otr_error(context->username, err_msg->str);
g_string_free(err_msg, TRUE);
break;
case OTRL_MSGEVENT_RCVDMSG_UNENCRYPTED:
err_msg = g_string_new("OTR: Received an unencrypted message: ");
g_string_append(err_msg, message);
ui_handle_otr_error(context->username, err_msg->str);
g_string_free(err_msg, TRUE);
break;
case OTRL_MSGEVENT_RCVDMSG_UNRECOGNIZED:
ui_handle_otr_error(context->username, "OTR: Cannot recognize the type of message received.");
break;
case OTRL_MSGEVENT_RCVDMSG_FOR_OTHER_INSTANCE:
ui_handle_otr_error(context->username, "OTR: Received and discarded a message intended for another instance.");
break;
default:
break;
}
}
@ -208,7 +253,7 @@ otrlib_end_session(OtrlUserState user_state, const char * const recipient, char
ConnContext *context = otrl_context_find(user_state, recipient, jid, "xmpp",
OTRL_INSTAG_MASTER, 0, NULL, NULL, NULL);
if (context != NULL) {
if (context) {
otrl_message_disconnect(user_state, ops, NULL, jid, "xmpp", recipient, 0);
}
}

View File

@ -1,7 +1,7 @@
/*
* profanity.c
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*
@ -63,6 +63,7 @@
#include "xmpp/xmpp.h"
#include "ui/ui.h"
#include "ui/windows.h"
#include "event/client_events.h"
static void _check_autoaway(void);
static void _init(const int disable_tls, char *log_level);
@ -71,6 +72,7 @@ static void _create_directories(void);
static void _connect_default(const char * const account);
static gboolean idle = FALSE;
static gboolean cont = TRUE;
void
prof_run(const int disable_tls, char *log_level, char *account_name)
@ -79,25 +81,27 @@ prof_run(const int disable_tls, char *log_level, char *account_name)
_connect_default(account_name);
ui_update();
char *line = NULL;
gboolean cmd_result = TRUE;
log_info("Starting main event loop");
while(cmd_result) {
while(!line) {
_check_autoaway();
line = ui_readline();
#ifdef HAVE_LIBOTR
otr_poll();
#endif
notify_remind();
jabber_process_events();
ui_update();
char *line = NULL;
while(cont) {
_check_autoaway();
line = ui_readline();
if (line) {
cont = cmd_process_input(line);
free(line);
line = NULL;
} else {
cont = TRUE;
}
cmd_result = cmd_process_input(line);
ui_input_clear();
FREE_SET_NULL(line);
#ifdef HAVE_LIBOTR
otr_poll();
#endif
notify_remind();
jabber_process_events();
ui_update();
}
}
@ -109,14 +113,14 @@ prof_handle_idle(void)
GSList *recipients = ui_get_chat_recipients();
GSList *curr = recipients;
while (curr != NULL) {
while (curr) {
char *barejid = curr->data;
ProfChatWin *chatwin = wins_get_chat(barejid);
chat_state_handle_idle(chatwin->barejid, chatwin->state);
curr = g_slist_next(curr);
}
if (recipients != NULL) {
if (recipients) {
g_slist_free(recipients);
}
}
@ -169,12 +173,12 @@ _check_autoaway()
// handle away mode
if (strcmp(pref_autoaway_mode, "away") == 0) {
presence_update(RESOURCE_AWAY, pref_autoaway_message, 0);
cl_ev_presence_send(RESOURCE_AWAY, pref_autoaway_message, 0);
ui_auto_away();
// handle idle mode
} else if (strcmp(pref_autoaway_mode, "idle") == 0) {
presence_update(RESOURCE_ONLINE, pref_autoaway_message, idle_ms / 1000);
cl_ev_presence_send(RESOURCE_ONLINE, pref_autoaway_message, idle_ms / 1000);
}
prefs_free_string(pref_autoaway_message);
@ -188,10 +192,10 @@ _check_autoaway()
// handle check
if (prefs_get_boolean(PREF_AUTOAWAY_CHECK)) {
if (strcmp(pref_autoaway_mode, "away") == 0) {
presence_update(RESOURCE_ONLINE, NULL, 0);
cl_ev_presence_send(RESOURCE_ONLINE, NULL, 0);
ui_end_auto_away();
} else if (strcmp(pref_autoaway_mode, "idle") == 0) {
presence_update(RESOURCE_ONLINE, NULL, 0);
cl_ev_presence_send(RESOURCE_ONLINE, NULL, 0);
ui_titlebar_presence(CONTACT_ONLINE);
}
}
@ -209,6 +213,7 @@ _init(const int disable_tls, char *log_level)
signal(SIGPIPE, SIG_IGN);
signal(SIGINT, SIG_IGN);
signal(SIGTSTP, SIG_IGN);
signal(SIGWINCH, ui_sigwinch_handler);
_create_directories();
log_level_t prof_log_level = log_level_from_string(log_level);
prefs_load();

View File

@ -1,7 +1,7 @@
/*
* profanity.h
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*

View File

@ -1,7 +1,7 @@
/*
* resource.c
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*
@ -46,7 +46,7 @@ Resource * resource_new(const char * const name, resource_presence_t presence,
Resource *new_resource = malloc(sizeof(struct resource_t));
new_resource->name = strdup(name);
new_resource->presence = presence;
if (status != NULL) {
if (status) {
new_resource->status = strdup(status);
} else {
new_resource->status = NULL;
@ -88,7 +88,7 @@ resource_compare_availability(Resource *first, Resource *second)
void resource_destroy(Resource *resource)
{
if (resource != NULL) {
if (resource) {
free(resource->name);
free(resource->status);
free(resource);

View File

@ -1,7 +1,7 @@
/*
* resource.h
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*

View File

@ -1,7 +1,7 @@
/*
* roster_list.c
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*
@ -42,6 +42,7 @@
#include "contact.h"
#include "jid.h"
#include "tools/autocomplete.h"
#include "config/preferences.h"
// nicknames
static Autocomplete name_ac;
@ -91,7 +92,7 @@ roster_update_presence(const char * const barejid, Resource *resource,
assert(barejid != NULL);
assert(resource != NULL);
PContact contact = g_hash_table_lookup(contacts, barejid);
PContact contact = roster_get_contact(barejid);
if (contact == NULL) {
return FALSE;
}
@ -109,14 +110,45 @@ roster_update_presence(const char * const barejid, Resource *resource,
PContact
roster_get_contact(const char * const barejid)
{
return g_hash_table_lookup(contacts, barejid);
gchar *barejidlower = g_utf8_strdown(barejid, -1);
PContact contact = g_hash_table_lookup(contacts, barejidlower);
g_free(barejidlower);
return contact;
}
char *
roster_get_msg_display_name(const char * const barejid, const char * const resource)
{
GString *result = g_string_new("");
PContact contact = roster_get_contact(barejid);
if (contact) {
if (p_contact_name(contact)) {
g_string_append(result, p_contact_name(contact));
} else {
g_string_append(result, barejid);
}
} else {
g_string_append(result, barejid);
}
if (resource && prefs_get_boolean(PREF_RESOURCE_MESSAGE)) {
g_string_append(result, "/");
g_string_append(result, resource);
}
char *result_str = result->str;
g_string_free(result, FALSE);
return result_str;
}
gboolean
roster_contact_offline(const char * const barejid,
const char * const resource, const char * const status)
{
PContact contact = g_hash_table_lookup(contacts, barejid);
PContact contact = roster_get_contact(barejid);
if (contact == NULL) {
return FALSE;
@ -174,7 +206,7 @@ roster_change_name(PContact contact, const char * const new_name)
const char *current_name = NULL;
const char *barejid = p_contact_barejid(contact);
if (p_contact_name(contact) != NULL) {
if (p_contact_name(contact)) {
current_name = strdup(p_contact_name(contact));
}
@ -191,9 +223,9 @@ roster_remove(const char * const name, const char * const barejid)
// remove each fulljid
PContact contact = roster_get_contact(barejid);
if (contact != NULL) {
if (contact) {
GList *resources = p_contact_get_available_resources(contact);
while (resources != NULL) {
while (resources) {
GString *fulljid = g_string_new(strdup(barejid));
g_string_append(fulljid, "/");
g_string_append(fulljid, resources->data);
@ -212,7 +244,7 @@ void
roster_update(const char * const barejid, const char * const name,
GSList *groups, const char * const subscription, gboolean pending_out)
{
PContact contact = g_hash_table_lookup(contacts, barejid);
PContact contact = roster_get_contact(barejid);
assert(contact != NULL);
p_contact_set_subscription(contact, subscription);
@ -220,7 +252,7 @@ roster_update(const char * const barejid, const char * const name,
const char * const new_name = name;
const char * current_name = NULL;
if (p_contact_name(contact) != NULL) {
if (p_contact_name(contact)) {
current_name = strdup(p_contact_name(contact));
}
@ -229,7 +261,7 @@ roster_update(const char * const barejid, const char * const name,
_replace_name(current_name, new_name, barejid);
// add groups
while (groups != NULL) {
while (groups) {
autocomplete_add(groups_ac, groups->data);
groups = g_slist_next(groups);
}
@ -239,8 +271,8 @@ gboolean
roster_add(const char * const barejid, const char * const name, GSList *groups,
const char * const subscription, gboolean pending_out)
{
PContact contact = g_hash_table_lookup(contacts, barejid);
if (contact != NULL) {
PContact contact = roster_get_contact(barejid);
if (contact) {
return FALSE;
}
@ -248,7 +280,7 @@ roster_add(const char * const barejid, const char * const name, GSList *groups,
pending_out);
// add groups
while (groups != NULL) {
while (groups) {
autocomplete_add(groups_ac, groups->data);
groups = g_slist_next(groups);
}
@ -286,7 +318,7 @@ roster_get_contacts_by_presence(const char * const presence)
}
}
// resturn all contact structs
// return all contact structs
return result;
}
@ -303,7 +335,7 @@ roster_get_contacts(void)
result = g_slist_insert_sorted(result, value, (GCompareFunc)_compare_contacts);
}
// resturn all contact structs
// return all contact structs
return result;
}
@ -321,7 +353,7 @@ roster_get_contacts_online(void)
result = g_slist_insert_sorted(result, value, (GCompareFunc)_compare_contacts);
}
// resturn all contact structs
// return all contact structs
return result;
}
@ -371,7 +403,7 @@ roster_get_nogroup(void)
}
}
// resturn all contact structs
// return all contact structs
return result;
}
@ -386,7 +418,7 @@ roster_get_group(const char * const group)
g_hash_table_iter_init(&iter, contacts);
while (g_hash_table_iter_next(&iter, &key, &value)) {
GSList *groups = p_contact_groups(value);
while (groups != NULL) {
while (groups) {
if (strcmp(groups->data, group) == 0) {
result = g_slist_insert_sorted(result, value, (GCompareFunc)_compare_contacts);
break;
@ -395,7 +427,7 @@ roster_get_group(const char * const group)
}
}
// resturn all contact structs
// return all contact structs
return result;
}
@ -445,12 +477,12 @@ _replace_name(const char * const current_name, const char * const new_name,
const char * const barejid)
{
// current handle exists already
if (current_name != NULL) {
if (current_name) {
autocomplete_remove(name_ac, current_name);
g_hash_table_remove(name_to_barejid, current_name);
_add_name_and_barejid(new_name, barejid);
// no current handle
} else if (new_name != NULL) {
} else if (new_name) {
autocomplete_remove(name_ac, barejid);
g_hash_table_remove(name_to_barejid, barejid);
_add_name_and_barejid(new_name, barejid);
@ -460,7 +492,7 @@ _replace_name(const char * const current_name, const char * const new_name,
static void
_add_name_and_barejid(const char * const name, const char * const barejid)
{
if (name != NULL) {
if (name) {
autocomplete_add(name_ac, name);
g_hash_table_insert(name_to_barejid, strdup(name), strdup(barejid));
} else {
@ -475,24 +507,18 @@ gint _compare_contacts(PContact a, PContact b)
const char * utf8_str_a = NULL;
const char * utf8_str_b = NULL;
if (p_contact_name(a) != NULL) {
utf8_str_a = p_contact_name(a);
if (p_contact_name_collate_key(a)) {
utf8_str_a = p_contact_name_collate_key(a);
} else {
utf8_str_a = p_contact_barejid(a);
utf8_str_a = p_contact_barejid_collate_key(a);
}
if (p_contact_name(b) != NULL) {
utf8_str_b = p_contact_name(b);
if (p_contact_name_collate_key(b)) {
utf8_str_b = p_contact_name_collate_key(b);
} else {
utf8_str_b = p_contact_barejid(b);
utf8_str_b = p_contact_barejid_collate_key(b);
}
gchar *key_a = g_utf8_collate_key(utf8_str_a, -1);
gchar *key_b = g_utf8_collate_key(utf8_str_b, -1);
gint result = g_strcmp0(key_a, key_b);
g_free(key_a);
g_free(key_b);
gint result = g_strcmp0(utf8_str_a, utf8_str_b);
return result;
}

View File

@ -1,7 +1,7 @@
/*
* roster_list.h
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*
@ -67,5 +67,6 @@ char * roster_group_autocomplete(const char * const search_str);
char * roster_barejid_autocomplete(const char * const search_str);
GSList * roster_get_contacts_by_presence(const char * const presence);
GSList * roster_get_nogroup(void);
char * roster_get_msg_display_name(const char * const barejid, const char * const resource);
#endif

View File

@ -1,822 +0,0 @@
/*
* server_events.c
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*
* Profanity 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.
*
* Profanity 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 Profanity. If not, see <http://www.gnu.org/licenses/>.
*
* In addition, as a special exception, the copyright holders give permission to
* link the code of portions of this program with the OpenSSL library under
* certain conditions as described in each individual source file, and
* distribute linked combinations including the two.
*
* You must obey the GNU General Public License in all respects for all of the
* code used other than OpenSSL. If you modify file(s) with this exception, you
* may extend this exception to your version of the file(s), but you are not
* obligated to do so. If you do not wish to do so, delete this exception
* statement from your version. If you delete this exception statement from all
* source files in the program, then also delete it here.
*
*/
#include <string.h>
#include <stdlib.h>
#include "config.h"
#include "chat_session.h"
#include "log.h"
#include "muc.h"
#include "config/preferences.h"
#include "config/account.h"
#include "roster_list.h"
#ifdef HAVE_LIBOTR
#include "otr/otr.h"
#include <libotr/proto.h>
#endif
#include "ui/ui.h"
void
handle_room_join_error(const char * const room, const char * const err)
{
if (muc_active(room)) {
muc_leave(room);
}
ui_handle_room_join_error(room, err);
}
// handle presence stanza errors
void
handle_presence_error(const char *from, const char * const type,
const char *err_msg)
{
// handle error from recipient
if (from != NULL) {
ui_handle_recipient_error(from, err_msg);
// handle errors from no recipient
} else {
ui_handle_error(err_msg);
}
}
// handle message stanza errors
void
handle_message_error(const char * const jid, const char * const type,
const char * const err_msg)
{
// handle errors from no recipient
if (jid == NULL) {
ui_handle_error(err_msg);
// handle recipient not found ('from' contains a value and type is 'cancel')
} else if (type != NULL && (strcmp(type, "cancel") == 0)) {
log_info("Recipient %s not found: %s", jid, err_msg);
Jid *jidp = jid_create(jid);
chat_session_remove(jidp->barejid);
// handle any other error from recipient
} else {
ui_handle_recipient_error(jid, err_msg);
}
}
void
handle_login_account_success(char *account_name)
{
ProfAccount *account = accounts_get_account(account_name);
#ifdef HAVE_LIBOTR
otr_on_connect(account);
#endif
ui_handle_login_account_success(account);
// attempt to rejoin rooms with passwords
GList *curr = muc_rooms();
while (curr != NULL) {
char *password = muc_password(curr->data);
if (password != NULL) {
char *nick = muc_nick(curr->data);
presence_join_room(curr->data, nick, password);
}
curr = g_list_next(curr);
}
g_list_free(curr);
log_info("%s logged in successfully", account->jid);
account_free(account);
}
void
handle_roster_received(void)
{
if (prefs_get_boolean(PREF_ROSTER)) {
ui_show_roster();
}
}
void
handle_lost_connection(void)
{
cons_show_error("Lost connection.");
roster_clear();
muc_invites_clear();
chat_sessions_clear();
ui_disconnected();
}
void
handle_failed_login(void)
{
cons_show_error("Login failed.");
log_info("Login failed");
}
void
handle_software_version_result(const char * const jid, const char * const presence,
const char * const name, const char * const version, const char * const os)
{
cons_show_software_version(jid, presence, name, version, os);
}
void
handle_disco_info(const char *from, GSList *identities, GSList *features)
{
cons_show_disco_info(from, identities, features);
}
void
handle_room_disco_info(const char * const room, GSList *identities, GSList *features)
{
ui_show_room_disco_info(room, identities, features);
}
void
handle_disco_info_error(const char * const from, const char * const error)
{
if (from) {
cons_show_error("Service discovery failed for %s: %s", from, error);
} else {
cons_show_error("Service discovery failed: %s", error);
}
}
void
handle_room_info_error(const char * const room, const char * const error)
{
ui_handle_room_info_error(room, error);
}
void
handle_room_list(GSList *rooms, const char *conference_node)
{
cons_show_room_list(rooms, conference_node);
}
void
handle_room_affiliation_list_result_error(const char * const room, const char * const affiliation,
const char * const error)
{
log_debug("Error retrieving %s list for room %s: %s", affiliation, room, error);
ui_handle_room_affiliation_list_error(room, affiliation, error);
}
void
handle_room_affiliation_list(const char * const room, const char * const affiliation, GSList *jids)
{
muc_jid_autocomplete_add_all(room, jids);
ui_handle_room_affiliation_list(room, affiliation, jids);
}
void
handle_room_role_set_error(const char * const room, const char * const nick, const char * const role,
const char * const error)
{
log_debug("Error setting role %s list for room %s, user %s: %s", role, room, nick, error);
ui_handle_room_role_set_error(room, nick, role, error);
}
void
handle_room_role_list_result_error(const char * const room, const char * const role, const char * const error)
{
log_debug("Error retrieving %s list for room %s: %s", role, room, error);
ui_handle_room_role_list_error(room, role, error);
}
void
handle_room_role_list(const char * const room, const char * const role, GSList *nicks)
{
ui_handle_room_role_list(room, role, nicks);
}
void
handle_room_affiliation_set_error(const char * const room, const char * const jid, const char * const affiliation,
const char * const error)
{
log_debug("Error setting affiliation %s list for room %s, user %s: %s", affiliation, room, jid, error);
ui_handle_room_affiliation_set_error(room, jid, affiliation, error);
}
void
handle_disco_items(GSList *items, const char *jid)
{
cons_show_disco_items(items, jid);
}
void
handle_room_invite(jabber_invite_t invite_type,
const char * const invitor, const char * const room,
const char * const reason)
{
if (!muc_active(room) && !muc_invites_contain(room)) {
cons_show_room_invite(invitor, room, reason);
muc_invites_add(room);
}
}
void
handle_room_broadcast(const char *const room_jid,
const char * const message)
{
if (muc_roster_complete(room_jid)) {
ui_room_broadcast(room_jid, message);
} else {
muc_pending_broadcasts_add(room_jid, message);
}
}
void
handle_room_subject(const char * const room, const char * const nick, const char * const subject)
{
muc_set_subject(room, subject);
if (muc_roster_complete(room)) {
ui_room_subject(room, nick, subject);
}
}
void
handle_room_history(const char * const room_jid, const char * const nick,
GTimeVal tv_stamp, const char * const message)
{
ui_room_history(room_jid, nick, tv_stamp, message);
}
void
handle_room_message(const char * const room_jid, const char * const nick,
const char * const message)
{
ui_room_message(room_jid, nick, message);
if (prefs_get_boolean(PREF_GRLOG)) {
Jid *jid = jid_create(jabber_get_fulljid());
groupchat_log_chat(jid->barejid, room_jid, nick, message);
jid_destroy(jid);
}
}
void
handle_incoming_private_message(char *fulljid, char *message)
{
ui_incoming_private_msg(fulljid, message, NULL);
}
void
handle_incoming_message(char *barejid, char *resource, char *message)
{
#ifdef HAVE_LIBOTR
gboolean was_decrypted = FALSE;
char *newmessage;
prof_otrpolicy_t policy = otr_get_policy(barejid);
char *whitespace_base = strstr(message,OTRL_MESSAGE_TAG_BASE);
//check for OTR whitespace (opportunistic or always)
if (policy == PROF_OTRPOLICY_OPPORTUNISTIC || policy == PROF_OTRPOLICY_ALWAYS) {
if (whitespace_base) {
if (strstr(message, OTRL_MESSAGE_TAG_V2) || strstr(message, OTRL_MESSAGE_TAG_V1)) {
// Remove whitespace pattern for proper display in UI
// Handle both BASE+TAGV1/2(16+8) and BASE+TAGV1+TAGV2(16+8+8)
int tag_length = 24;
if (strstr(message, OTRL_MESSAGE_TAG_V2) && strstr(message, OTRL_MESSAGE_TAG_V1)) {
tag_length = 32;
}
memmove(whitespace_base, whitespace_base+tag_length, tag_length);
char *otr_query_message = otr_start_query();
cons_show("OTR Whitespace pattern detected. Attempting to start OTR session...");
message_send_chat(barejid, otr_query_message);
}
}
}
newmessage = otr_decrypt_message(barejid, message, &was_decrypted);
// internal OTR message
if (newmessage == NULL) {
return;
}
if (policy == PROF_OTRPOLICY_ALWAYS && !was_decrypted && !whitespace_base) {
char *otr_query_message = otr_start_query();
cons_show("Attempting to start OTR session...");
message_send_chat(barejid, otr_query_message);
}
ui_incoming_msg(barejid, resource, newmessage, NULL);
if (prefs_get_boolean(PREF_CHLOG)) {
const char *jid = jabber_get_fulljid();
Jid *jidp = jid_create(jid);
char *pref_otr_log = prefs_get_string(PREF_OTR_LOG);
if (!was_decrypted || (strcmp(pref_otr_log, "on") == 0)) {
chat_log_chat(jidp->barejid, barejid, newmessage, PROF_IN_LOG, NULL);
} else if (strcmp(pref_otr_log, "redact") == 0) {
chat_log_chat(jidp->barejid, barejid, "[redacted]", PROF_IN_LOG, NULL);
}
prefs_free_string(pref_otr_log);
jid_destroy(jidp);
}
otr_free_message(newmessage);
#else
ui_incoming_msg(barejid, resource, message, NULL);
if (prefs_get_boolean(PREF_CHLOG)) {
const char *jid = jabber_get_fulljid();
Jid *jidp = jid_create(jid);
chat_log_chat(jidp->barejid, barejid, message, PROF_IN_LOG, NULL);
jid_destroy(jidp);
}
#endif
}
void
handle_delayed_private_message(char *fulljid, char *message, GTimeVal tv_stamp)
{
ui_incoming_private_msg(fulljid, message, &tv_stamp);
}
void
handle_delayed_message(char *barejid, char *message, GTimeVal tv_stamp)
{
ui_incoming_msg(barejid, NULL, message, &tv_stamp);
if (prefs_get_boolean(PREF_CHLOG)) {
const char *jid = jabber_get_fulljid();
Jid *jidp = jid_create(jid);
chat_log_chat(jidp->barejid, barejid, message, PROF_IN_LOG, &tv_stamp);
jid_destroy(jidp);
}
}
void
handle_typing(char *barejid, char *resource)
{
ui_contact_typing(barejid, resource);
if (ui_chat_win_exists(barejid)) {
chat_session_recipient_typing(barejid, resource);
}
}
void
handle_paused(char *barejid, char *resource)
{
if (ui_chat_win_exists(barejid)) {
chat_session_recipient_paused(barejid, resource);
}
}
void
handle_inactive(char *barejid, char *resource)
{
if (ui_chat_win_exists(barejid)) {
chat_session_recipient_inactive(barejid, resource);
}
}
void
handle_gone(const char * const barejid, const char * const resource)
{
ui_recipient_gone(barejid, resource);
if (ui_chat_win_exists(barejid)) {
chat_session_recipient_gone(barejid, resource);
}
}
void
handle_activity(const char * const barejid, const char * const resource, gboolean send_states)
{
if (ui_chat_win_exists(barejid)) {
chat_session_recipient_active(barejid, resource, send_states);
}
}
void
handle_subscription(const char *barejid, jabber_subscr_t type)
{
switch (type) {
case PRESENCE_SUBSCRIBE:
/* TODO: auto-subscribe if needed */
cons_show("Received authorization request from %s", barejid);
log_info("Received authorization request from %s", barejid);
ui_print_system_msg_from_recipient(barejid, "Authorization request, type '/sub allow' to accept or '/sub deny' to reject");
if (prefs_get_boolean(PREF_NOTIFY_SUB)) {
notify_subscription(barejid);
}
break;
case PRESENCE_SUBSCRIBED:
cons_show("Subscription received from %s", barejid);
log_info("Subscription received from %s", barejid);
ui_print_system_msg_from_recipient(barejid, "Subscribed");
break;
case PRESENCE_UNSUBSCRIBED:
cons_show("%s deleted subscription", barejid);
log_info("%s deleted subscription", barejid);
ui_print_system_msg_from_recipient(barejid, "Unsubscribed");
break;
default:
/* unknown type */
break;
}
}
void
handle_contact_offline(char *barejid, char *resource, char *status)
{
gboolean updated = roster_contact_offline(barejid, resource, status);
if (resource != NULL && updated) {
ui_contact_offline(barejid, resource, status);
}
rosterwin_roster();
chat_session_remove(barejid);
}
void
handle_contact_online(char *barejid, Resource *resource,
GDateTime *last_activity)
{
gboolean updated = roster_update_presence(barejid, resource, last_activity);
if (updated) {
char *show_console = prefs_get_string(PREF_STATUSES_CONSOLE);
char *show_chat_win = prefs_get_string(PREF_STATUSES_CHAT);
PContact contact = roster_get_contact(barejid);
if (p_contact_subscription(contact) != NULL) {
if (strcmp(p_contact_subscription(contact), "none") != 0) {
// show in console if "all"
if (g_strcmp0(show_console, "all") == 0) {
cons_show_contact_online(contact, resource, last_activity);
// show in console of "online" and presence online
} else if (g_strcmp0(show_console, "online") == 0 &&
resource->presence == RESOURCE_ONLINE) {
cons_show_contact_online(contact, resource, last_activity);
}
// show in chat win if "all"
if (g_strcmp0(show_chat_win, "all") == 0) {
ui_chat_win_contact_online(contact, resource, last_activity);
// show in char win if "online" and presence online
} else if (g_strcmp0(show_chat_win, "online") == 0 &&
resource->presence == RESOURCE_ONLINE) {
ui_chat_win_contact_online(contact, resource, last_activity);
}
}
}
prefs_free_string(show_console);
prefs_free_string(show_chat_win);
}
rosterwin_roster();
chat_session_remove(barejid);
}
void
handle_leave_room(const char * const room)
{
muc_leave(room);
ui_leave_room(room);
}
void
handle_room_destroy(const char * const room)
{
muc_leave(room);
ui_room_destroy(room);
}
void
handle_room_destroyed(const char * const room, const char * const new_jid, const char * const password,
const char * const reason)
{
muc_leave(room);
ui_room_destroyed(room, reason, new_jid, password);
}
void
handle_room_kicked(const char * const room, const char * const actor, const char * const reason)
{
muc_leave(room);
ui_room_kicked(room, actor, reason);
}
void
handle_room_banned(const char * const room, const char * const actor, const char * const reason)
{
muc_leave(room);
ui_room_banned(room, actor, reason);
}
void
handle_room_configure(const char * const room, DataForm *form)
{
ui_handle_room_configuration(room, form);
}
void
handle_room_configuration_form_error(const char * const room, const char * const message)
{
ui_handle_room_configuration_form_error(room, message);
}
void
handle_room_config_submit_result(const char * const room)
{
ui_handle_room_config_submit_result(room);
}
void
handle_room_config_submit_result_error(const char * const room, const char * const message)
{
ui_handle_room_config_submit_result_error(room, message);
}
void
handle_room_kick_result_error(const char * const room, const char * const nick, const char * const error)
{
ui_handle_room_kick_error(room, nick, error);
}
void
handle_room_occupant_offline(const char * const room, const char * const nick,
const char * const show, const char * const status)
{
muc_roster_remove(room, nick);
char *muc_status_pref = prefs_get_string(PREF_STATUSES_MUC);
if (g_strcmp0(muc_status_pref, "none") != 0) {
ui_room_member_offline(room, nick);
}
prefs_free_string(muc_status_pref);
occupantswin_occupants(room);
}
void
handle_room_occupent_kicked(const char * const room, const char * const nick, const char * const actor,
const char * const reason)
{
muc_roster_remove(room, nick);
ui_room_member_kicked(room, nick, actor, reason);
occupantswin_occupants(room);
}
void
handle_room_occupent_banned(const char * const room, const char * const nick, const char * const actor,
const char * const reason)
{
muc_roster_remove(room, nick);
ui_room_member_banned(room, nick, actor, reason);
occupantswin_occupants(room);
}
void
handle_group_add(const char * const contact,
const char * const group)
{
ui_group_added(contact, group);
}
void
handle_group_remove(const char * const contact,
const char * const group)
{
ui_group_removed(contact, group);
}
void
handle_roster_remove(const char * const barejid)
{
ui_roster_remove(barejid);
}
void
handle_roster_add(const char * const barejid, const char * const name)
{
ui_roster_add(barejid, name);
}
void
handle_roster_update(const char * const barejid, const char * const name,
GSList *groups, const char * const subscription, gboolean pending_out)
{
roster_update(barejid, name, groups, subscription, pending_out);
rosterwin_roster();
}
void
handle_autoping_cancel(void)
{
prefs_set_autoping(0);
cons_show_error("Server ping not supported, autoping disabled.");
}
void
handle_xmpp_stanza(const char * const msg)
{
ui_handle_stanza(msg);
}
void
handle_ping_result(const char * const from, int millis)
{
if (from == NULL) {
cons_show("Ping response from server: %dms.", millis);
} else {
cons_show("Ping response from %s: %dms.", from, millis);
}
}
void
handle_ping_error_result(const char * const from, const char * const error)
{
if (error == NULL) {
cons_show_error("Error returned from pinging %s.", from);
} else {
cons_show_error("Error returned from pinging %s: %s.", from, error);
}
}
void
handle_muc_self_online(const char * const room, const char * const nick, gboolean config_required,
const char * const role, const char * const affiliation, const char * const actor, const char * const reason,
const char * const jid, const char * const show, const char * const status)
{
muc_roster_add(room, nick, jid, role, affiliation, show, status);
char *old_role = muc_role_str(room);
char *old_affiliation = muc_affiliation_str(room);
muc_set_role(room, role);
muc_set_affiliation(room, affiliation);
// handle self nick change
if (muc_nick_change_pending(room)) {
muc_nick_change_complete(room, nick);
ui_room_nick_change(room, nick);
// handle roster complete
} else if (!muc_roster_complete(room)) {
if (muc_autojoin(room)) {
ui_room_join(room, FALSE);
} else {
ui_room_join(room, TRUE);
}
muc_invites_remove(room);
muc_roster_set_complete(room);
// show roster if occupants list disabled by default
if (!prefs_get_boolean(PREF_OCCUPANTS)) {
GList *occupants = muc_roster(room);
ui_room_roster(room, occupants, NULL);
g_list_free(occupants);
}
char *subject = muc_subject(room);
if (subject != NULL) {
ui_room_subject(room, NULL, subject);
}
GList *pending_broadcasts = muc_pending_broadcasts(room);
if (pending_broadcasts != NULL) {
GList *curr = pending_broadcasts;
while (curr != NULL) {
ui_room_broadcast(room, curr->data);
curr = g_list_next(curr);
}
}
// room configuration required
if (config_required) {
muc_set_requires_config(room, TRUE);
ui_room_requires_config(room);
}
// check for change in role/affiliation
} else {
if (prefs_get_boolean(PREF_MUC_PRIVILEGES)) {
// both changed
if ((g_strcmp0(role, old_role) != 0) && (g_strcmp0(affiliation, old_affiliation) != 0)) {
ui_room_role_and_affiliation_change(room, role, affiliation, actor, reason);
// role changed
} else if (g_strcmp0(role, old_role) != 0) {
ui_room_role_change(room, role, actor, reason);
// affiliation changed
} else if (g_strcmp0(affiliation, old_affiliation) != 0) {
ui_room_affiliation_change(room, affiliation, actor, reason);
}
}
}
occupantswin_occupants(room);
}
void
handle_muc_occupant_online(const char * const room, const char * const nick, const char * const jid,
const char * const role, const char * const affiliation, const char * const actor, const char * const reason,
const char * const show, const char * const status)
{
Occupant *occupant = muc_roster_item(room, nick);
const char *old_role = NULL;
const char *old_affiliation = NULL;
if (occupant) {
old_role = muc_occupant_role_str(occupant);
old_affiliation = muc_occupant_affiliation_str(occupant);
}
gboolean updated = muc_roster_add(room, nick, jid, role, affiliation, show, status);
// not yet finished joining room
if (!muc_roster_complete(room)) {
return;
}
// handle nickname change
char *old_nick = muc_roster_nick_change_complete(room, nick);
if (old_nick) {
ui_room_member_nick_change(room, old_nick, nick);
free(old_nick);
occupantswin_occupants(room);
return;
}
// joined room
if (!occupant) {
char *muc_status_pref = prefs_get_string(PREF_STATUSES_MUC);
if (g_strcmp0(muc_status_pref, "none") != 0) {
ui_room_member_online(room, nick, role, affiliation, show, status);
}
prefs_free_string(muc_status_pref);
occupantswin_occupants(room);
return;
}
// presence updated
if (updated) {
char *muc_status_pref = prefs_get_string(PREF_STATUSES_MUC);
if (g_strcmp0(muc_status_pref, "all") == 0) {
ui_room_member_presence(room, nick, show, status);
}
prefs_free_string(muc_status_pref);
occupantswin_occupants(room);
// presence unchanged, check for role/affiliation change
} else {
if (prefs_get_boolean(PREF_MUC_PRIVILEGES)) {
// both changed
if ((g_strcmp0(role, old_role) != 0) && (g_strcmp0(affiliation, old_affiliation) != 0)) {
ui_room_occupant_role_and_affiliation_change(room, nick, role, affiliation, actor, reason);
// role changed
} else if (g_strcmp0(role, old_role) != 0) {
ui_room_occupant_role_change(room, nick, role, actor, reason);
// affiliation changed
} else if (g_strcmp0(affiliation, old_affiliation) != 0) {
ui_room_occupant_affiliation_change(room, nick, affiliation, actor, reason);
}
}
occupantswin_occupants(room);
}
}

View File

@ -1,125 +0,0 @@
/*
* server_events.h
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*
* Profanity 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.
*
* Profanity 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 Profanity. If not, see <http://www.gnu.org/licenses/>.
*
* In addition, as a special exception, the copyright holders give permission to
* link the code of portions of this program with the OpenSSL library under
* certain conditions as described in each individual source file, and
* distribute linked combinations including the two.
*
* You must obey the GNU General Public License in all respects for all of the
* code used other than OpenSSL. If you modify file(s) with this exception, you
* may extend this exception to your version of the file(s), but you are not
* obligated to do so. If you do not wish to do so, delete this exception
* statement from your version. If you delete this exception statement from all
* source files in the program, then also delete it here.
*
*/
#ifndef SERVER_EVENTS_H
#define SERVER_EVENTS_H
#include "xmpp/xmpp.h"
void handle_login_account_success(char *account_name);
void handle_lost_connection(void);
void handle_failed_login(void);
void handle_software_version_result(const char * const jid, const char * const presence,
const char * const name, const char * const version, const char * const os);
void handle_disco_info(const char *from, GSList *identities, GSList *features);
void handle_disco_info_error(const char * const from, const char * const error);
void handle_room_list(GSList *rooms, const char *conference_node);
void handle_disco_items(GSList *items, const char *jid);
void handle_room_invite(jabber_invite_t invite_type,
const char * const invitor, const char * const room,
const char * const reason);
void handle_room_broadcast(const char *const room_jid,
const char * const message);
void handle_room_subject(const char * const room, const char * const nick, const char * const subject);
void handle_room_history(const char * const room_jid, const char * const nick,
GTimeVal tv_stamp, const char * const message);
void handle_room_message(const char * const room_jid, const char * const nick,
const char * const message);
void handle_room_join_error(const char * const room, const char * const err);
void handle_room_info_error(const char * const room, const char * const error);
void handle_room_disco_info(const char * const room, GSList *identities, GSList *features);
void handle_room_affiliation_list_result_error(const char * const room, const char * const affiliation,
const char * const error);
void handle_room_affiliation_list(const char * const room, const char * const affiliation, GSList *jids);
void handle_room_affiliation_set_error(const char * const room, const char * const jid, const char * const affiliation,
const char * const error);
void handle_room_role_list_result_error(const char * const from, const char * const role, const char * const error);
void handle_room_role_list(const char * const from, const char * const role, GSList *nicks);
void handle_room_role_set_error(const char * const room, const char * const nick, const char * const role,
const char * const error);
void handle_room_kick_result_error(const char * const room, const char * const nick, const char * const error);
void handle_incoming_message(char *barejid, char *resource, char *message);
void handle_incoming_private_message(char *fulljid, char *message);
void handle_delayed_message(char *fulljid, char *message, GTimeVal tv_stamp);
void handle_delayed_private_message(char *fulljid, char *message, GTimeVal tv_stamp);
void handle_typing(char *barejid, char *resource);
void handle_paused(char *barejid, char *resource);
void handle_inactive(char *barejid, char *resource);
void handle_activity(char *barejid, char *resource, gboolean send_states);
void handle_gone(const char * const barejid, const char * const resource);
void handle_subscription(const char *from, jabber_subscr_t type);
void handle_contact_offline(char *contact, char *resource, char *status);
void handle_contact_online(char *contact, Resource *resource,
GDateTime *last_activity);
void handle_leave_room(const char * const room);
void handle_room_destroy(const char * const room);
void handle_room_occupant_offline(const char * const room, const char * const nick,
const char * const show, const char * const status);
void handle_room_destroyed(const char * const room, const char * const new_jid, const char * const password,
const char * const reason);
void handle_room_kicked(const char * const room, const char * const actor, const char * const reason);
void handle_room_occupent_kicked(const char * const room, const char * const nick, const char * const actor,
const char * const reason);
void handle_room_banned(const char * const room, const char * const actor, const char * const reason);
void handle_room_occupent_banned(const char * const room, const char * const nick, const char * const actor,
const char * const reason);
void handle_group_add(const char * const contact,
const char * const group);
void handle_group_remove(const char * const contact,
const char * const group);
void handle_roster_remove(const char * const barejid);
void handle_roster_add(const char * const barejid, const char * const name);
void handle_autoping_cancel(void);
void handle_message_error(const char * const from, const char * const type,
const char * const err_msg);
void handle_presence_error(const char *from, const char * const type,
const char *err_msg);
void handle_xmpp_stanza(const char * const msg);
void handle_ping_result(const char * const from, int millis);
void handle_ping_error_result(const char * const from, const char * const error);
void handle_room_configure(const char * const room, DataForm *form);
void handle_room_configuration_form_error(const char * const from, const char * const message);
void handle_room_config_submit_result(const char * const room);
void handle_room_config_submit_result_error(const char * const room, const char * const message);
void handle_muc_self_online(const char * const room, const char * const nick, gboolean config_required,
const char * const role, const char * const affiliation, const char * const actor, const char * const reason,
const char * const jid, const char * const show, const char * const status);
void handle_muc_occupant_online(const char * const room, const char * const nick, const char * const jid,
const char * const role, const char * const affiliation, const char * const actor, const char * const reason,
const char * const show_str, const char * const status_str);
void handle_roster_update(const char * const barejid, const char * const name,
GSList *groups, const char * const subscription, gboolean pending_out);
void handle_roster_received(void);
#endif

View File

@ -1,7 +1,7 @@
/*
* autocomplete.c
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*

View File

@ -1,7 +1,7 @@
/*
* autocomplete.h
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*

View File

@ -1,283 +0,0 @@
/*
* history.c
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*
* Profanity 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.
*
* Profanity 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 Profanity. If not, see <http://www.gnu.org/licenses/>.
*
* In addition, as a special exception, the copyright holders give permission to
* link the code of portions of this program with the OpenSSL library under
* certain conditions as described in each individual source file, and
* distribute linked combinations including the two.
*
* You must obey the GNU General Public License in all respects for all of the
* code used other than OpenSSL. If you modify file(s) with this exception, you
* may extend this exception to your version of the file(s), but you are not
* obligated to do so. If you do not wish to do so, delete this exception
* statement from your version. If you delete this exception statement from all
* source files in the program, then also delete it here.
*
*/
#include <stdlib.h>
#include <string.h>
#include <glib.h>
#include "history.h"
struct history_session_t {
GList *items;
GList *sess_curr;
GList *sess_new;
GList *orig_curr;
};
struct history_t {
GList *items;
guint max_size;
struct history_session_t session;
};
static void _replace_history_with_session(History history);
static gboolean _adding_new(History history);
static void _reset_session(History history);
static gboolean _has_session(History history);
static void _remove_first(History history);
static void _update_current_session_item(History history, char *item);
static void _add_to_history(History history, char *item);
static void _remove_last_session_item(History history);
static void _replace_current_with_original(History history);
static void _create_session(History history);
static void _session_previous(History history);
static void _session_next(History history);
History
history_new(unsigned int size)
{
History new_history = malloc(sizeof(struct history_t));
new_history->items = NULL;
new_history->max_size = size;
_reset_session(new_history);
return new_history;
}
void
history_append(History history, char *item)
{
char *copied = "";
if (item != NULL) {
copied = strdup(item);
}
if (history->items == NULL) {
_add_to_history(history, copied);
return;
}
if (!_has_session(history)) {
if (g_list_length(history->items) == history->max_size) {
_remove_first(history);
}
_add_to_history(history, copied);
} else {
_update_current_session_item(history, copied);
if (_adding_new(history)) {
if (strcmp(history->session.sess_curr->data, "") == 0) {
_remove_last_session_item(history);
}
_replace_history_with_session(history);
} else {
_remove_last_session_item(history);
char *new = strdup(history->session.sess_curr->data);
history->session.items = g_list_append(history->session.items, new);
_replace_current_with_original(history);
_replace_history_with_session(history);
}
}
}
char *
history_previous(History history, char *item)
{
// no history
if (history->items == NULL) {
return NULL;
}
char *copied = "";
if (item != NULL) {
copied = strdup(item);
}
if (!_has_session(history)) {
_create_session(history);
// add the new item
history->session.items = g_list_append(history->session.items, copied);
history->session.sess_new = g_list_last(history->session.items);
char *result = strdup(history->session.sess_curr->data);
return result;
} else {
_update_current_session_item(history, copied);
_session_previous(history);
}
char *result = strdup(history->session.sess_curr->data);
return result;
}
char *
history_next(History history, char *item)
{
// no history, or no session, return NULL
if ((history->items == NULL) || (history->session.items == NULL)) {
return NULL;
}
if (g_list_next(history->session.sess_curr) == NULL) {
return NULL;
}
char *copied = "";
if (item != NULL) {
copied = strdup(item);
}
_update_current_session_item(history, copied);
_session_next(history);
char *result = strdup(history->session.sess_curr->data);
return result;
}
static void
_replace_history_with_session(History history)
{
g_list_free(history->items);
history->items = g_list_copy(history->session.items);
if (g_list_length(history->items) > history->max_size) {
_remove_first(history);
}
_reset_session(history);
}
static gboolean
_adding_new(History history)
{
return (history->session.sess_curr ==
g_list_last(history->session.items));
}
static void
_reset_session(History history)
{
history->session.items = NULL;
history->session.sess_curr = NULL;
history->session.sess_new = NULL;
history->session.orig_curr = NULL;
}
static gboolean
_has_session(History history)
{
return (history->session.items != NULL);
}
static void
_remove_first(History history)
{
GList *first = g_list_first(history->items);
char *first_item = first->data;
history->items = g_list_remove(history->items, first_item);
}
static void
_update_current_session_item(History history, char *item)
{
history->session.sess_curr->data = item;
}
static void
_add_to_history(History history, char *item)
{
history->items = g_list_append(history->items, item);
}
static void
_remove_last_session_item(History history)
{
history->session.items = g_list_reverse(history->session.items);
GList *first = g_list_first(history->session.items);
history->session.items =
g_list_remove(history->session.items, first->data);
history->session.items = g_list_reverse(history->session.items);
}
static void
_replace_current_with_original(History history)
{
history->session.sess_curr->data = strdup(history->session.orig_curr->data);
}
static void
_create_session(History history)
{
history->session.items = g_list_copy(history->items);
history->session.sess_curr = g_list_last(history->session.items);
history->session.orig_curr = g_list_last(history->items);
}
static void
_session_previous(History history)
{
history->session.sess_curr =
g_list_previous(history->session.sess_curr);
if (history->session.orig_curr == NULL)
history->session.orig_curr = g_list_last(history->items);
else
history->session.orig_curr =
g_list_previous(history->session.orig_curr);
if (history->session.sess_curr == NULL) {
history->session.sess_curr = g_list_first(history->session.items);
history->session.orig_curr = g_list_first(history->items);
}
}
static void
_session_next(History history)
{
history->session.sess_curr = g_list_next(history->session.sess_curr);
history->session.orig_curr = g_list_next(history->session.orig_curr);
if (history->session.sess_curr == NULL) {
history->session.sess_curr = g_list_last(history->session.items);
history->session.orig_curr = NULL;
}
}

View File

@ -1,7 +1,7 @@
/*
* parser.c
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*
@ -47,9 +47,9 @@
*
* inp - The line of input
* min - The minimum allowed number of arguments
* max - The maxmimum allowed number of arguments
* max - The maximum allowed number of arguments
*
* Returns - An NULL terminated array of strings representing the aguments
* Returns - An NULL terminated array of strings representing the arguments
* of the command, or NULL if the validation fails.
*
* E.g. the following input line:
@ -69,7 +69,7 @@ parse_args(const char * const inp, int min, int max, gboolean *result)
return NULL;
}
// copy and strip input of leading/trailing whitepsace
// copy and strip input of leading/trailing whitespace
char *copy = strdup(inp);
g_strstrip(copy);
@ -156,7 +156,7 @@ parse_args(const char * const inp, int min, int max, gboolean *result)
token = g_slist_next(token);
int arg_count = 0;
while (token != NULL) {
while (token) {
args[arg_count++] = strdup(token->data);
token = g_slist_next(token);
}
@ -181,9 +181,9 @@ parse_args(const char * const inp, int min, int max, gboolean *result)
*
* inp - The line of input
* min - The minimum allowed number of arguments
* max - The maxmimum allowed number of arguments
* max - The maximum allowed number of arguments
*
* Returns - An NULL terminated array of strings representing the aguments
* Returns - An NULL terminated array of strings representing the arguments
* of the command, or NULL if the validation fails.
*
* E.g. the following input line:
@ -303,7 +303,7 @@ parse_args_with_freetext(const char * const inp, int min, int max, gboolean *res
token = g_slist_next(token);
int arg_count = 0;
while (token != NULL) {
while (token) {
args[arg_count++] = strdup(token->data);
token = g_slist_next(token);
}
@ -419,7 +419,7 @@ parse_options(gchar **args, gchar **opt_keys, gboolean *res)
}
// check if duplicate
if (g_list_find_custom(found_keys, args[curr], (GCompareFunc)g_strcmp0) != NULL) {
if (g_list_find_custom(found_keys, args[curr], (GCompareFunc)g_strcmp0)) {
*res = FALSE;
g_list_free(keys);
return options;
@ -450,7 +450,7 @@ parse_options(gchar **args, gchar **opt_keys, gboolean *res)
void
options_destroy(GHashTable *options)
{
if (options != NULL) {
if (options) {
g_hash_table_destroy(options);
}
}

View File

@ -1,7 +1,7 @@
/*
* parser.h
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*

View File

@ -1,7 +1,7 @@
/*
* tinyurl.c
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*
@ -74,7 +74,7 @@ tinyurl_get(char *url)
g_string_free(full_url, TRUE);
if (output.buffer != NULL) {
if (output.buffer) {
output.buffer[output.size++] = '\0';
return output.buffer;
} else {

View File

@ -1,7 +1,7 @@
/*
* tinyurl.h
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*

View File

@ -1,7 +1,7 @@
/*
* buffer.c
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*
@ -81,7 +81,7 @@ buffer_free(ProfBuff buffer)
void
buffer_push(ProfBuff buffer, const char show_char, GDateTime *time,
int flags, theme_item_t theme_item, const char * const from, const char * const message)
int flags, theme_item_t theme_item, const char * const from, const char * const message, DeliveryReceipt *receipt)
{
ProfBuffEntry *e = malloc(sizeof(struct prof_buff_entry_t));
e->show_char = show_char;
@ -90,6 +90,7 @@ buffer_push(ProfBuff buffer, const char show_char, GDateTime *time,
e->time = time;
e->from = strdup(from);
e->message = strdup(message);
e->receipt = receipt;
if (g_slist_length(buffer->entries) == BUFF_SIZE) {
_free_entry(buffer->entries->data);
@ -99,6 +100,24 @@ buffer_push(ProfBuff buffer, const char show_char, GDateTime *time,
buffer->entries = g_slist_append(buffer->entries, e);
}
gboolean
buffer_mark_received(ProfBuff buffer, const char * const id)
{
GSList *entries = buffer->entries;
while (entries) {
ProfBuffEntry *entry = entries->data;
if (entry->receipt && g_strcmp0(entry->receipt->id, id) == 0) {
if (!entry->receipt->received) {
entry->receipt->received = TRUE;
return TRUE;
}
}
entries = g_slist_next(entries);
}
return FALSE;
}
ProfBuffEntry*
buffer_yield_entry(ProfBuff buffer, int entry)
{
@ -112,5 +131,9 @@ _free_entry(ProfBuffEntry *entry)
free(entry->message);
free(entry->from);
g_date_time_unref(entry->time);
if (entry->receipt) {
free(entry->receipt->id);
free(entry->receipt);
}
free(entry);
}

View File

@ -1,7 +1,7 @@
/*
* buffer.h
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*
@ -40,6 +40,11 @@
#include <glib.h>
typedef struct delivery_receipt_t {
char *id;
gboolean received;
} DeliveryReceipt;
typedef struct prof_buff_entry_t {
char show_char;
GDateTime *time;
@ -47,13 +52,18 @@ typedef struct prof_buff_entry_t {
theme_item_t theme_item;
char *from;
char *message;
DeliveryReceipt *receipt;
} ProfBuffEntry;
typedef struct prof_buff_t *ProfBuff;
ProfBuff buffer_create();
void buffer_free(ProfBuff buffer);
void buffer_push(ProfBuff buffer, const char show_char, GDateTime *time, int flags, theme_item_t theme_item, const char * const from, const char * const message);
void buffer_push(ProfBuff buffer, const char show_char, GDateTime *time, int flags, theme_item_t theme_item,
const char * const from, const char * const message, DeliveryReceipt *receipt);
int buffer_size(ProfBuff buffer);
ProfBuffEntry* buffer_yield_entry(ProfBuff buffer, int entry);
gboolean buffer_mark_received(ProfBuff buffer, const char * const id);
#endif

View File

@ -1,7 +1,7 @@
/*
* console.c
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*
@ -67,14 +67,14 @@ void
cons_show_time(void)
{
ProfWin *console = wins_get_console();
win_save_print(console, '-', NULL, NO_EOL, 0, "", "");
win_print(console, '-', NULL, NO_EOL, 0, "", "");
}
void
cons_show_word(const char * const word)
{
ProfWin *console = wins_get_console();
win_save_print(console, '-', NULL, NO_DATE | NO_EOL, 0, "", word);
win_print(console, '-', NULL, NO_DATE | NO_EOL, 0, "", word);
}
void
@ -86,7 +86,7 @@ cons_debug(const char * const msg, ...)
va_start(arg, msg);
GString *fmt_msg = g_string_new(NULL);
g_string_vprintf(fmt_msg, msg, arg);
win_save_println(console, fmt_msg->str);
win_println(console, fmt_msg->str);
g_string_free(fmt_msg, TRUE);
va_end(arg);
}
@ -100,7 +100,7 @@ cons_show(const char * const msg, ...)
va_start(arg, msg);
GString *fmt_msg = g_string_new(NULL);
g_string_vprintf(fmt_msg, msg, arg);
win_save_println(console, fmt_msg->str);
win_println(console, fmt_msg->str);
g_string_free(fmt_msg, TRUE);
va_end(arg);
}
@ -113,7 +113,7 @@ cons_show_error(const char * const msg, ...)
va_start(arg, msg);
GString *fmt_msg = g_string_new(NULL);
g_string_vprintf(fmt_msg, msg, arg);
win_save_print(console, '-', NULL, 0, THEME_ERROR, "", fmt_msg->str);
win_print(console, '-', NULL, 0, THEME_ERROR, "", fmt_msg->str);
g_string_free(fmt_msg, TRUE);
va_end(arg);
@ -126,8 +126,8 @@ cons_show_typing(const char * const barejid)
ProfWin *console = wins_get_console();
const char * display_usr = NULL;
PContact contact = roster_get_contact(barejid);
if (contact != NULL) {
if (p_contact_name(contact) != NULL) {
if (contact) {
if (p_contact_name(contact)) {
display_usr = p_contact_name(contact);
} else {
display_usr = barejid;
@ -136,7 +136,7 @@ cons_show_typing(const char * const barejid)
display_usr = barejid;
}
win_save_vprint(console, '-', NULL, 0, THEME_TYPING, "", "!! %s is typing a message...", display_usr);
win_vprint(console, '-', NULL, 0, THEME_TYPING, "", "!! %s is typing a message...", display_usr);
cons_alert();
}
@ -149,7 +149,7 @@ cons_show_incoming_message(const char * const short_from, const int win_index)
if (ui_index == 10) {
ui_index = 0;
}
win_save_vprint(console, '-', NULL, 0, THEME_INCOMING, "", "<< incoming from %s (%d)", short_from, ui_index);
win_vprint(console, '-', NULL, 0, THEME_INCOMING, "", "<< incoming from %s (%d)", short_from, ui_index);
cons_alert();
}
@ -167,23 +167,23 @@ cons_about(void)
if (strcmp(PACKAGE_STATUS, "development") == 0) {
#ifdef HAVE_GIT_VERSION
win_save_vprint(console, '-', NULL, 0, 0, "", "Welcome to Profanity, version %sdev.%s.%s", PACKAGE_VERSION, PROF_GIT_BRANCH, PROF_GIT_REVISION);
win_vprint(console, '-', NULL, 0, 0, "", "Welcome to Profanity, version %sdev.%s.%s", PACKAGE_VERSION, PROF_GIT_BRANCH, PROF_GIT_REVISION);
#else
win_save_vprint(console, '-', NULL, 0, 0, "", "Welcome to Profanity, version %sdev", PACKAGE_VERSION);
win_vprint(console, '-', NULL, 0, 0, "", "Welcome to Profanity, version %sdev", PACKAGE_VERSION);
#endif
} else {
win_save_vprint(console, '-', NULL, 0, 0, "", "Welcome to Profanity, version %s", PACKAGE_VERSION);
win_vprint(console, '-', NULL, 0, 0, "", "Welcome to Profanity, version %s", PACKAGE_VERSION);
}
}
win_save_vprint(console, '-', NULL, 0, 0, "", "Copyright (C) 2012 - 2014 James Booth <%s>.", PACKAGE_BUGREPORT);
win_save_println(console, "License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>");
win_save_println(console, "");
win_save_println(console, "This is free software; you are free to change and redistribute it.");
win_save_println(console, "There is NO WARRANTY, to the extent permitted by law.");
win_save_println(console, "");
win_save_println(console, "Type '/help' to show complete help.");
win_save_println(console, "");
win_vprint(console, '-', NULL, 0, 0, "", "Copyright (C) 2012 - 2015 James Booth <%s>.", PACKAGE_BUGREPORT);
win_println(console, "License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>");
win_println(console, "");
win_println(console, "This is free software; you are free to change and redistribute it.");
win_println(console, "There is NO WARRANTY, to the extent permitted by law.");
win_println(console, "");
win_println(console, "Type '/help' to show complete help.");
win_println(console, "");
if (prefs_get_boolean(PREF_VERCHECK)) {
cons_check_version(FALSE);
@ -200,18 +200,18 @@ cons_check_version(gboolean not_available_msg)
ProfWin *console = wins_get_console();
char *latest_release = release_get_latest();
if (latest_release != NULL) {
if (latest_release) {
gboolean relase_valid = g_regex_match_simple("^\\d+\\.\\d+\\.\\d+$", latest_release, 0, 0);
if (relase_valid) {
if (release_is_new(latest_release)) {
win_save_vprint(console, '-', NULL, 0, 0, "", "A new version of Profanity is available: %s", latest_release);
win_save_println(console, "Check <http://www.profanity.im> for details.");
win_save_println(console, "");
win_vprint(console, '-', NULL, 0, 0, "", "A new version of Profanity is available: %s", latest_release);
win_println(console, "Check <http://www.profanity.im> for details.");
win_println(console, "");
} else {
if (not_available_msg) {
win_save_println(console, "No new version available.");
win_save_println(console, "");
win_println(console, "No new version available.");
win_println(console, "");
}
}
@ -225,16 +225,16 @@ void
cons_show_login_success(ProfAccount *account)
{
ProfWin *console = wins_get_console();
win_save_vprint(console, '-', NULL, NO_EOL, 0, "", "%s logged in successfully, ", account->jid);
win_vprint(console, '-', NULL, NO_EOL, 0, "", "%s logged in successfully, ", account->jid);
resource_presence_t presence = accounts_get_login_presence(account->name);
const char *presence_str = string_from_resource_presence(presence);
theme_item_t presence_colour = theme_main_presence_attrs(presence_str);
win_save_vprint(console, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", "%s", presence_str);
win_save_vprint(console, '-', NULL, NO_DATE | NO_EOL, 0, "", " (priority %d)",
win_vprint(console, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", "%s", presence_str);
win_vprint(console, '-', NULL, NO_DATE | NO_EOL, 0, "", " (priority %d)",
accounts_get_priority_for_presence_type(account->name, presence));
win_save_print(console, '-', NULL, NO_DATE, 0, "", ".");
win_print(console, '-', NULL, NO_DATE, 0, "", ".");
cons_alert();
}
@ -247,10 +247,11 @@ cons_show_wins(void)
GSList *window_strings = wins_create_summary();
GSList *curr = window_strings;
while (curr != NULL) {
win_save_println(console, curr->data);
while (curr) {
win_println(console, curr->data);
curr = g_slist_next(curr);
}
g_slist_free_full(window_strings, free);
cons_show("");
cons_alert();
@ -264,7 +265,7 @@ cons_show_room_invites(GSList *invites)
cons_show("No outstanding chat room invites.");
} else {
cons_show("Chat room invites, use /join or /decline commands:");
while (invites != NULL) {
while (invites) {
cons_show(" %s", invites->data);
invites = g_slist_next(invites);
}
@ -293,53 +294,53 @@ cons_show_caps(const char * const fulljid, resource_presence_t presence)
const char *resource_presence = string_from_resource_presence(presence);
theme_item_t presence_colour = theme_main_presence_attrs(resource_presence);
win_save_vprint(console, '-', NULL, NO_EOL, presence_colour, "", "%s", fulljid);
win_save_print(console, '-', NULL, NO_DATE, 0, "", ":");
win_vprint(console, '-', NULL, NO_EOL, presence_colour, "", "%s", fulljid);
win_print(console, '-', NULL, NO_DATE, 0, "", ":");
// show identity
if ((caps->category != NULL) || (caps->type != NULL) || (caps->name != NULL)) {
win_save_print(console, '-', NULL, NO_EOL, 0, "", "Identity: ");
if (caps->name != NULL) {
win_save_print(console, '-', NULL, NO_DATE | NO_EOL, 0, "", caps->name);
if ((caps->category != NULL) || (caps->type != NULL)) {
win_save_print(console, '-', NULL, NO_DATE | NO_EOL, 0, "", " ");
if (caps->category || caps->type || caps->name) {
win_print(console, '-', NULL, NO_EOL, 0, "", "Identity: ");
if (caps->name) {
win_print(console, '-', NULL, NO_DATE | NO_EOL, 0, "", caps->name);
if (caps->category || caps->type) {
win_print(console, '-', NULL, NO_DATE | NO_EOL, 0, "", " ");
}
}
if (caps->type != NULL) {
win_save_print(console, '-', NULL, NO_DATE | NO_EOL, 0, "", caps->type);
if (caps->category != NULL) {
win_save_print(console, '-', NULL, NO_DATE | NO_EOL, 0, "", " ");
if (caps->type) {
win_print(console, '-', NULL, NO_DATE | NO_EOL, 0, "", caps->type);
if (caps->category) {
win_print(console, '-', NULL, NO_DATE | NO_EOL, 0, "", " ");
}
}
if (caps->category != NULL) {
win_save_print(console, '-', NULL, NO_DATE | NO_EOL, 0, "", caps->category);
if (caps->category) {
win_print(console, '-', NULL, NO_DATE | NO_EOL, 0, "", caps->category);
}
win_save_newline(console);
win_newline(console);
}
if (caps->software != NULL) {
win_save_vprint(console, '-', NULL, NO_EOL, 0, "", "Software: %s", caps->software);
if (caps->software) {
win_vprint(console, '-', NULL, NO_EOL, 0, "", "Software: %s", caps->software);
}
if (caps->software_version != NULL) {
win_save_vprint(console, '-', NULL, NO_DATE | NO_EOL, 0, "", ", %s", caps->software_version);
if (caps->software_version) {
win_vprint(console, '-', NULL, NO_DATE | NO_EOL, 0, "", ", %s", caps->software_version);
}
if ((caps->software != NULL) || (caps->software_version != NULL)) {
win_save_newline(console);
if (caps->software || caps->software_version) {
win_newline(console);
}
if (caps->os != NULL) {
win_save_vprint(console, '-', NULL, NO_EOL, 0, "", "OS: %s", caps->os);
if (caps->os) {
win_vprint(console, '-', NULL, NO_EOL, 0, "", "OS: %s", caps->os);
}
if (caps->os_version != NULL) {
win_save_vprint(console, '-', NULL, NO_DATE | NO_EOL, 0, "", ", %s", caps->os_version);
if (caps->os_version) {
win_vprint(console, '-', NULL, NO_DATE | NO_EOL, 0, "", ", %s", caps->os_version);
}
if ((caps->os != NULL) || (caps->os_version != NULL)) {
win_save_newline(console);
if (caps->os || caps->os_version) {
win_newline(console);
}
if (caps->features != NULL) {
win_save_println(console, "Features:");
if (caps->features) {
win_println(console, "Features:");
GSList *feature = caps->features;
while (feature != NULL) {
win_save_vprint(console, '-', NULL, 0, 0, "", " %s", feature->data);
while (feature) {
win_vprint(console, '-', NULL, 0, 0, "", " %s", feature->data);
feature = g_slist_next(feature);
}
}
@ -357,19 +358,19 @@ cons_show_software_version(const char * const jid, const char * const presence,
const char * const name, const char * const version, const char * const os)
{
ProfWin *console = wins_get_console();
if ((name != NULL) || (version != NULL) || (os != NULL)) {
if (name || version || os) {
cons_show("");
theme_item_t presence_colour = theme_main_presence_attrs(presence);
win_save_vprint(console, '-', NULL, NO_EOL, presence_colour, "", "%s", jid);
win_save_print(console, '-', NULL, NO_DATE, 0, "", ":");
win_vprint(console, '-', NULL, NO_EOL, presence_colour, "", "%s", jid);
win_print(console, '-', NULL, NO_DATE, 0, "", ":");
}
if (name != NULL) {
if (name) {
cons_show("Name : %s", name);
}
if (version != NULL) {
if (version) {
cons_show("Version : %s", version);
}
if (os != NULL) {
if (os) {
cons_show("OS : %s", os);
}
@ -385,7 +386,7 @@ cons_show_received_subs(void)
} else {
cons_show("Outstanding subscription requests from:",
g_slist_length(received));
while (received != NULL) {
while (received) {
cons_show(" %s", received->data);
received = g_slist_next(received);
}
@ -402,17 +403,18 @@ cons_show_sent_subs(void)
GSList *contacts = roster_get_contacts();
PContact contact = NULL;
cons_show("Awaiting subscription responses from:");
while (contacts != NULL) {
contact = (PContact) contacts->data;
GSList *curr = contacts;
while (curr) {
contact = (PContact) curr->data;
if (p_contact_pending_out(contact)) {
cons_show(" %s", p_contact_barejid(contact));
}
contacts = g_slist_next(contacts);
curr = g_slist_next(curr);
}
g_slist_free(contacts);
} else {
cons_show("No pending requests sent.");
}
cons_alert();
}
@ -420,15 +422,15 @@ void
cons_show_room_list(GSList *rooms, const char * const conference_node)
{
ProfWin *console = wins_get_console();
if ((rooms != NULL) && (g_slist_length(rooms) > 0)) {
if (rooms && (g_slist_length(rooms) > 0)) {
cons_show("Chat rooms at %s:", conference_node);
while (rooms != NULL) {
while (rooms) {
DiscoItem *room = rooms->data;
win_save_vprint(console, '-', NULL, NO_EOL, 0, "", " %s", room->jid);
if (room->name != NULL) {
win_save_vprint(console, '-', NULL, NO_DATE | NO_EOL, 0, "", ", (%s)", room->name);
win_vprint(console, '-', NULL, NO_EOL, 0, "", " %s", room->jid);
if (room->name) {
win_vprint(console, '-', NULL, NO_DATE | NO_EOL, 0, "", ", (%s)", room->name);
}
win_save_newline(console);
win_newline(console);
rooms = g_slist_next(rooms);
}
} else {
@ -450,7 +452,7 @@ cons_show_bookmarks(const GList *list)
cons_show("");
cons_show("Bookmarks:");
while (list != NULL) {
while (list) {
Bookmark *item = list->data;
theme_item_t presence_colour = THEME_TEXT;
@ -458,24 +460,24 @@ cons_show_bookmarks(const GList *list)
if (muc_active(item->jid)) {
presence_colour = THEME_ONLINE;
}
win_save_vprint(console, '-', NULL, NO_EOL, presence_colour, "", " %s", item->jid);
if (item->nick != NULL) {
win_save_vprint(console, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", "/%s", item->nick);
win_vprint(console, '-', NULL, NO_EOL, presence_colour, "", " %s", item->jid);
if (item->nick) {
win_vprint(console, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", "/%s", item->nick);
}
if (item->autojoin) {
win_save_print(console, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", " (autojoin)");
win_print(console, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", " (autojoin)");
}
if (item->password != NULL) {
win_save_print(console, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", " (private)");
if (item->password) {
win_print(console, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", " (private)");
}
if (muc_active(item->jid)) {
ProfWin *roomwin = (ProfWin*)wins_get_muc(item->jid);
if (roomwin != NULL) {
if (roomwin) {
int num = wins_get_num(roomwin);
win_save_vprint(console, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", " (%d)", num);
win_vprint(console, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", " (%d)", num);
}
}
win_save_newline(console);
win_newline(console);
list = g_list_next(list);
}
}
@ -485,26 +487,26 @@ cons_show_bookmarks(const GList *list)
void
cons_show_disco_info(const char *jid, GSList *identities, GSList *features)
{
if (((identities != NULL) && (g_slist_length(identities) > 0)) ||
((features != NULL) && (g_slist_length(features) > 0))) {
if ((identities && (g_slist_length(identities) > 0)) ||
(features && (g_slist_length(features) > 0))) {
cons_show("");
cons_show("Service disovery info for %s", jid);
if (identities != NULL) {
if (identities) {
cons_show(" Identities");
}
while (identities != NULL) {
while (identities) {
DiscoIdentity *identity = identities->data; // anme trpe, cat
GString *identity_str = g_string_new(" ");
if (identity->name != NULL) {
if (identity->name) {
identity_str = g_string_append(identity_str, identity->name);
identity_str = g_string_append(identity_str, " ");
}
if (identity->type != NULL) {
if (identity->type) {
identity_str = g_string_append(identity_str, identity->type);
identity_str = g_string_append(identity_str, " ");
}
if (identity->category != NULL) {
if (identity->category) {
identity_str = g_string_append(identity_str, identity->category);
}
cons_show(identity_str->str);
@ -512,10 +514,10 @@ cons_show_disco_info(const char *jid, GSList *identities, GSList *features)
identities = g_slist_next(identities);
}
if (features != NULL) {
if (features) {
cons_show(" Features:");
}
while (features != NULL) {
while (features) {
cons_show(" %s", features->data);
features = g_slist_next(features);
}
@ -528,16 +530,16 @@ void
cons_show_disco_items(GSList *items, const char * const jid)
{
ProfWin *console = wins_get_console();
if ((items != NULL) && (g_slist_length(items) > 0)) {
if (items && (g_slist_length(items) > 0)) {
cons_show("");
cons_show("Service discovery items for %s:", jid);
while (items != NULL) {
while (items) {
DiscoItem *item = items->data;
win_save_vprint(console, '-', NULL, NO_EOL, 0, "", " %s", item->jid);
if (item->name != NULL) {
win_save_vprint(console, '-', NULL, NO_DATE | NO_EOL, 0, "", ", (%s)", item->name);
win_vprint(console, '-', NULL, NO_EOL, 0, "", " %s", item->jid);
if (item->name) {
win_vprint(console, '-', NULL, NO_DATE | NO_EOL, 0, "", ", (%s)", item->name);
}
win_save_vprint(console, '-', NULL, NO_DATE, 0, "", "");
win_vprint(console, '-', NULL, NO_DATE, 0, "", "");
items = g_slist_next(items);
}
} else {
@ -554,7 +556,7 @@ cons_show_status(const char * const barejid)
ProfWin *console = wins_get_console();
PContact pcontact = roster_get_contact(barejid);
if (pcontact != NULL) {
if (pcontact) {
win_show_contact(console, pcontact);
} else {
cons_show("No such contact \"%s\" in roster.", barejid);
@ -569,8 +571,8 @@ cons_show_room_invite(const char * const invitor, const char * const room,
{
char *display_from = NULL;
PContact contact = roster_get_contact(invitor);
if (contact != NULL) {
if (p_contact_name(contact) != NULL) {
if (contact) {
if (p_contact_name(contact)) {
display_from = strdup(p_contact_name(contact));
} else {
display_from = strdup(invitor);
@ -584,7 +586,7 @@ cons_show_room_invite(const char * const invitor, const char * const room,
cons_show(" From : %s", display_from);
cons_show(" Room : %s", room);
if (reason != NULL) {
if (reason) {
cons_show(" Message: %s", reason);
}
@ -612,7 +614,7 @@ cons_show_account_list(gchar **accounts)
(g_strcmp0(jabber_get_account_name(), accounts[i]) == 0)) {
resource_presence_t presence = accounts_get_last_presence(accounts[i]);
theme_item_t presence_colour = theme_main_presence_attrs(string_from_resource_presence(presence));
win_save_vprint(console, '-', NULL, 0, presence_colour, "", "%s", accounts[i]);
win_vprint(console, '-', NULL, 0, presence_colour, "", "%s", accounts[i]);
} else {
cons_show(accounts[i]);
}
@ -671,9 +673,9 @@ cons_show_account(ProfAccount *account)
if (g_list_length(account->otr_manual) > 0) {
GString *manual = g_string_new("OTR manual : ");
GList *curr = account->otr_manual;
while (curr != NULL) {
while (curr) {
g_string_append(manual, curr->data);
if (curr->next != NULL) {
if (curr->next) {
g_string_append(manual, ", ");
}
curr = curr->next;
@ -684,9 +686,9 @@ cons_show_account(ProfAccount *account)
if (g_list_length(account->otr_opportunistic) > 0) {
GString *opportunistic = g_string_new("OTR opportunistic : ");
GList *curr = account->otr_opportunistic;
while (curr != NULL) {
while (curr) {
g_string_append(opportunistic, curr->data);
if (curr->next != NULL) {
if (curr->next) {
g_string_append(opportunistic, ", ");
}
curr = curr->next;
@ -697,9 +699,9 @@ cons_show_account(ProfAccount *account)
if (g_list_length(account->otr_always) > 0) {
GString *always = g_string_new("OTR always : ");
GList *curr = account->otr_always;
while (curr != NULL) {
while (curr) {
g_string_append(always, curr->data);
if (curr->next != NULL) {
if (curr->next) {
g_string_append(always, ", ");
}
curr = curr->next;
@ -717,76 +719,81 @@ cons_show_account(ProfAccount *account)
GList *resources = jabber_get_available_resources();
GList *ordered_resources = NULL;
if (resources != NULL) {
win_save_println(console, "Resources:");
GList *curr = resources;
if (curr) {
win_println(console, "Resources:");
// sort in order of availabiltiy
while (resources != NULL) {
Resource *resource = resources->data;
// sort in order of availability
while (curr) {
Resource *resource = curr->data;
ordered_resources = g_list_insert_sorted(ordered_resources,
resource, (GCompareFunc)resource_compare_availability);
resources = g_list_next(resources);
curr = g_list_next(curr);
}
}
while (ordered_resources != NULL) {
Resource *resource = ordered_resources->data;
g_list_free(resources);
curr = ordered_resources;
while (curr) {
Resource *resource = curr->data;
const char *resource_presence = string_from_resource_presence(resource->presence);
theme_item_t presence_colour = theme_main_presence_attrs(resource_presence);
win_save_vprint(console, '-', NULL, NO_EOL, presence_colour, "", " %s (%d), %s", resource->name, resource->priority, resource_presence);
win_vprint(console, '-', NULL, NO_EOL, presence_colour, "", " %s (%d), %s", resource->name, resource->priority, resource_presence);
if (resource->status != NULL) {
win_save_vprint(console, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", ", \"%s\"", resource->status);
if (resource->status) {
win_vprint(console, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", ", \"%s\"", resource->status);
}
win_save_vprint(console, '-', NULL, NO_DATE, 0, "", "");
win_vprint(console, '-', NULL, NO_DATE, 0, "", "");
Jid *jidp = jid_create_from_bare_and_resource(account->jid, resource->name);
Capabilities *caps = caps_lookup(jidp->fulljid);
jid_destroy(jidp);
if (caps != NULL) {
if (caps) {
// show identity
if ((caps->category != NULL) || (caps->type != NULL) || (caps->name != NULL)) {
win_save_print(console, '-', NULL, NO_EOL, 0, "", " Identity: ");
if (caps->name != NULL) {
win_save_print(console, '-', NULL, NO_DATE | NO_EOL, 0, "", caps->name);
if ((caps->category != NULL) || (caps->type != NULL)) {
win_save_print(console, '-', NULL, NO_DATE | NO_EOL, 0, "", " ");
if (caps->category || caps->type || caps->name) {
win_print(console, '-', NULL, NO_EOL, 0, "", " Identity: ");
if (caps->name) {
win_print(console, '-', NULL, NO_DATE | NO_EOL, 0, "", caps->name);
if (caps->category || caps->type) {
win_print(console, '-', NULL, NO_DATE | NO_EOL, 0, "", " ");
}
}
if (caps->type != NULL) {
win_save_print(console, '-', NULL, NO_DATE | NO_EOL, 0, "", caps->type);
if (caps->category != NULL) {
win_save_print(console, '-', NULL, NO_DATE | NO_EOL, 0, "", " ");
if (caps->type) {
win_print(console, '-', NULL, NO_DATE | NO_EOL, 0, "", caps->type);
if (caps->category) {
win_print(console, '-', NULL, NO_DATE | NO_EOL, 0, "", " ");
}
}
if (caps->category != NULL) {
win_save_print(console, '-', NULL, NO_DATE | NO_EOL, 0, "", caps->category);
if (caps->category) {
win_print(console, '-', NULL, NO_DATE | NO_EOL, 0, "", caps->category);
}
win_save_newline(console);
win_newline(console);
}
if (caps->software != NULL) {
win_save_vprint(console, '-', NULL, NO_EOL, 0, "", " Software: %s", caps->software);
if (caps->software) {
win_vprint(console, '-', NULL, NO_EOL, 0, "", " Software: %s", caps->software);
}
if (caps->software_version != NULL) {
win_save_vprint(console, '-', NULL, NO_DATE | NO_EOL, 0, "", ", %s", caps->software_version);
if (caps->software_version) {
win_vprint(console, '-', NULL, NO_DATE | NO_EOL, 0, "", ", %s", caps->software_version);
}
if ((caps->software != NULL) || (caps->software_version != NULL)) {
win_save_newline(console);
if (caps->software || caps->software_version) {
win_newline(console);
}
if (caps->os != NULL) {
win_save_vprint(console, '-', NULL, NO_EOL, 0, "", " OS: %s", caps->os);
if (caps->os) {
win_vprint(console, '-', NULL, NO_EOL, 0, "", " OS: %s", caps->os);
}
if (caps->os_version != NULL) {
win_save_vprint(console, '-', NULL, NO_DATE | NO_EOL, 0, "", ", %s", caps->os_version);
if (caps->os_version) {
win_vprint(console, '-', NULL, NO_DATE | NO_EOL, 0, "", ", %s", caps->os_version);
}
if ((caps->os != NULL) || (caps->os_version != NULL)) {
win_save_newline(console);
if (caps->os || caps->os_version) {
win_newline(console);
}
caps_destroy(caps);
}
ordered_resources = g_list_next(ordered_resources);
curr = g_list_next(curr);
}
g_list_free(ordered_resources);
}
cons_alert();
@ -801,10 +808,10 @@ cons_show_aliases(GList *aliases)
}
GList *curr = aliases;
if (curr != NULL) {
if (curr) {
cons_show("Command aliases:");
}
while (curr != NULL) {
while (curr) {
ProfAlias *alias = curr->data;
cons_show(" /%s -> %s", alias->name, alias->value);
curr = g_list_next(curr);
@ -850,9 +857,9 @@ cons_resource_setting(void)
else
cons_show("Resource title (/resource) : OFF");
if (prefs_get_boolean(PREF_RESOURCE_MESSAGE))
cons_show("Message title (/resource) : ON");
cons_show("Resource message (/resource) : ON");
else
cons_show("Message title (/resource) : OFF");
cons_show("Resource message (/resource) : OFF");
}
void
@ -899,6 +906,11 @@ cons_occupants_setting(void)
else
cons_show("Occupants (/occupants) : hide");
if (prefs_get_boolean(PREF_OCCUPANTS_JID))
cons_show("Occupant jids (/occupants) : show");
else
cons_show("Occupant jids (/occupants) : hide");
int size = prefs_get_occupants_size();
cons_show("Occupants size (/occupants) : %d", size);
}
@ -907,7 +919,7 @@ void
cons_autoconnect_setting(void)
{
char *pref_connect_account = prefs_get_string(PREF_CONNECT_ACCOUNT);
if (pref_connect_account != NULL)
if (pref_connect_account)
cons_show("Autoconnect (/autoconnect) : %s", pref_connect_account);
else
cons_show("Autoconnect (/autoconnect) : OFF");
@ -925,6 +937,16 @@ cons_time_setting(void)
cons_show("Time (/time) : %s", pref_time);
prefs_free_string(pref_time);
char *pref_time_statusbar = prefs_get_string(PREF_TIME_STATUSBAR);
if (g_strcmp0(pref_time_statusbar, "minutes") == 0)
cons_show("Time statusbar (/time) : minutes");
else if (g_strcmp0(pref_time_statusbar, "off") == 0)
cons_show("Time statusbar (/time) : OFF");
else
cons_show("Time statusbar (/time) : seconds");
prefs_free_string(pref_time_statusbar);
}
void
@ -994,6 +1016,9 @@ cons_roster_setting(void)
else
cons_show("Roster resource (/roster) : hide");
char *by = prefs_get_string(PREF_ROSTER_BY);
cons_show("Roster by (/roster) : %s", by);
int size = prefs_get_roster_size();
cons_show("Roster size (/roster) : %d", size);
}
@ -1120,27 +1145,27 @@ void
cons_states_setting(void)
{
if (prefs_get_boolean(PREF_STATES))
cons_show("Send chat states (/states) : ON");
cons_show("Send chat states (/states) : ON");
else
cons_show("Send chat states (/states) : OFF");
cons_show("Send chat states (/states) : OFF");
}
void
cons_outtype_setting(void)
{
if (prefs_get_boolean(PREF_OUTTYPE))
cons_show("Send composing (/outtype) : ON");
cons_show("Send composing (/outtype) : ON");
else
cons_show("Send composing (/outtype) : OFF");
cons_show("Send composing (/outtype) : OFF");
}
void
cons_intype_setting(void)
{
if (prefs_get_boolean(PREF_INTYPE))
cons_show("Show typing (/intype) : ON");
cons_show("Show typing (/intype) : ON");
else
cons_show("Show typing (/intype) : OFF");
cons_show("Show typing (/intype) : OFF");
}
void
@ -1148,11 +1173,11 @@ cons_gone_setting(void)
{
gint gone_time = prefs_get_gone();
if (gone_time == 0) {
cons_show("Leave conversation (/gone) : OFF");
cons_show("Leave conversation (/gone) : OFF");
} else if (gone_time == 1) {
cons_show("Leave conversation (/gone) : 1 minute");
cons_show("Leave conversation (/gone) : 1 minute");
} else {
cons_show("Leave conversation (/gone) : %d minutes", gone_time);
cons_show("Leave conversation (/gone) : %d minutes", gone_time);
}
}
@ -1160,9 +1185,33 @@ void
cons_history_setting(void)
{
if (prefs_get_boolean(PREF_HISTORY))
cons_show("Chat history (/history) : ON");
cons_show("Chat history (/history) : ON");
else
cons_show("Chat history (/history) : OFF");
cons_show("Chat history (/history) : OFF");
}
void
cons_carbons_setting(void)
{
if (prefs_get_boolean(PREF_CARBONS))
cons_show("Message carbons (/carbons) : ON");
else
cons_show("Message carbons (/carbons) : OFF");
}
void
cons_receipts_setting(void)
{
if (prefs_get_boolean(PREF_RECEIPTS_REQUEST))
cons_show("Request receipts (/receipts) : ON");
else
cons_show("Request receipts (/receipts) : OFF");
if (prefs_get_boolean(PREF_RECEIPTS_SEND))
cons_show("Send receipts (/receipts) : ON");
else
cons_show("Send receipts (/receipts) : OFF");
}
void
@ -1175,6 +1224,8 @@ cons_show_chat_prefs(void)
cons_intype_setting();
cons_gone_setting();
cons_history_setting();
cons_carbons_setting();
cons_receipts_setting();
cons_alert();
}
@ -1359,7 +1410,7 @@ cons_show_themes(GSList *themes)
cons_show("No available themes.");
} else {
cons_show("Available themes:");
while (themes != NULL) {
while (themes) {
cons_show(themes->data);
themes = g_slist_next(themes);
}
@ -1400,7 +1451,7 @@ cons_help(void)
cons_show("/help basic - List basic commands for getting started.");
cons_show("/help chatting - List chat commands.");
cons_show("/help groupchat - List groupchat commands.");
cons_show("/help presence - List commands to change presence.");
cons_show("/help presences - List commands to change presence.");
cons_show("/help contacts - List commands for manipulating your roster.");
cons_show("/help service - List service discovery commands.");
cons_show("/help settings - List commands for changing settings.");
@ -1417,27 +1468,10 @@ cons_navigation_help(void)
cons_show("");
cons_show("Navigation:");
cons_show("");
cons_show("Alt-1 : This console window.");
cons_show("F1 : This console window.");
cons_show("Alt-2..Alt-0 : Chat windows.");
cons_show("F2..F10 : Chat windows.");
cons_show("Alt-1..Alt-0, F1..F10 : Choose window.");
cons_show("Alt-LEFT, Alt-RIGHT : Previous/next chat window");
cons_show("UP, DOWN : Navigate input history.");
cons_show("Ctrl-n, Ctrl-p : Navigate input history.");
cons_show("LEFT, RIGHT, HOME, END : Move cursor.");
cons_show("Ctrl-b, Ctrl-f, Ctrl-a, Ctrl-e : Move cursor.");
cons_show("Ctrl-LEFT, Ctrl-RIGHT : Jump word.");
cons_show("Ctrl-w : Delete previous word.");
cons_show("Alt-Backspace : Delete previous word.");
cons_show("Backspace : Delete previous character.");
cons_show("DEL : Delete next character.");
cons_show("Ctrl-d : Delete next character.");
cons_show("ESC : Clear current input.");
cons_show("Ctrl-u : Delete all previous characters.");
cons_show("TAB : Autocomplete.");
cons_show("PAGE UP, PAGE DOWN : Page the main window.");
cons_show("Shift-UP, Shift-DOWN : Page occupants/roster panel.");
cons_show("Ctrl-UP, Ctrl-DOWN : Page occupants/roster panel.");
cons_show("PAGEUP, PAGEDOWN : Page the main window.");
cons_show("Alt-PAGEUP, Alt-PAGEDOWN : Page occupants/roster panel.");
cons_show("");
cons_alert();
@ -1448,7 +1482,7 @@ cons_show_roster_group(const char * const group, GSList *list)
{
cons_show("");
if (list != NULL) {
if (list) {
cons_show("%s:", group);
} else {
cons_show("No group named %s exists.", group);
@ -1537,22 +1571,22 @@ cons_theme_colours(void)
ProfWin *console = wins_get_console();
cons_show("Theme colours:");
win_save_print(console, '-', NULL, NO_EOL, THEME_WHITE, "", " white ");
win_save_print(console, '-', NULL, NO_DATE, THEME_WHITE_BOLD, "", " bold_white");
win_save_print(console, '-', NULL, NO_EOL, THEME_GREEN, "", " green ");
win_save_print(console, '-', NULL, NO_DATE, THEME_GREEN_BOLD, "", " bold_green");
win_save_print(console, '-', NULL, NO_EOL, THEME_RED, "", " red ");
win_save_print(console, '-', NULL, NO_DATE, THEME_RED_BOLD, "", " bold_red");
win_save_print(console, '-', NULL, NO_EOL, THEME_YELLOW, "", " yellow ");
win_save_print(console, '-', NULL, NO_DATE, THEME_YELLOW_BOLD, "", " bold_yellow");
win_save_print(console, '-', NULL, NO_EOL, THEME_BLUE, "", " blue ");
win_save_print(console, '-', NULL, NO_DATE, THEME_BLUE_BOLD, "", " bold_blue");
win_save_print(console, '-', NULL, NO_EOL, THEME_CYAN, "", " cyan ");
win_save_print(console, '-', NULL, NO_DATE, THEME_CYAN_BOLD, "", " bold_cyan");
win_save_print(console, '-', NULL, NO_EOL, THEME_MAGENTA, "", " magenta ");
win_save_print(console, '-', NULL, NO_DATE, THEME_MAGENTA_BOLD, "", " bold_magenta");
win_save_print(console, '-', NULL, NO_EOL, THEME_BLACK, "", " black ");
win_save_print(console, '-', NULL, NO_DATE, THEME_BLACK_BOLD, "", " bold_black");
win_print(console, '-', NULL, NO_EOL, THEME_WHITE, "", " white ");
win_print(console, '-', NULL, NO_DATE, THEME_WHITE_BOLD, "", " bold_white");
win_print(console, '-', NULL, NO_EOL, THEME_GREEN, "", " green ");
win_print(console, '-', NULL, NO_DATE, THEME_GREEN_BOLD, "", " bold_green");
win_print(console, '-', NULL, NO_EOL, THEME_RED, "", " red ");
win_print(console, '-', NULL, NO_DATE, THEME_RED_BOLD, "", " bold_red");
win_print(console, '-', NULL, NO_EOL, THEME_YELLOW, "", " yellow ");
win_print(console, '-', NULL, NO_DATE, THEME_YELLOW_BOLD, "", " bold_yellow");
win_print(console, '-', NULL, NO_EOL, THEME_BLUE, "", " blue ");
win_print(console, '-', NULL, NO_DATE, THEME_BLUE_BOLD, "", " bold_blue");
win_print(console, '-', NULL, NO_EOL, THEME_CYAN, "", " cyan ");
win_print(console, '-', NULL, NO_DATE, THEME_CYAN_BOLD, "", " bold_cyan");
win_print(console, '-', NULL, NO_EOL, THEME_MAGENTA, "", " magenta ");
win_print(console, '-', NULL, NO_DATE, THEME_MAGENTA_BOLD, "", " bold_magenta");
win_print(console, '-', NULL, NO_EOL, THEME_BLACK, "", " black ");
win_print(console, '-', NULL, NO_DATE, THEME_BLACK_BOLD, "", " bold_black");
cons_show("");
}
@ -1560,25 +1594,25 @@ static void
_cons_splash_logo(void)
{
ProfWin *console = wins_get_console();
win_save_println(console, "Welcome to");
win_println(console, "Welcome to");
win_save_print(console, '-', NULL, 0, THEME_SPLASH, "", " ___ _ ");
win_save_print(console, '-', NULL, 0, THEME_SPLASH, "", " / __) (_)_ ");
win_save_print(console, '-', NULL, 0, THEME_SPLASH, "", " ____ ____ ___ | |__ ____ ____ _| |_ _ _ ");
win_save_print(console, '-', NULL, 0, THEME_SPLASH, "", "| _ \\ / ___) _ \\| __) _ | _ \\| | _) | | |");
win_save_print(console, '-', NULL, 0, THEME_SPLASH, "", "| | | | | | |_| | | ( ( | | | | | | |_| |_| |");
win_save_print(console, '-', NULL, 0, THEME_SPLASH, "", "| ||_/|_| \\___/|_| \\_||_|_| |_|_|\\___)__ |");
win_save_print(console, '-', NULL, 0, THEME_SPLASH, "", "|_| (____/ ");
win_save_print(console, '-', NULL, 0, THEME_SPLASH, "", "");
win_print(console, '-', NULL, 0, THEME_SPLASH, "", " ___ _ ");
win_print(console, '-', NULL, 0, THEME_SPLASH, "", " / __) (_)_ ");
win_print(console, '-', NULL, 0, THEME_SPLASH, "", " ____ ____ ___ | |__ ____ ____ _| |_ _ _ ");
win_print(console, '-', NULL, 0, THEME_SPLASH, "", "| _ \\ / ___) _ \\| __) _ | _ \\| | _) | | |");
win_print(console, '-', NULL, 0, THEME_SPLASH, "", "| | | | | | |_| | | ( ( | | | | | | |_| |_| |");
win_print(console, '-', NULL, 0, THEME_SPLASH, "", "| ||_/|_| \\___/|_| \\_||_|_| |_|_|\\___)__ |");
win_print(console, '-', NULL, 0, THEME_SPLASH, "", "|_| (____/ ");
win_print(console, '-', NULL, 0, THEME_SPLASH, "", "");
if (strcmp(PACKAGE_STATUS, "development") == 0) {
#ifdef HAVE_GIT_VERSION
win_save_vprint(console, '-', NULL, 0, 0, "", "Version %sdev.%s.%s", PACKAGE_VERSION, PROF_GIT_BRANCH, PROF_GIT_REVISION);
win_vprint(console, '-', NULL, 0, 0, "", "Version %sdev.%s.%s", PACKAGE_VERSION, PROF_GIT_BRANCH, PROF_GIT_REVISION);
#else
win_save_vprint(console, '-', NULL, 0, 0, "", "Version %sdev", PACKAGE_VERSION);
win_vprint(console, '-', NULL, 0, 0, "", "Version %sdev", PACKAGE_VERSION);
#endif
} else {
win_save_vprint(console, '-', NULL, 0, 0, "", "Version %s", PACKAGE_VERSION);
win_vprint(console, '-', NULL, 0, 0, "", "Version %s", PACKAGE_VERSION);
}
}
@ -1592,7 +1626,7 @@ _show_roster_contacts(GSList *list, gboolean show_groups)
PContact contact = curr->data;
GString *title = g_string_new(" ");
title = g_string_append(title, p_contact_barejid(contact));
if (p_contact_name(contact) != NULL) {
if (p_contact_name(contact)) {
title = g_string_append(title, " (");
title = g_string_append(title, p_contact_name(contact));
title = g_string_append(title, ")");
@ -1605,11 +1639,11 @@ _show_roster_contacts(GSList *list, gboolean show_groups)
} else {
presence_colour = theme_main_presence_attrs("offline");
}
win_save_vprint(console, '-', NULL, NO_EOL, presence_colour, "", title->str);
win_vprint(console, '-', NULL, NO_EOL, presence_colour, "", title->str);
g_string_free(title, TRUE);
win_save_print(console, '-', NULL, NO_DATE | NO_EOL, 0, "", " - ");
win_print(console, '-', NULL, NO_DATE | NO_EOL, 0, "", " - ");
GString *sub = g_string_new("");
sub = g_string_append(sub, p_contact_subscription(contact));
if (p_contact_pending_out(contact)) {
@ -1625,28 +1659,28 @@ _show_roster_contacts(GSList *list, gboolean show_groups)
}
if (show_groups) {
win_save_vprint(console, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", "%s", sub->str);
win_vprint(console, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", "%s", sub->str);
} else {
win_save_vprint(console, '-', NULL, NO_DATE, presence_colour, "", "%s", sub->str);
win_vprint(console, '-', NULL, NO_DATE, presence_colour, "", "%s", sub->str);
}
g_string_free(sub, TRUE);
if (show_groups) {
GSList *groups = p_contact_groups(contact);
if (groups != NULL) {
if (groups) {
GString *groups_str = g_string_new(" - ");
while (groups != NULL) {
while (groups) {
g_string_append(groups_str, groups->data);
if (g_slist_next(groups) != NULL) {
if (g_slist_next(groups)) {
g_string_append(groups_str, ", ");
}
groups = g_slist_next(groups);
}
win_save_vprint(console, '-', NULL, NO_DATE, 0, "", "%s", groups_str->str);
win_vprint(console, '-', NULL, NO_DATE, 0, "", "%s", groups_str->str);
g_string_free(groups_str, TRUE);
} else {
win_save_print(console, '-', NULL, NO_DATE, 0, "", " ");
win_print(console, '-', NULL, NO_DATE, 0, "", " ");
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
/*
* inputwin.c
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*
@ -35,15 +35,17 @@
#ifndef UI_INPUTWIN_H
#define UI_INPUTWIN_H
#include <glib.h>
#define INP_WIN_MAX 1000
void create_input_window(void);
char* inp_read(int *key_type, wint_t *ch);
void inp_win_reset(void);
char* inp_readline(void);
void inp_nonblocking(gboolean reset);
void inp_close(void);
void inp_win_clear(void);
void inp_win_resize(void);
void inp_put_back(void);
void inp_non_block(gint);
void inp_block(void);
void inp_get_password(char *passwd);
void inp_replace_input(const char * const new_input);
void inp_history_append(char *inp);
char* inp_get_password(void);
#endif

View File

@ -1,7 +1,7 @@
/*
* notifier.c
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*
@ -48,10 +48,10 @@
#include "log.h"
#include "muc.h"
#include "ui/ui.h"
#include "ui/windows.h"
#include "config/preferences.h"
static void _notify(const char * const message, int timeout,
const char * const category);
static void _notify(const char * const message, int timeout, const char * const category);
static GTimer *remind_timer;
@ -89,7 +89,7 @@ notify_invite(const char * const from, const char * const room,
g_string_append(message, from);
g_string_append(message, "\nto: ");
g_string_append(message, room);
if (reason != NULL) {
if (reason) {
g_string_append_printf(message, "\n\"%s\"", reason);
}
@ -99,17 +99,25 @@ notify_invite(const char * const from, const char * const room,
}
void
notify_message(const char * const handle, int win, const char * const text)
notify_message(ProfWin *window, const char * const name, const char * const text)
{
GString *message = g_string_new("");
g_string_append_printf(message, "%s (win %d)", handle, win);
if (text != NULL) {
g_string_append_printf(message, "\n%s", text);
int num = wins_get_num(window);
if (num == 10) {
num = 0;
}
_notify(message->str, 10000, "incoming message");
gboolean is_current = wins_is_current(window);
if (!is_current || (is_current && prefs_get_boolean(PREF_NOTIFY_MESSAGE_CURRENT)) ) {
GString *message = g_string_new("");
g_string_append_printf(message, "%s (win %d)", name, num);
g_string_free(message, TRUE);
if (prefs_get_boolean(PREF_NOTIFY_MESSAGE_TEXT) && text) {
g_string_append_printf(message, "\n%s", text);
}
_notify(message->str, 10000, "incoming message");
g_string_free(message, TRUE);
}
}
void
@ -117,7 +125,7 @@ notify_room_message(const char * const handle, const char * const room, int win,
{
GString *message = g_string_new("");
g_string_append_printf(message, "%s in %s (win %d)", handle, room, win);
if (text != NULL) {
if (text) {
g_string_append_printf(message, "\n%s", text);
}
@ -243,10 +251,9 @@ _notify(const char * const message, int timeout,
Shell_NotifyIcon(NIM_MODIFY, &nid);
#endif
#ifdef HAVE_OSXNOTIFY
GString *notify_command = g_string_new("terminal-notifier -title \"Profanity\" -message \"");
GString *notify_command = g_string_new("terminal-notifier -title \"Profanity\" -message '");
char *escaped_double = str_replace(message, "\"", "\\\"");
char *escaped_single = str_replace(escaped_double, "`", "\\`");
char *escaped_single = str_replace(message, "'", "'\\''");
if (escaped_single[0] == '<') {
g_string_append(notify_command, "\\<");
@ -264,8 +271,7 @@ _notify(const char * const message, int timeout,
g_string_append(notify_command, escaped_single);
}
g_string_append(notify_command, "\"");
free(escaped_double);
g_string_append(notify_command, "'");
free(escaped_single);
char *term_name = getenv("TERM_PROGRAM");
@ -276,7 +282,7 @@ _notify(const char * const message, int timeout,
app_id = "com.googlecode.iterm2";
}
if (app_id != NULL) {
if (app_id) {
g_string_append(notify_command, " -sender ");
g_string_append(notify_command, app_id);
}
@ -288,4 +294,4 @@ _notify(const char * const message, int timeout,
g_string_free(notify_command, TRUE);
#endif
}
}

View File

@ -1,7 +1,7 @@
/*
* occupantswin.c
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*
@ -40,7 +40,7 @@
#include "config/preferences.h"
static void
_occuptantswin_occupant(ProfLayoutSplit *layout, Occupant *occupant)
_occuptantswin_occupant(ProfLayoutSplit *layout, Occupant *occupant, gboolean showjid)
{
const char *presence_str = string_from_resource_presence(occupant->presence);
theme_item_t presence_colour = theme_main_presence_attrs(presence_str);
@ -51,6 +51,13 @@ _occuptantswin_occupant(ProfLayoutSplit *layout, Occupant *occupant)
win_printline_nowrap(layout->subwin, msg->str);
g_string_free(msg, TRUE);
if (showjid && occupant->jid) {
GString *msg = g_string_new(" ");
g_string_append(msg, occupant->jid);
win_printline_nowrap(layout->subwin, msg->str);
g_string_free(msg, TRUE);
}
wattroff(layout->subwin, theme_attrs(presence_colour));
}
@ -74,7 +81,7 @@ occupantswin_occupants(const char * const roomjid)
while (roster_curr) {
Occupant *occupant = roster_curr->data;
if (occupant->role == MUC_ROLE_MODERATOR) {
_occuptantswin_occupant(layout, occupant);
_occuptantswin_occupant(layout, occupant, mucwin->showjid);
}
roster_curr = g_list_next(roster_curr);
}
@ -86,7 +93,7 @@ occupantswin_occupants(const char * const roomjid)
while (roster_curr) {
Occupant *occupant = roster_curr->data;
if (occupant->role == MUC_ROLE_PARTICIPANT) {
_occuptantswin_occupant(layout, occupant);
_occuptantswin_occupant(layout, occupant, mucwin->showjid);
}
roster_curr = g_list_next(roster_curr);
}
@ -98,7 +105,7 @@ occupantswin_occupants(const char * const roomjid)
while (roster_curr) {
Occupant *occupant = roster_curr->data;
if (occupant->role == MUC_ROLE_VISITOR) {
_occuptantswin_occupant(layout, occupant);
_occuptantswin_occupant(layout, occupant, mucwin->showjid);
}
roster_curr = g_list_next(roster_curr);
}
@ -109,7 +116,7 @@ occupantswin_occupants(const char * const roomjid)
GList *roster_curr = occupants;
while (roster_curr) {
Occupant *occupant = roster_curr->data;
_occuptantswin_occupant(layout, occupant);
_occuptantswin_occupant(layout, occupant, mucwin->showjid);
roster_curr = g_list_next(roster_curr);
}
}

View File

@ -1,7 +1,7 @@
/*
* rosterwin.c
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*

View File

@ -1,7 +1,7 @@
/*
* statusbar.c
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*
@ -48,6 +48,7 @@
#include "ui/ui.h"
#include "ui/statusbar.h"
#include "ui/inputwin.h"
#include "config/preferences.h"
#define TIME_CHECK 60000000
@ -94,7 +95,7 @@ create_status_bar(void)
mvwprintw(status_bar, 0, cols - 34 + ((current - 1) * 3), bracket);
wattroff(status_bar, bracket_attrs);
if (last_time != NULL) {
if (last_time) {
g_date_time_unref(last_time);
}
last_time = g_date_time_new_now_local();
@ -126,10 +127,17 @@ status_bar_resize(void)
mvwprintw(status_bar, 0, cols - 34 + ((current - 1) * 3), bracket);
wattroff(status_bar, bracket_attrs);
if (message != NULL) {
mvwprintw(status_bar, 0, 10, message);
if (message) {
char *time_pref = prefs_get_string(PREF_TIME_STATUSBAR);
if (g_strcmp0(time_pref, "minutes") == 0) {
mvwprintw(status_bar, 0, 10, message);
} else if (g_strcmp0(time_pref, "seconds") == 0) {
mvwprintw(status_bar, 0, 13, message);
} else {
mvwprintw(status_bar, 0, 1, message);
}
}
if (last_time != NULL) {
if (last_time) {
g_date_time_unref(last_time);
}
last_time = g_date_time_new_now_local();
@ -192,7 +200,7 @@ status_bar_inactive(const int win)
is_new[11] = TRUE;
_mark_new(11);
// still have active winsows
// still have active windows
} else if (g_hash_table_size(remaining_active) != 0) {
is_active[11] = TRUE;
is_new[11] = FALSE;
@ -241,7 +249,7 @@ status_bar_active(const int win)
_mark_active(11);
}
// visible winsow indicators
// visible window indicators
} else {
is_active[true_win] = TRUE;
is_new[true_win] = FALSE;
@ -289,11 +297,19 @@ status_bar_print_message(const char * const msg)
{
werase(status_bar);
if (message != NULL) {
if (message) {
free(message);
}
message = strdup(msg);
mvwprintw(status_bar, 0, 10, message);
char *time_pref = prefs_get_string(PREF_TIME_STATUSBAR);
if (g_strcmp0(time_pref, "minutes") == 0) {
mvwprintw(status_bar, 0, 10, message);
} else if (g_strcmp0(time_pref, "seconds") == 0) {
mvwprintw(status_bar, 0, 13, message);
} else {
mvwprintw(status_bar, 0, 1, message);
}
int cols = getmaxx(stdscr);
int bracket_attrs = theme_attrs(THEME_STATUS_BRACKET);
@ -309,7 +325,7 @@ status_bar_print_message(const char * const msg)
void
status_bar_clear(void)
{
if (message != NULL) {
if (message) {
free(message);
message = NULL;
}
@ -330,7 +346,7 @@ status_bar_clear(void)
void
status_bar_clear_message(void)
{
if (message != NULL) {
if (message) {
free(message);
message = NULL;
}
@ -412,23 +428,37 @@ _mark_inactive(int num)
static void
_status_bar_draw(void)
{
if (last_time != NULL) {
if (last_time) {
g_date_time_unref(last_time);
}
last_time = g_date_time_new_now_local();
gchar *date_fmt = g_date_time_format(last_time, "%H:%M");
assert(date_fmt != NULL);
int bracket_attrs = theme_attrs(THEME_STATUS_BRACKET);
wattron(status_bar, bracket_attrs);
mvwaddch(status_bar, 0, 1, '[');
wattroff(status_bar, bracket_attrs);
mvwprintw(status_bar, 0, 2, date_fmt);
wattron(status_bar, bracket_attrs);
mvwaddch(status_bar, 0, 7, ']');
wattroff(status_bar, bracket_attrs);
g_free(date_fmt);
char *time_pref = prefs_get_string(PREF_TIME_STATUSBAR);
if (g_strcmp0(time_pref, "minutes") == 0) {
gchar *date_fmt = g_date_time_format(last_time, "%H:%M");
assert(date_fmt != NULL);
wattron(status_bar, bracket_attrs);
mvwaddch(status_bar, 0, 1, '[');
wattroff(status_bar, bracket_attrs);
mvwprintw(status_bar, 0, 2, date_fmt);
wattron(status_bar, bracket_attrs);
mvwaddch(status_bar, 0, 7, ']');
wattroff(status_bar, bracket_attrs);
g_free(date_fmt);
} else if (g_strcmp0(time_pref, "seconds") == 0) {
gchar *date_fmt = g_date_time_format(last_time, "%H:%M:%S");
assert(date_fmt != NULL);
wattron(status_bar, bracket_attrs);
mvwaddch(status_bar, 0, 1, '[');
wattroff(status_bar, bracket_attrs);
mvwprintw(status_bar, 0, 2, date_fmt);
wattron(status_bar, bracket_attrs);
mvwaddch(status_bar, 0, 10, ']');
wattroff(status_bar, bracket_attrs);
g_free(date_fmt);
}
_update_win_statuses();
wnoutrefresh(status_bar);

View File

@ -1,7 +1,7 @@
/*
* statusbar.h
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*

View File

@ -1,7 +1,7 @@
/*
* titlebar.c
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*
@ -80,7 +80,7 @@ title_bar_update_virtual(void)
{
ProfWin *window = wins_get_current();
if (window->type != WIN_CONSOLE) {
if (typing_elapsed != NULL) {
if (typing_elapsed) {
gdouble seconds = g_timer_elapsed(typing_elapsed, NULL);
if (seconds >= 10) {
@ -109,8 +109,11 @@ void
title_bar_console(void)
{
werase(win);
typing = FALSE;
if (typing_elapsed) {
g_timer_destroy(typing_elapsed);
}
typing_elapsed = NULL;
typing = FALSE;
_title_bar_draw();
}
@ -125,7 +128,7 @@ title_bar_set_presence(contact_presence_t presence)
void
title_bar_switch(void)
{
if (typing_elapsed != NULL) {
if (typing_elapsed) {
g_timer_destroy(typing_elapsed);
typing_elapsed = NULL;
typing = FALSE;
@ -138,7 +141,7 @@ void
title_bar_set_typing(gboolean is_typing)
{
if (is_typing) {
if (typing_elapsed != NULL) {
if (typing_elapsed) {
g_timer_start(typing_elapsed);
} else {
typing_elapsed = g_timer_new();
@ -249,7 +252,7 @@ _show_privacy(ProfChatWin *chatwin)
{
int bracket_attrs = theme_attrs(THEME_TITLE_BRACKET);
if (!chatwin->is_otr) {
if (chatwin->enc_mode == PROF_ENC_NONE) {
if (prefs_get_boolean(PREF_OTR_WARN)) {
int unencrypted_attrs = theme_attrs(THEME_TITLE_UNENCRYPTED);
wprintw(win, " ");

View File

@ -1,7 +1,7 @@
/*
* titlebar.h
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*

View File

@ -1,7 +1,7 @@
/*
* ui.h
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*
@ -59,9 +59,8 @@ void ui_close(void);
void ui_redraw(void);
void ui_resize(void);
GSList* ui_get_chat_recipients(void);
gboolean ui_switch_win(const int i);
void ui_next_win(void);
void ui_previous_win(void);
void ui_switch_win(ProfWin *window);
void ui_sigwinch_handler(int sig);
void ui_gone_secure(const char * const barejid, gboolean trusted);
void ui_gone_insecure(const char * const barejid);
@ -81,10 +80,12 @@ void ui_smp_answer_failure(const char * const barejid);
void ui_otr_authenticating(const char * const barejid);
void ui_otr_authetication_waiting(const char * const recipient);
void ui_handle_otr_error(const char * const barejid, const char * const message);
unsigned long ui_get_idle_time(void);
void ui_reset_idle_time(void);
void ui_new_chat_win(const char * const barejid);
void ui_new_private_win(const char * const fulljid);
ProfPrivateWin* ui_new_private_win(const char * const fulljid);
ProfChatWin* ui_new_chat_win(const char * const barejid);
void ui_print_system_msg_from_recipient(const char * const barejid, const char *message);
gint ui_unread(void);
void ui_close_connected_win(int index);
@ -94,7 +95,6 @@ int ui_close_read_wins(void);
// current window actions
void ui_clear_current(void);
win_type_t ui_current_win_type(void);
int ui_current_win_index(void);
gboolean ui_current_win_is_otr(void);
ProfChatWin *ui_get_current_chat(void);
@ -102,27 +102,28 @@ ProfChatWin *ui_get_current_chat(void);
void ui_current_print_line(const char * const msg, ...);
void ui_current_print_formatted_line(const char show_char, int attrs, const char * const msg, ...);
void ui_current_error_line(const char * const msg);
void ui_win_error_line(ProfWin *window, const char * const msg);
win_type_t ui_win_type(int index);
void ui_close_win(int index);
gboolean ui_win_exists(int index);
int ui_win_unread(int index);
char * ui_ask_password(void);
void ui_handle_stanza(const char * const msg);
// ui events
void ui_contact_online(char *barejid, Resource *resource, GDateTime *last_activity);
void ui_contact_typing(const char * const barejid, const char * const resource);
void ui_incoming_msg(const char * const from, const char * const resource, const char * const message, GTimeVal *tv_stamp);
void ui_incoming_private_msg(const char * const fulljid, const char * const message, GTimeVal *tv_stamp);
void ui_message_receipt(const char * const barejid, const char * const id);
void ui_disconnected(void);
void ui_recipient_gone(const char * const barejid, const char * const resource);
void ui_outgoing_chat_msg(const char * const from, const char * const barejid,
const char * const message);
void ui_outgoing_private_msg(const char * const from, const char * const fulljid,
const char * const message);
void ui_outgoing_chat_msg(ProfChatWin *chatwin, const char * const message, char *id);
void ui_outgoing_chat_msg_carbon(const char * const barejid, const char * const message);
void ui_outgoing_private_msg(ProfPrivateWin *privwin, const char * const message);
void ui_room_join(const char * const roomjid, gboolean focus);
void ui_switch_to_room(const char * const roomjid);
@ -171,6 +172,7 @@ void ui_room_member_nick_change(const char * const roomjid,
void ui_room_nick_change(const char * const roomjid, const char * const nick);
void ui_room_member_presence(const char * const roomjid,
const char * const nick, const char * const show, const char * const status);
void ui_room_update_occupants(const char * const roomjid);
void ui_room_show_occupants(const char * const roomjid);
void ui_room_hide_occupants(const char * const roomjid);
void ui_show_roster(void);
@ -218,6 +220,11 @@ void ui_tidy_wins(void);
void ui_prune_wins(void);
gboolean ui_swap_wins(int source_win, int target_win);
void ui_page_up(void);
void ui_page_down(void);
void ui_subwin_page_up(void);
void ui_subwin_page_down(void);
void ui_auto_away(void);
void ui_end_auto_away(void);
void ui_titlebar_presence(contact_presence_t presence);
@ -227,9 +234,10 @@ void ui_update_presence(const resource_presence_t resource_presence,
void ui_about(void);
void ui_statusbar_new(const int win);
char * ui_readline(void);
char* ui_readline(void);
void ui_input_clear(void);
void ui_input_nonblocking(gboolean);
void ui_write(char *line, int offset);
void ui_invalid_command_usage(const char * const usage, void (*setting_func)(void));
@ -308,6 +316,8 @@ void cons_outtype_setting(void);
void cons_intype_setting(void);
void cons_gone_setting(void);
void cons_history_setting(void);
void cons_carbons_setting(void);
void cons_receipts_setting(void);
void cons_log_setting(void);
void cons_chlog_setting(void);
void cons_grlog_setting(void);
@ -332,7 +342,7 @@ void notifier_initialise(void);
void notifier_uninit(void);
void notify_typing(const char * const handle);
void notify_message(const char * const handle, int win, const char * const text);
void notify_message(ProfWin *window, const char * const name, const char * const text);
void notify_room_message(const char * const handle, const char * const room,
int win, const char * const text);
void notify_remind(void);

View File

@ -1,7 +1,7 @@
/*
* window.c
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*
@ -38,6 +38,7 @@
#include <string.h>
#include <time.h>
#include <assert.h>
#include <wchar.h>
#include <glib.h>
#ifdef HAVE_NCURSESW_NCURSES_H
@ -59,7 +60,7 @@
#define CEILING(X) (X-(int)(X) > 0 ? (int)(X+1) : (int)(X))
static void _win_print(ProfWin *window, const char show_char, GDateTime *time,
int flags, theme_item_t theme_item, const char * const from, const char * const message);
int flags, theme_item_t theme_item, const char * const from, const char * const message, DeliveryReceipt *receipt);
static void _win_print_wrapped(WINDOW *win, const char * const message);
int
@ -134,7 +135,7 @@ win_create_chat(const char * const barejid)
new_win->barejid = strdup(barejid);
new_win->resource_override = NULL;
new_win->is_otr = FALSE;
new_win->enc_mode = PROF_ENC_NONE;
new_win->is_trusted = FALSE;
new_win->history_shown = FALSE;
new_win->unread = 0;
@ -177,6 +178,11 @@ win_create_muc(const char * const roomjid)
new_win->roomjid = strdup(roomjid);
new_win->unread = 0;
if (prefs_get_boolean(PREF_OCCUPANTS_JID)) {
new_win->showjid = TRUE;
} else {
new_win->showjid = FALSE;
}
new_win->memcheck = PROFMUCWIN_MEMCHECK;
@ -331,12 +337,13 @@ win_free(ProfWin* window)
buffer_free(window->layout->buffer);
delwin(window->layout->win);
}
free(window->layout);
if (window->type == WIN_CHAT) {
ProfChatWin *chatwin = (ProfChatWin*)window;
free(chatwin->barejid);
free(chatwin->resource_override);
free(chatwin->state);
chat_state_free(chatwin->state);
}
if (window->type == WIN_MUC) {
@ -359,7 +366,101 @@ win_free(ProfWin* window)
}
void
win_handle_page(ProfWin *window, const wint_t ch, const int result)
win_page_up(ProfWin *window)
{
int rows = getmaxy(stdscr);
int y = getcury(window->layout->win);
int page_space = rows - 4;
int *page_start = &(window->layout->y_pos);
*page_start -= page_space;
// went past beginning, show first page
if (*page_start < 0)
*page_start = 0;
window->layout->paged = 1;
win_update_virtual(window);
// switch off page if last line and space line visible
if ((y) - *page_start == page_space) {
window->layout->paged = 0;
}
}
void
win_page_down(ProfWin *window)
{
int rows = getmaxy(stdscr);
int y = getcury(window->layout->win);
int page_space = rows - 4;
int *page_start = &(window->layout->y_pos);
*page_start += page_space;
// only got half a screen, show full screen
if ((y - (*page_start)) < page_space)
*page_start = y - page_space;
// went past end, show full screen
else if (*page_start >= y)
*page_start = y - page_space - 1;
window->layout->paged = 1;
win_update_virtual(window);
// switch off page if last line and space line visible
if ((y) - *page_start == page_space) {
window->layout->paged = 0;
}
}
void
win_sub_page_down(ProfWin *window)
{
if (window->layout->type == LAYOUT_SPLIT) {
int rows = getmaxy(stdscr);
int page_space = rows - 4;
ProfLayoutSplit *split_layout = (ProfLayoutSplit*)window->layout;
int sub_y = getcury(split_layout->subwin);
int *sub_y_pos = &(split_layout->sub_y_pos);
*sub_y_pos += page_space;
// only got half a screen, show full screen
if ((sub_y- (*sub_y_pos)) < page_space)
*sub_y_pos = sub_y - page_space;
// went past end, show full screen
else if (*sub_y_pos >= sub_y)
*sub_y_pos = sub_y - page_space - 1;
win_update_virtual(window);
}
}
void
win_sub_page_up(ProfWin *window)
{
if (window->layout->type == LAYOUT_SPLIT) {
int rows = getmaxy(stdscr);
int page_space = rows - 4;
ProfLayoutSplit *split_layout = (ProfLayoutSplit*)window->layout;
int *sub_y_pos = &(split_layout->sub_y_pos);
*sub_y_pos -= page_space;
// went past beginning, show first page
if (*sub_y_pos < 0)
*sub_y_pos = 0;
win_update_virtual(window);
}
}
void
win_mouse(ProfWin *window, const wint_t ch, const int result)
{
int rows = getmaxy(stdscr);
int y = getcury(window->layout->win);
@ -403,69 +504,6 @@ win_handle_page(ProfWin *window, const wint_t ch, const int result)
}
}
}
// page up
if (ch == KEY_PPAGE) {
*page_start -= page_space;
// went past beginning, show first page
if (*page_start < 0)
*page_start = 0;
window->layout->paged = 1;
win_update_virtual(window);
// page down
} else if (ch == KEY_NPAGE) {
*page_start += page_space;
// only got half a screen, show full screen
if ((y - (*page_start)) < page_space)
*page_start = y - page_space;
// went past end, show full screen
else if (*page_start >= y)
*page_start = y - page_space - 1;
window->layout->paged = 1;
win_update_virtual(window);
}
// switch off page if last line and space line visible
if ((y) - *page_start == page_space) {
window->layout->paged = 0;
}
if (window->layout->type == LAYOUT_SPLIT) {
ProfLayoutSplit *split_layout = (ProfLayoutSplit*)window->layout;
int sub_y = getcury(split_layout->subwin);
int *sub_y_pos = &(split_layout->sub_y_pos);
// alt up arrow
if ((result == KEY_CODE_YES) && ((ch == 565) || (ch == 337))) {
*sub_y_pos -= page_space;
// went past beginning, show first page
if (*sub_y_pos < 0)
*sub_y_pos = 0;
win_update_virtual(window);
// alt down arrow
} else if ((result == KEY_CODE_YES) && ((ch == 524) || (ch == 336))) {
*sub_y_pos += page_space;
// only got half a screen, show full screen
if ((sub_y- (*sub_y_pos)) < page_space)
*sub_y_pos = sub_y - page_space;
// went past end, show full screen
else if (*sub_y_pos >= sub_y)
*sub_y_pos = sub_y - page_space - 1;
win_update_virtual(window);
}
}
}
void
@ -515,14 +553,14 @@ win_show_occupant(ProfWin *window, Occupant *occupant)
theme_item_t presence_colour = theme_main_presence_attrs(presence_str);
win_save_print(window, '-', NULL, NO_EOL, presence_colour, "", occupant->nick);
win_save_vprint(window, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", " is %s", presence_str);
win_print(window, '-', NULL, NO_EOL, presence_colour, "", occupant->nick);
win_vprint(window, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", " is %s", presence_str);
if (occupant->status) {
win_save_vprint(window, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", ", \"%s\"", occupant->status);
win_vprint(window, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", ", \"%s\"", occupant->status);
}
win_save_print(window, '-', NULL, NO_DATE, presence_colour, "", "");
win_print(window, '-', NULL, NO_DATE, presence_colour, "", "");
}
void
@ -536,15 +574,15 @@ win_show_contact(ProfWin *window, PContact contact)
theme_item_t presence_colour = theme_main_presence_attrs(presence);
if (name != NULL) {
win_save_print(window, '-', NULL, NO_EOL, presence_colour, "", name);
if (name) {
win_print(window, '-', NULL, NO_EOL, presence_colour, "", name);
} else {
win_save_print(window, '-', NULL, NO_EOL, presence_colour, "", barejid);
win_print(window, '-', NULL, NO_EOL, presence_colour, "", barejid);
}
win_save_vprint(window, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", " is %s", presence);
win_vprint(window, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", " is %s", presence);
if (last_activity != NULL) {
if (last_activity) {
GDateTime *now = g_date_time_new_now_local();
GTimeSpan span = g_date_time_difference(now, last_activity);
@ -555,18 +593,18 @@ win_show_contact(ProfWin *window, PContact contact)
int seconds = span / G_TIME_SPAN_SECOND;
if (hours > 0) {
win_save_vprint(window, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", ", idle %dh%dm%ds", hours, minutes, seconds);
win_vprint(window, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", ", idle %dh%dm%ds", hours, minutes, seconds);
}
else {
win_save_vprint(window, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", ", idle %dm%ds", minutes, seconds);
win_vprint(window, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", ", idle %dm%ds", minutes, seconds);
}
}
if (status != NULL) {
win_save_vprint(window, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", ", \"%s\"", p_contact_status(contact));
if (status) {
win_vprint(window, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", ", \"%s\"", p_contact_status(contact));
}
win_save_print(window, '-', NULL, NO_DATE, presence_colour, "", "");
win_print(window, '-', NULL, NO_DATE, presence_colour, "", "");
}
void
@ -578,21 +616,21 @@ win_show_occupant_info(ProfWin *window, const char * const room, Occupant *occup
theme_item_t presence_colour = theme_main_presence_attrs(presence_str);
win_save_print(window, '!', NULL, NO_EOL, presence_colour, "", occupant->nick);
win_save_vprint(window, '!', NULL, NO_DATE | NO_EOL, presence_colour, "", " is %s", presence_str);
win_print(window, '!', NULL, NO_EOL, presence_colour, "", occupant->nick);
win_vprint(window, '!', NULL, NO_DATE | NO_EOL, presence_colour, "", " is %s", presence_str);
if (occupant->status) {
win_save_vprint(window, '!', NULL, NO_DATE | NO_EOL, presence_colour, "", ", \"%s\"", occupant->status);
win_vprint(window, '!', NULL, NO_DATE | NO_EOL, presence_colour, "", ", \"%s\"", occupant->status);
}
win_save_newline(window);
win_newline(window);
if (occupant->jid) {
win_save_vprint(window, '!', NULL, 0, 0, "", " Jid: %s", occupant->jid);
win_vprint(window, '!', NULL, 0, 0, "", " Jid: %s", occupant->jid);
}
win_save_vprint(window, '!', NULL, 0, 0, "", " Affiliation: %s", occupant_affiliation);
win_save_vprint(window, '!', NULL, 0, 0, "", " Role: %s", occupant_role);
win_vprint(window, '!', NULL, 0, 0, "", " Affiliation: %s", occupant_affiliation);
win_vprint(window, '!', NULL, 0, 0, "", " Role: %s", occupant_role);
Jid *jidp = jid_create_from_bare_and_resource(room, occupant->nick);
Capabilities *caps = caps_lookup(jidp->fulljid);
@ -600,47 +638,47 @@ win_show_occupant_info(ProfWin *window, const char * const room, Occupant *occup
if (caps) {
// show identity
if ((caps->category != NULL) || (caps->type != NULL) || (caps->name != NULL)) {
win_save_print(window, '!', NULL, NO_EOL, 0, "", " Identity: ");
if (caps->name != NULL) {
win_save_print(window, '!', NULL, NO_DATE | NO_EOL, 0, "", caps->name);
if ((caps->category != NULL) || (caps->type != NULL)) {
win_save_print(window, '-', NULL, NO_DATE | NO_EOL, 0, "", " ");
if (caps->category || caps->type || caps->name) {
win_print(window, '!', NULL, NO_EOL, 0, "", " Identity: ");
if (caps->name) {
win_print(window, '!', NULL, NO_DATE | NO_EOL, 0, "", caps->name);
if (caps->category || caps->type) {
win_print(window, '-', NULL, NO_DATE | NO_EOL, 0, "", " ");
}
}
if (caps->type != NULL) {
win_save_print(window, '!', NULL, NO_DATE | NO_EOL, 0, "", caps->type);
if (caps->category != NULL) {
win_save_print(window, '!', NULL, NO_DATE | NO_EOL, 0, "", " ");
if (caps->type) {
win_print(window, '!', NULL, NO_DATE | NO_EOL, 0, "", caps->type);
if (caps->category) {
win_print(window, '!', NULL, NO_DATE | NO_EOL, 0, "", " ");
}
}
if (caps->category != NULL) {
win_save_print(window, '!', NULL, NO_DATE | NO_EOL, 0, "", caps->category);
if (caps->category) {
win_print(window, '!', NULL, NO_DATE | NO_EOL, 0, "", caps->category);
}
win_save_newline(window);
win_newline(window);
}
if (caps->software != NULL) {
win_save_vprint(window, '!', NULL, NO_EOL, 0, "", " Software: %s", caps->software);
if (caps->software) {
win_vprint(window, '!', NULL, NO_EOL, 0, "", " Software: %s", caps->software);
}
if (caps->software_version != NULL) {
win_save_vprint(window, '!', NULL, NO_DATE | NO_EOL, 0, "", ", %s", caps->software_version);
if (caps->software_version) {
win_vprint(window, '!', NULL, NO_DATE | NO_EOL, 0, "", ", %s", caps->software_version);
}
if ((caps->software != NULL) || (caps->software_version != NULL)) {
win_save_newline(window);
if (caps->software || caps->software_version) {
win_newline(window);
}
if (caps->os != NULL) {
win_save_vprint(window, '!', NULL, NO_EOL, 0, "", " OS: %s", caps->os);
if (caps->os) {
win_vprint(window, '!', NULL, NO_EOL, 0, "", " OS: %s", caps->os);
}
if (caps->os_version != NULL) {
win_save_vprint(window, '!', NULL, NO_DATE | NO_EOL, 0, "", ", %s", caps->os_version);
if (caps->os_version) {
win_vprint(window, '!', NULL, NO_DATE | NO_EOL, 0, "", ", %s", caps->os_version);
}
if ((caps->os != NULL) || (caps->os_version != NULL)) {
win_save_newline(window);
if (caps->os || caps->os_version) {
win_newline(window);
}
caps_destroy(caps);
}
win_save_print(window, '-', NULL, 0, 0, "", "");
win_print(window, '-', NULL, 0, 0, "", "");
}
void
@ -650,24 +688,22 @@ win_show_info(ProfWin *window, PContact contact)
const char *name = p_contact_name(contact);
const char *presence = p_contact_presence(contact);
const char *sub = p_contact_subscription(contact);
GList *resources = p_contact_get_available_resources(contact);
GList *ordered_resources = NULL;
GDateTime *last_activity = p_contact_last_activity(contact);
theme_item_t presence_colour = theme_main_presence_attrs(presence);
win_save_print(window, '-', NULL, 0, 0, "", "");
win_save_print(window, '-', NULL, NO_EOL, presence_colour, "", barejid);
if (name != NULL) {
win_save_vprint(window, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", " (%s)", name);
win_print(window, '-', NULL, 0, 0, "", "");
win_print(window, '-', NULL, NO_EOL, presence_colour, "", barejid);
if (name) {
win_vprint(window, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", " (%s)", name);
}
win_save_print(window, '-', NULL, NO_DATE, 0, "", ":");
win_print(window, '-', NULL, NO_DATE, 0, "", ":");
if (sub != NULL) {
win_save_vprint(window, '-', NULL, 0, 0, "", "Subscription: %s", sub);
if (sub) {
win_vprint(window, '-', NULL, 0, 0, "", "Subscription: %s", sub);
}
if (last_activity != NULL) {
if (last_activity) {
GDateTime *now = g_date_time_new_now_local();
GTimeSpan span = g_date_time_difference(now, last_activity);
@ -678,36 +714,41 @@ win_show_info(ProfWin *window, PContact contact)
int seconds = span / G_TIME_SPAN_SECOND;
if (hours > 0) {
win_save_vprint(window, '-', NULL, 0, 0, "", "Last activity: %dh%dm%ds", hours, minutes, seconds);
win_vprint(window, '-', NULL, 0, 0, "", "Last activity: %dh%dm%ds", hours, minutes, seconds);
}
else {
win_save_vprint(window, '-', NULL, 0, 0, "", "Last activity: %dm%ds", minutes, seconds);
win_vprint(window, '-', NULL, 0, 0, "", "Last activity: %dm%ds", minutes, seconds);
}
g_date_time_unref(now);
}
if (resources != NULL) {
win_save_print(window, '-', NULL, 0, 0, "", "Resources:");
GList *resources = p_contact_get_available_resources(contact);
GList *ordered_resources = NULL;
if (resources) {
win_print(window, '-', NULL, 0, 0, "", "Resources:");
// sort in order of availabiltiy
while (resources != NULL) {
Resource *resource = resources->data;
// sort in order of availability
GList *curr = resources;
while (curr) {
Resource *resource = curr->data;
ordered_resources = g_list_insert_sorted(ordered_resources,
resource, (GCompareFunc)resource_compare_availability);
resources = g_list_next(resources);
curr = g_list_next(curr);
}
}
g_list_free(resources);
while (ordered_resources != NULL) {
Resource *resource = ordered_resources->data;
GList *curr = ordered_resources;
while (curr) {
Resource *resource = curr->data;
const char *resource_presence = string_from_resource_presence(resource->presence);
theme_item_t presence_colour = theme_main_presence_attrs(resource_presence);
win_save_vprint(window, '-', NULL, NO_EOL, presence_colour, "", " %s (%d), %s", resource->name, resource->priority, resource_presence);
if (resource->status != NULL) {
win_save_vprint(window, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", ", \"%s\"", resource->status);
win_vprint(window, '-', NULL, NO_EOL, presence_colour, "", " %s (%d), %s", resource->name, resource->priority, resource_presence);
if (resource->status) {
win_vprint(window, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", ", \"%s\"", resource->status);
}
win_save_newline(window);
win_newline(window);
Jid *jidp = jid_create_from_bare_and_resource(barejid, resource->name);
Capabilities *caps = caps_lookup(jidp->fulljid);
@ -715,48 +756,49 @@ win_show_info(ProfWin *window, PContact contact)
if (caps) {
// show identity
if ((caps->category != NULL) || (caps->type != NULL) || (caps->name != NULL)) {
win_save_print(window, '-', NULL, NO_EOL, 0, "", " Identity: ");
if (caps->name != NULL) {
win_save_print(window, '-', NULL, NO_DATE | NO_EOL, 0, "", caps->name);
if ((caps->category != NULL) || (caps->type != NULL)) {
win_save_print(window, '-', NULL, NO_DATE | NO_EOL, 0, "", " ");
if (caps->category || caps->type || caps->name) {
win_print(window, '-', NULL, NO_EOL, 0, "", " Identity: ");
if (caps->name) {
win_print(window, '-', NULL, NO_DATE | NO_EOL, 0, "", caps->name);
if (caps->category || caps->type) {
win_print(window, '-', NULL, NO_DATE | NO_EOL, 0, "", " ");
}
}
if (caps->type != NULL) {
win_save_print(window, '-', NULL, NO_DATE | NO_EOL, 0, "", caps->type);
if (caps->category != NULL) {
win_save_print(window, '-', NULL, NO_DATE | NO_EOL, 0, "", " ");
if (caps->type) {
win_print(window, '-', NULL, NO_DATE | NO_EOL, 0, "", caps->type);
if (caps->category) {
win_print(window, '-', NULL, NO_DATE | NO_EOL, 0, "", " ");
}
}
if (caps->category != NULL) {
win_save_print(window, '-', NULL, NO_DATE | NO_EOL, 0, "", caps->category);
if (caps->category) {
win_print(window, '-', NULL, NO_DATE | NO_EOL, 0, "", caps->category);
}
win_save_newline(window);
win_newline(window);
}
if (caps->software != NULL) {
win_save_vprint(window, '-', NULL, NO_EOL, 0, "", " Software: %s", caps->software);
if (caps->software) {
win_vprint(window, '-', NULL, NO_EOL, 0, "", " Software: %s", caps->software);
}
if (caps->software_version != NULL) {
win_save_vprint(window, '-', NULL, NO_DATE | NO_EOL, 0, "", ", %s", caps->software_version);
if (caps->software_version) {
win_vprint(window, '-', NULL, NO_DATE | NO_EOL, 0, "", ", %s", caps->software_version);
}
if ((caps->software != NULL) || (caps->software_version != NULL)) {
win_save_newline(window);
if (caps->software || caps->software_version) {
win_newline(window);
}
if (caps->os != NULL) {
win_save_vprint(window, '-', NULL, NO_EOL, 0, "", " OS: %s", caps->os);
if (caps->os) {
win_vprint(window, '-', NULL, NO_EOL, 0, "", " OS: %s", caps->os);
}
if (caps->os_version != NULL) {
win_save_vprint(window, '-', NULL, NO_DATE | NO_EOL, 0, "", ", %s", caps->os_version);
if (caps->os_version) {
win_vprint(window, '-', NULL, NO_DATE | NO_EOL, 0, "", ", %s", caps->os_version);
}
if ((caps->os != NULL) || (caps->os_version != NULL)) {
win_save_newline(window);
if (caps->os || caps->os_version) {
win_newline(window);
}
caps_destroy(caps);
}
ordered_resources = g_list_next(ordered_resources);
curr = g_list_next(curr);
}
g_list_free(ordered_resources);
}
void
@ -767,7 +809,7 @@ win_show_status_string(ProfWin *window, const char * const from,
{
theme_item_t presence_colour;
if (show != NULL) {
if (show) {
presence_colour = theme_main_presence_attrs(show);
} else if (strcmp(default_show, "online") == 0) {
presence_colour = THEME_ONLINE;
@ -776,14 +818,14 @@ win_show_status_string(ProfWin *window, const char * const from,
}
win_save_vprint(window, '-', NULL, NO_EOL, presence_colour, "", "%s %s", pre, from);
win_vprint(window, '-', NULL, NO_EOL, presence_colour, "", "%s %s", pre, from);
if (show != NULL)
win_save_vprint(window, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", " is %s", show);
if (show)
win_vprint(window, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", " is %s", show);
else
win_save_vprint(window, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", " is %s", default_show);
win_vprint(window, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", " is %s", default_show);
if (last_activity != NULL) {
if (last_activity) {
GDateTime *now = g_date_time_new_now_local();
GTimeSpan span = g_date_time_difference(now, last_activity);
g_date_time_unref(now);
@ -795,17 +837,17 @@ win_show_status_string(ProfWin *window, const char * const from,
int seconds = span / G_TIME_SPAN_SECOND;
if (hours > 0) {
win_save_vprint(window, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", ", idle %dh%dm%ds", hours, minutes, seconds);
win_vprint(window, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", ", idle %dh%dm%ds", hours, minutes, seconds);
}
else {
win_save_vprint(window, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", ", idle %dm%ds", minutes, seconds);
win_vprint(window, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", ", idle %dm%ds", minutes, seconds);
}
}
if (status != NULL)
win_save_vprint(window, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", ", \"%s\"", status);
if (status)
win_vprint(window, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", ", \"%s\"", status);
win_save_print(window, '-', NULL, NO_DATE, presence_colour, "", "");
win_print(window, '-', NULL, NO_DATE, presence_colour, "", "");
}
@ -817,7 +859,7 @@ win_print_incoming_message(ProfWin *window, GTimeVal *tv_stamp,
{
case WIN_CHAT:
case WIN_PRIVATE:
win_save_print(window, '-', tv_stamp, NO_ME, THEME_TEXT_THEM, from, message);
win_print(window, '-', tv_stamp, NO_ME, THEME_TEXT_THEM, from, message);
break;
default:
assert(FALSE);
@ -826,19 +868,19 @@ win_print_incoming_message(ProfWin *window, GTimeVal *tv_stamp,
}
void
win_save_vprint(ProfWin *window, const char show_char, GTimeVal *tstamp,
win_vprint(ProfWin *window, const char show_char, GTimeVal *tstamp,
int flags, theme_item_t theme_item, const char * const from, const char * const message, ...)
{
va_list arg;
va_start(arg, message);
GString *fmt_msg = g_string_new(NULL);
g_string_vprintf(fmt_msg, message, arg);
win_save_print(window, show_char, tstamp, flags, theme_item, from, fmt_msg->str);
win_print(window, show_char, tstamp, flags, theme_item, from, fmt_msg->str);
g_string_free(fmt_msg, TRUE);
}
void
win_save_print(ProfWin *window, const char show_char, GTimeVal *tstamp,
win_print(ProfWin *window, const char show_char, GTimeVal *tstamp,
int flags, theme_item_t theme_item, const char * const from, const char * const message)
{
GDateTime *time;
@ -849,27 +891,58 @@ win_save_print(ProfWin *window, const char show_char, GTimeVal *tstamp,
time = g_date_time_new_from_timeval_utc(tstamp);
}
buffer_push(window->layout->buffer, show_char, time, flags, theme_item, from, message);
_win_print(window, show_char, time, flags, theme_item, from, message);
buffer_push(window->layout->buffer, show_char, time, flags, theme_item, from, message, NULL);
_win_print(window, show_char, time, flags, theme_item, from, message, NULL);
// TODO: cross-reference.. this should be replaced by a real event-based system
ui_input_nonblocking(TRUE);
}
void
win_save_println(ProfWin *window, const char * const message)
win_print_with_receipt(ProfWin *window, const char show_char, GTimeVal *tstamp,
int flags, theme_item_t theme_item, const char * const from, const char * const message, char *id)
{
win_save_print(window, '-', NULL, 0, 0, "", message);
GDateTime *time;
if (tstamp == NULL) {
time = g_date_time_new_now_local();
} else {
time = g_date_time_new_from_timeval_utc(tstamp);
}
DeliveryReceipt *receipt = malloc(sizeof(struct delivery_receipt_t));
receipt->id = strdup(id);
receipt->received = FALSE;
buffer_push(window->layout->buffer, show_char, time, flags, theme_item, from, message, receipt);
_win_print(window, show_char, time, flags, theme_item, from, message, receipt);
// TODO: cross-reference.. this should be replaced by a real event-based system
ui_input_nonblocking(TRUE);
}
void
win_save_newline(ProfWin *window)
win_mark_received(ProfWin *window, const char * const id)
{
win_save_print(window, '-', NULL, NO_DATE, 0, "", "");
gboolean received = buffer_mark_received(window->layout->buffer, id);
if (received) {
win_redraw(window);
}
}
void
win_println(ProfWin *window, const char * const message)
{
win_print(window, '-', NULL, 0, 0, "", message);
}
void
win_newline(ProfWin *window)
{
win_print(window, '-', NULL, NO_DATE, 0, "", "");
}
static void
_win_print(ProfWin *window, const char show_char, GDateTime *time,
int flags, theme_item_t theme_item, const char * const from, const char * const message)
int flags, theme_item_t theme_item, const char * const from, const char * const message, DeliveryReceipt *receipt)
{
// flags : 1st bit = 0/1 - me/not me
// 2nd bit = 0/1 - date/no date
@ -907,6 +980,10 @@ _win_print(ProfWin *window, const char show_char, GDateTime *time,
colour = 0;
}
if (receipt && !receipt->received) {
colour = theme_attrs(THEME_RECEIPT_SENT);
}
wattron(window->layout->win, colour);
if (strncmp(message, "/me ", 4) == 0) {
wprintw(window->layout->win, "*%s ", from);
@ -919,7 +996,11 @@ _win_print(ProfWin *window, const char show_char, GDateTime *time,
}
if (!me_message) {
wattron(window->layout->win, theme_attrs(theme_item));
if (receipt && !receipt->received) {
wattron(window->layout->win, theme_attrs(THEME_RECEIPT_SENT));
} else {
wattron(window->layout->win, theme_attrs(theme_item));
}
}
if (prefs_get_boolean(PREF_WRAP)) {
@ -935,7 +1016,11 @@ _win_print(ProfWin *window, const char show_char, GDateTime *time,
if (me_message) {
wattroff(window->layout->win, colour);
} else {
wattroff(window->layout->win, theme_attrs(theme_item));
if (receipt && !receipt->received) {
wattroff(window->layout->win, theme_attrs(THEME_RECEIPT_SENT));
} else {
wattroff(window->layout->win, theme_attrs(theme_item));
}
}
}
@ -951,7 +1036,6 @@ _win_indent(WINDOW *win, int size)
static void
_win_print_wrapped(WINDOW *win, const char * const message)
{
int linei = 0;
int wordi = 0;
char *word = malloc(strlen(message) + 1);
@ -964,18 +1048,26 @@ _win_print_wrapped(WINDOW *win, const char * const message)
}
free(time_pref);
while (message[linei] != '\0') {
if (message[linei] == ' ') {
gchar *curr_ch = g_utf8_offset_to_pointer(message, 0);
while (*curr_ch != '\0') {
if (*curr_ch == ' ') {
waddch(win, ' ');
linei++;
} else if (message[linei] == '\n') {
curr_ch = g_utf8_next_char(curr_ch);
} else if (*curr_ch == '\n') {
waddch(win, '\n');
_win_indent(win, indent);
linei++;
curr_ch = g_utf8_next_char(curr_ch);
} else {
// get word
wordi = 0;
while (message[linei] != ' ' && message[linei] != '\n' && message[linei] != '\0') {
word[wordi++] = message[linei++];
while (*curr_ch != ' ' && *curr_ch != '\n' && *curr_ch != '\0') {
size_t ch_len = mbrlen(curr_ch, 4, NULL);
int offset = 0;
while (offset < ch_len) {
word[wordi++] = curr_ch[offset++];
}
curr_ch = g_utf8_next_char(curr_ch);
}
word[wordi] = '\0';
@ -983,17 +1075,27 @@ _win_print_wrapped(WINDOW *win, const char * const message)
int maxx = getmaxx(win);
// word larger than line
if (strlen(word) > (maxx - indent)) {
int i;
for (i = 0; i < wordi; i++) {
if (utf8_display_len(word) > (maxx - indent)) {
gchar *word_ch = g_utf8_offset_to_pointer(word, 0);
while(*word_ch != '\0') {
curx = getcurx(win);
if (curx < indent) {
_win_indent(win, indent);
}
waddch(win, word[i]);
gchar copy[wordi++];
g_utf8_strncpy(copy, word_ch, 1);
if (curx + utf8_display_len(copy) > maxx) {
waddch(win, '\n');
_win_indent(win, indent);
}
waddstr(win, copy);
word_ch = g_utf8_next_char(word_ch);
}
} else {
if (curx + strlen(word) > maxx) {
if (curx + utf8_display_len(word) > maxx) {
waddch(win, '\n');
_win_indent(win, indent);
}
@ -1017,7 +1119,7 @@ win_redraw(ProfWin *window)
for (i = 0; i < size; i++) {
ProfBuffEntry *e = buffer_yield_entry(window->layout->buffer, i);
_win_print(window, e->show_char, e->time, e->flags, e->theme_item, e->from, e->message);
_win_print(window, e->show_char, e->time, e->flags, e->theme_item, e->from, e->message, e->receipt);
}
}

View File

@ -1,7 +1,7 @@
/*
* window.h
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*
@ -99,6 +99,11 @@ typedef enum {
WIN_XML
} win_type_t;
typedef enum {
PROF_ENC_NONE,
PROF_ENC_OTR
} prof_enc_t;
typedef struct prof_win_t {
win_type_t type;
ProfLayout *layout;
@ -113,7 +118,7 @@ typedef struct prof_chat_win_t {
char *barejid;
int unread;
ChatState *state;
gboolean is_otr;
prof_enc_t enc_mode;
gboolean is_trusted;
char *resource_override;
gboolean history_shown;
@ -124,6 +129,7 @@ typedef struct prof_muc_win_t {
ProfWin window;
char *roomjid;
int unread;
gboolean showjid;
unsigned long memcheck;
} ProfMucWin;
@ -168,19 +174,27 @@ void win_print_incoming_message(ProfWin *window, GTimeVal *tv_stamp,
const char * const from, const char * const message);
void win_show_info(ProfWin *window, PContact contact);
void win_show_occupant_info(ProfWin *window, const char * const room, Occupant *occupant);
void win_save_vprint(ProfWin *window, const char show_char, GTimeVal *tstamp, int flags, theme_item_t theme_item, const char * const from, const char * const message, ...);
void win_save_print(ProfWin *window, const char show_char, GTimeVal *tstamp, int flags, theme_item_t theme_item, const char * const from, const char * const message);
void win_save_println(ProfWin *window, const char * const message);
void win_save_newline(ProfWin *window);
void win_vprint(ProfWin *window, const char show_char, GTimeVal *tstamp, int flags, theme_item_t theme_item, const char * const from, const char * const message, ...);
void win_print(ProfWin *window, const char show_char, GTimeVal *tstamp, int flags, theme_item_t theme_item, const char * const from, const char * const message);
void win_print_with_receipt(ProfWin *window, const char show_char, GTimeVal *tstamp, int flags,
theme_item_t theme_item, const char * const from, const char * const message, char *id);
void win_println(ProfWin *window, const char * const message);
void win_newline(ProfWin *window);
void win_redraw(ProfWin *window);
void win_hide_subwin(ProfWin *window);
void win_show_subwin(ProfWin *window);
int win_roster_cols(void);
int win_occpuants_cols(void);
void win_printline_nowrap(WINDOW *win, char *msg);
void win_handle_page(ProfWin *current, const wint_t ch, const int result);
void win_mouse(ProfWin *current, const wint_t ch, const int result);
void win_mark_received(ProfWin *window, const char * const id);
int win_unread(ProfWin *window);
gboolean win_has_active_subwin(ProfWin *window);
void win_page_up(ProfWin *window);
void win_page_down(ProfWin *window);
void win_sub_page_down(ProfWin *window);
void win_sub_page_up(ProfWin *window);
#endif

View File

@ -1,7 +1,7 @@
/*
* windows.c
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*
@ -53,6 +53,7 @@
#include "ui/statusbar.h"
#include "ui/window.h"
#include "ui/windows.h"
#include "event/ui_events.h"
static GHashTable *windows;
static int current;
@ -83,7 +84,7 @@ wins_get_chat(const char * const barejid)
GList *values = g_hash_table_get_values(windows);
GList *curr = values;
while (curr != NULL) {
while (curr) {
ProfWin *window = curr->data;
if (window->type == WIN_CHAT) {
ProfChatWin *chatwin = (ProfChatWin*)window;
@ -105,7 +106,7 @@ wins_get_muc_conf(const char * const roomjid)
GList *values = g_hash_table_get_values(windows);
GList *curr = values;
while (curr != NULL) {
while (curr) {
ProfWin *window = curr->data;
if (window->type == WIN_MUC_CONFIG) {
ProfMucConfWin *confwin = (ProfMucConfWin*)window;
@ -127,11 +128,12 @@ wins_get_muc(const char * const roomjid)
GList *values = g_hash_table_get_values(windows);
GList *curr = values;
while (curr != NULL) {
while (curr) {
ProfWin *window = curr->data;
if (window->type == WIN_MUC) {
ProfMucWin *mucwin = (ProfMucWin*)window;
if (g_strcmp0(mucwin->roomjid, roomjid) == 0) {
g_list_free(values);
return mucwin;
}
}
@ -148,11 +150,12 @@ wins_get_private(const char * const fulljid)
GList *values = g_hash_table_get_values(windows);
GList *curr = values;
while (curr != NULL) {
while (curr) {
ProfWin *window = curr->data;
if (window->type == WIN_PRIVATE) {
ProfPrivateWin *privatewin = (ProfPrivateWin*)window;
if (g_strcmp0(privatewin->fulljid, fulljid) == 0) {
g_list_free(values);
return privatewin;
}
}
@ -166,7 +169,7 @@ wins_get_private(const char * const fulljid)
ProfWin *
wins_get_current(void)
{
if (windows != NULL) {
if (windows) {
return g_hash_table_lookup(windows, GINT_TO_POINTER(current));
} else {
return NULL;
@ -283,7 +286,7 @@ wins_get_next(void)
GList *curr = keys;
// find our place in the list
while (curr != NULL) {
while (curr) {
if (current == GPOINTER_TO_INT(curr->data)) {
break;
}
@ -292,7 +295,7 @@ wins_get_next(void)
// if there is a next window return it
curr = g_list_next(curr);
if (curr != NULL) {
if (curr) {
int next = GPOINTER_TO_INT(curr->data);
g_list_free(keys);
return wins_get_by_num(next);
@ -312,7 +315,7 @@ wins_get_previous(void)
GList *curr = keys;
// find our place in the list
while (curr != NULL) {
while (curr) {
if (current == GPOINTER_TO_INT(curr->data)) {
break;
}
@ -321,7 +324,7 @@ wins_get_previous(void)
// if there is a previous window return it
curr = g_list_previous(curr);
if (curr != NULL) {
if (curr) {
int previous = GPOINTER_TO_INT(curr->data);
g_list_free(keys);
return wins_get_by_num(previous);
@ -339,7 +342,7 @@ wins_get_num(ProfWin *window)
GList *keys = g_hash_table_get_keys(windows);
GList *curr = keys;
while (curr != NULL) {
while (curr) {
gconstpointer num_p = curr->data;
ProfWin *curr_win = g_hash_table_lookup(windows, num_p);
if (curr_win == window) {
@ -408,9 +411,9 @@ wins_new_xmlconsole(void)
{
GList *keys = g_hash_table_get_keys(windows);
int result = get_next_available_win_num(keys);
g_list_free(keys);
ProfWin *newwin = win_create_xmlconsole();
g_hash_table_insert(windows, GINT_TO_POINTER(result), newwin);
g_list_free(keys);
return newwin;
}
@ -419,9 +422,9 @@ wins_new_chat(const char * const barejid)
{
GList *keys = g_hash_table_get_keys(windows);
int result = get_next_available_win_num(keys);
g_list_free(keys);
ProfWin *newwin = win_create_chat(barejid);
g_hash_table_insert(windows, GINT_TO_POINTER(result), newwin);
g_list_free(keys);
return newwin;
}
@ -430,9 +433,9 @@ wins_new_muc(const char * const roomjid)
{
GList *keys = g_hash_table_get_keys(windows);
int result = get_next_available_win_num(keys);
g_list_free(keys);
ProfWin *newwin = win_create_muc(roomjid);
g_hash_table_insert(windows, GINT_TO_POINTER(result), newwin);
g_list_free(keys);
return newwin;
}
@ -441,9 +444,9 @@ wins_new_muc_config(const char * const roomjid, DataForm *form)
{
GList *keys = g_hash_table_get_keys(windows);
int result = get_next_available_win_num(keys);
g_list_free(keys);
ProfWin *newwin = win_create_muc_config(roomjid, form);
g_hash_table_insert(windows, GINT_TO_POINTER(result), newwin);
g_list_free(keys);
return newwin;
}
@ -452,9 +455,9 @@ wins_new_private(const char * const fulljid)
{
GList *keys = g_hash_table_get_keys(windows);
int result = get_next_available_win_num(keys);
g_list_free(keys);
ProfWin *newwin = win_create_private(fulljid);
g_hash_table_insert(windows, GINT_TO_POINTER(result), newwin);
g_list_free(keys);
return newwin;
}
@ -465,7 +468,7 @@ wins_get_total_unread(void)
GList *values = g_hash_table_get_values(windows);
GList *curr = values;
while (curr != NULL) {
while (curr) {
ProfWin *window = curr->data;
result += win_unread(window);
curr = g_list_next(curr);
@ -481,7 +484,7 @@ wins_resize_all(void)
GList *values = g_hash_table_get_values(windows);
GList *curr = values;
while (curr != NULL) {
while (curr) {
ProfWin *window = curr->data;
int subwin_cols = 0;
@ -495,7 +498,13 @@ wins_resize_all(void)
}
wresize(layout->base.win, PAD_SIZE, cols - subwin_cols);
wresize(layout->subwin, PAD_SIZE, subwin_cols);
rosterwin_roster();
if (window->type == WIN_CONSOLE) {
rosterwin_roster();
} else if (window->type == WIN_MUC) {
ProfMucWin *mucwin = (ProfMucWin *)window;
assert(mucwin->memcheck == PROFMUCWIN_MEMCHECK);
occupantswin_occupants(mucwin->roomjid);
}
} else {
wresize(layout->base.win, PAD_SIZE, cols);
}
@ -555,7 +564,7 @@ wins_get_xmlconsole(void)
GList *values = g_hash_table_get_values(windows);
GList *curr = values;
while (curr != NULL) {
while (curr) {
ProfWin *window = curr->data;
if (window->type == WIN_XML) {
ProfXMLWin *xmlwin = (ProfXMLWin*)window;
@ -577,7 +586,7 @@ wins_get_chat_recipients(void)
GList *values = g_hash_table_get_values(windows);
GList *curr = values;
while (curr != NULL) {
while (curr) {
ProfWin *window = curr->data;
if (window->type == WIN_CHAT) {
ProfChatWin *chatwin = (ProfChatWin*)window;
@ -596,7 +605,7 @@ wins_get_prune_wins(void)
GList *values = g_hash_table_get_values(windows);
GList *curr = values;
while (curr != NULL) {
while (curr) {
ProfWin *window = curr->data;
if (win_unread(window) == 0 &&
window->type != WIN_MUC &&
@ -617,10 +626,10 @@ wins_lost_connection(void)
GList *values = g_hash_table_get_values(windows);
GList *curr = values;
while (curr != NULL) {
while (curr) {
ProfWin *window = curr->data;
if (window->type != WIN_CONSOLE) {
win_save_print(window, '-', NULL, 0, THEME_ERROR, "", "Lost connection.");
win_print(window, '-', NULL, 0, THEME_ERROR, "", "Lost connection.");
// if current win, set current_win_dirty
if (wins_is_current(window)) {
@ -636,22 +645,24 @@ gboolean
wins_swap(int source_win, int target_win)
{
ProfWin *source = g_hash_table_lookup(windows, GINT_TO_POINTER(source_win));
ProfWin *console = wins_get_console();
if (source != NULL) {
if (source) {
ProfWin *target = g_hash_table_lookup(windows, GINT_TO_POINTER(target_win));
// target window empty
if (target == NULL) {
if (!target) {
g_hash_table_steal(windows, GINT_TO_POINTER(source_win));
status_bar_inactive(source_win);
g_hash_table_insert(windows, GINT_TO_POINTER(target_win), source);
status_bar_inactive(source_win);
if (win_unread(source) > 0) {
status_bar_new(target_win);
} else {
status_bar_active(target_win);
}
if ((wins_get_current_num() == source_win) || (wins_get_current_num() == target_win)) {
ui_switch_win(1);
if (wins_get_current_num() == source_win) {
wins_set_current_by_num(target_win);
ui_ev_focus_win(console);
}
return TRUE;
@ -672,7 +683,7 @@ wins_swap(int source_win, int target_win)
status_bar_active(source_win);
}
if ((wins_get_current_num() == source_win) || (wins_get_current_num() == target_win)) {
ui_switch_win(1);
ui_ev_focus_win(console);
}
return TRUE;
}
@ -708,7 +719,7 @@ wins_tidy(void)
int num = 1;
GList *curr = keys;
while (curr != NULL) {
while (curr) {
ProfWin *window = g_hash_table_lookup(windows, curr->data);
if (num == 10) {
g_hash_table_insert(new_windows, GINT_TO_POINTER(0), window);
@ -731,7 +742,8 @@ wins_tidy(void)
windows = new_windows;
current = 1;
ui_switch_win(1);
ProfWin *console = wins_get_console();
ui_ev_focus_win(console);
g_list_free(keys);
return TRUE;
} else {
@ -749,7 +761,7 @@ wins_create_summary(void)
keys = g_list_sort(keys, cmp_win_num);
GList *curr = keys;
while (curr != NULL) {
while (curr) {
ProfWin *window = g_hash_table_lookup(windows, curr->data);
int ui_index = GPOINTER_TO_INT(curr->data);

View File

@ -1,7 +1,7 @@
/*
* windows.h
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*

View File

@ -1,7 +1,7 @@
/*
* bookmark.c
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*
@ -42,7 +42,7 @@
#include "common.h"
#include "log.h"
#include "muc.h"
#include "server_events.h"
#include "event/server_events.h"
#include "xmpp/connection.h"
#include "xmpp/stanza.h"
#include "xmpp/xmpp.h"
@ -74,7 +74,7 @@ bookmark_request(void)
autocomplete_free(bookmark_ac);
bookmark_ac = autocomplete_new();
if (bookmark_list != NULL) {
if (bookmark_list) {
g_list_free_full(bookmark_list, _bookmark_item_destroy);
bookmark_list = NULL;
}
@ -96,12 +96,12 @@ bookmark_add(const char *jid, const char *nick, const char *password, const char
} else {
Bookmark *item = malloc(sizeof(*item));
item->jid = strdup(jid);
if (nick != NULL) {
if (nick) {
item->nick = strdup(nick);
} else {
item->nick = NULL;
}
if (password != NULL) {
if (password) {
item->password = strdup(password);
} else {
item->password = NULL;
@ -136,15 +136,15 @@ bookmark_update(const char *jid, const char *nick, const char *password, const c
return FALSE;
} else {
Bookmark *bm = found->data;
if (nick != NULL) {
if (nick) {
free(bm->nick);
bm->nick = strdup(nick);
}
if (password != NULL) {
if (password) {
free(bm->password);
bm->password = strdup(password);
}
if (autojoin_str != NULL) {
if (autojoin_str) {
if (g_strcmp0(autojoin_str, "on") == 0) {
bm->autojoin = TRUE;
} else if (g_strcmp0(autojoin_str, "off") == 0) {
@ -228,7 +228,7 @@ bookmark_find(const char * const search_str)
void
bookmark_autocomplete_reset(void)
{
if (bookmark_ac != NULL) {
if (bookmark_ac) {
autocomplete_reset(bookmark_ac);
}
}
@ -413,14 +413,14 @@ _send_bookmarks(void)
xmpp_stanza_set_ns(storage, "storage:bookmarks");
GList *curr = bookmark_list;
while (curr != NULL) {
while (curr) {
Bookmark *bookmark = curr->data;
xmpp_stanza_t *conference = xmpp_stanza_new(ctx);
xmpp_stanza_set_name(conference, STANZA_NAME_CONFERENCE);
xmpp_stanza_set_attribute(conference, STANZA_ATTR_JID, bookmark->jid);
Jid *jidp = jid_create(bookmark->jid);
if (jidp->localpart != NULL) {
if (jidp->localpart) {
xmpp_stanza_set_attribute(conference, STANZA_ATTR_NAME, jidp->localpart);
}
jid_destroy(jidp);
@ -431,7 +431,7 @@ _send_bookmarks(void)
xmpp_stanza_set_attribute(conference, STANZA_ATTR_AUTOJOIN, "false");
}
if (bookmark->nick != NULL) {
if (bookmark->nick) {
xmpp_stanza_t *nick_st = xmpp_stanza_new(ctx);
xmpp_stanza_set_name(nick_st, STANZA_NAME_NICK);
xmpp_stanza_t *nick_text = xmpp_stanza_new(ctx);
@ -443,7 +443,7 @@ _send_bookmarks(void)
xmpp_stanza_release(nick_st);
}
if (bookmark->password != NULL) {
if (bookmark->password) {
xmpp_stanza_t *password_st = xmpp_stanza_new(ctx);
xmpp_stanza_set_name(password_st, STANZA_NAME_PASSWORD);
xmpp_stanza_t *password_text = xmpp_stanza_new(ctx);

View File

@ -1,7 +1,7 @@
/*
* bookmark.h
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*

View File

@ -1,7 +1,7 @@
/*
* capabilities.c
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*
@ -154,56 +154,56 @@ _caps_by_ver(const char * const ver)
char *category = g_key_file_get_string(cache, ver, "category", NULL);
if (category) {
new_caps->category = strdup(category);
new_caps->category = category;
} else {
new_caps->category = NULL;
}
char *type = g_key_file_get_string(cache, ver, "type", NULL);
if (type) {
new_caps->type = strdup(type);
new_caps->type = type;
} else {
new_caps->type = NULL;
}
char *name = g_key_file_get_string(cache, ver, "name", NULL);
if (name) {
new_caps->name = strdup(name);
new_caps->name = name;
} else {
new_caps->name = NULL;
}
char *software = g_key_file_get_string(cache, ver, "software", NULL);
if (software) {
new_caps->software = strdup(software);
new_caps->software = software;
} else {
new_caps->software = NULL;
}
char *software_version = g_key_file_get_string(cache, ver, "software_version", NULL);
if (software_version) {
new_caps->software_version = strdup(software_version);
new_caps->software_version = software_version;
} else {
new_caps->software_version = NULL;
}
char *os = g_key_file_get_string(cache, ver, "os", NULL);
if (os) {
new_caps->os = strdup(os);
new_caps->os = os;
} else {
new_caps->os = NULL;
}
char *os_version = g_key_file_get_string(cache, ver, "os_version", NULL);
if (os_version) {
new_caps->os_version = strdup(os_version);
new_caps->os_version = os_version;
} else {
new_caps->os_version = NULL;
}
gsize features_len = 0;
gchar **features = g_key_file_get_string_list(cache, ver, "features", &features_len, NULL);
if (features != NULL && features_len > 0) {
if (features && features_len > 0) {
GSList *features_list = NULL;
int i;
for (i = 0; i < features_len; i++) {
@ -395,16 +395,16 @@ caps_create(xmpp_stanza_t *query)
GSList *features = NULL;
xmpp_stanza_t *softwareinfo = xmpp_stanza_get_child_by_ns(query, STANZA_NS_DATA);
if (softwareinfo != NULL) {
if (softwareinfo) {
DataForm *form = form_create(softwareinfo);
FormField *formField = NULL;
char *form_type = form_get_form_type_field(form);
if (g_strcmp0(form_type, STANZA_DATAFORM_SOFTWARE) == 0) {
GSList *field = form->fields;
while (field != NULL) {
while (field) {
formField = field->data;
if (formField->values != NULL) {
if (formField->values) {
if (strcmp(formField->var, "software") == 0) {
software = strdup(formField->values->data);
} else if (strcmp(formField->var, "software_version") == 0) {
@ -424,7 +424,7 @@ caps_create(xmpp_stanza_t *query)
xmpp_stanza_t *child = xmpp_stanza_get_children(query);
GSList *identity_stanzas = NULL;
while (child != NULL) {
while (child) {
if (g_strcmp0(xmpp_stanza_get_name(child), "feature") == 0) {
features = g_slist_append(features, strdup(xmpp_stanza_get_attribute(child, "var")));
}
@ -490,42 +490,42 @@ caps_create(xmpp_stanza_t *query)
Capabilities *new_caps = malloc(sizeof(struct capabilities_t));
if (category != NULL) {
if (category) {
new_caps->category = strdup(category);
} else {
new_caps->category = NULL;
}
if (type != NULL) {
if (type) {
new_caps->type = strdup(type);
} else {
new_caps->type = NULL;
}
if (name != NULL) {
if (name) {
new_caps->name = strdup(name);
} else {
new_caps->name = NULL;
}
if (software != NULL) {
if (software) {
new_caps->software = software;
} else {
new_caps->software = NULL;
}
if (software_version != NULL) {
if (software_version) {
new_caps->software_version = software_version;
} else {
new_caps->software_version = NULL;
}
if (os != NULL) {
if (os) {
new_caps->os = os;
} else {
new_caps->os = NULL;
}
if (os_version != NULL) {
if (os_version) {
new_caps->os_version = os_version;
} else {
new_caps->os_version = NULL;
}
if (features != NULL) {
if (features) {
new_caps->features = features;
} else {
new_caps->features = NULL;
@ -635,7 +635,7 @@ caps_close(void)
void
caps_destroy(Capabilities *caps)
{
if (caps != NULL) {
if (caps) {
free(caps->category);
free(caps->type);
free(caps->name);
@ -643,7 +643,7 @@ caps_destroy(Capabilities *caps)
free(caps->software_version);
free(caps->os);
free(caps->os_version);
if (caps->features != NULL) {
if (caps->features) {
g_slist_free_full(caps->features, free);
}
free(caps);

View File

@ -1,7 +1,7 @@
/*
* capabilities.h
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*

View File

@ -1,7 +1,7 @@
/*
* connection.c
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*
@ -45,7 +45,7 @@
#include "log.h"
#include "muc.h"
#include "profanity.h"
#include "server_events.h"
#include "event/server_events.h"
#include "xmpp/bookmark.h"
#include "xmpp/capabilities.h"
#include "xmpp/connection.h"
@ -129,11 +129,11 @@ jabber_connect_with_account(const ProfAccount * const account)
log_info("Connecting using account: %s", account->name);
// save account name and password for reconnect
if (saved_account.name != NULL) {
if (saved_account.name) {
free(saved_account.name);
}
saved_account.name = strdup(account->name);
if (saved_account.passwd != NULL) {
if (saved_account.passwd) {
free(saved_account.passwd);
}
saved_account.passwd = strdup(account->password);
@ -157,7 +157,7 @@ jabber_connect_with_details(const char * const jid,
// save details for reconnect, remember name for account creating on success
saved_details.name = strdup(jid);
saved_details.passwd = strdup(passwd);
if (altdomain != NULL) {
if (altdomain) {
saved_details.altdomain = strdup(altdomain);
} else {
saved_details.altdomain = NULL;
@ -199,11 +199,11 @@ jabber_disconnect(void)
_connection_free_saved_account();
_connection_free_saved_details();
_connection_free_session_data();
if (jabber_conn.conn != NULL) {
if (jabber_conn.conn) {
xmpp_conn_release(jabber_conn.conn);
jabber_conn.conn = NULL;
}
if (jabber_conn.ctx != NULL) {
if (jabber_conn.ctx) {
xmpp_ctx_free(jabber_conn.ctx);
jabber_conn.ctx = NULL;
}
@ -238,7 +238,7 @@ jabber_process_events(void)
break;
case JABBER_DISCONNECTED:
reconnect_sec = prefs_get_reconnect();
if ((reconnect_sec != 0) && (reconnect_timer != NULL)) {
if ((reconnect_sec != 0) && reconnect_timer) {
int elapsed_sec = g_timer_elapsed(reconnect_timer, NULL);
if (elapsed_sec > reconnect_sec) {
_jabber_reconnect();
@ -302,7 +302,7 @@ void
connection_set_presence_message(const char * const message)
{
FREE_SET_NULL(jabber_conn.presence_message);
if (message != NULL) {
if (message) {
jabber_conn.presence_message = strdup(message);
}
}
@ -371,15 +371,15 @@ _jabber_connect(const char * const fulljid, const char * const passwd,
jid_destroy(jid);
log_info("Connecting as %s", fulljid);
if (jabber_conn.log != NULL) {
if (jabber_conn.log) {
free(jabber_conn.log);
}
jabber_conn.log = _xmpp_get_file_logger();
if (jabber_conn.conn != NULL) {
if (jabber_conn.conn) {
xmpp_conn_release(jabber_conn.conn);
}
if (jabber_conn.ctx != NULL) {
if (jabber_conn.ctx) {
xmpp_ctx_free(jabber_conn.ctx);
}
jabber_conn.ctx = xmpp_ctx_new(NULL, jabber_conn.log);
@ -436,9 +436,9 @@ _connection_handler(xmpp_conn_t * const conn,
log_debug("Connection handler: XMPP_CONN_CONNECT");
// logged in with account
if (saved_account.name != NULL) {
if (saved_account.name) {
log_debug("Connection handler: logged in with account name: %s", saved_account.name);
handle_login_account_success(saved_account.name);
sv_ev_login_account_success(saved_account.name);
// logged in without account, use details to create new account
} else {
@ -446,7 +446,7 @@ _connection_handler(xmpp_conn_t * const conn,
accounts_add(saved_details.name, saved_details.altdomain, saved_details.port);
accounts_set_jid(saved_details.name, saved_details.jid);
handle_login_account_success(saved_details.name);
sv_ev_login_account_success(saved_details.name);
saved_account.name = strdup(saved_details.name);
saved_account.passwd = strdup(saved_details.passwd);
@ -466,10 +466,15 @@ _connection_handler(xmpp_conn_t * const conn,
roster_request();
bookmark_request();
if (prefs_get_boolean(PREF_CARBONS)){
iq_enable_carbons();
}
jabber_conn.conn_status = JABBER_CONNECTED;
if (prefs_get_reconnect() != 0) {
if (reconnect_timer != NULL) {
if (reconnect_timer) {
g_timer_destroy(reconnect_timer);
reconnect_timer = NULL;
}
@ -481,7 +486,7 @@ _connection_handler(xmpp_conn_t * const conn,
// lost connection for unknown reason
if (jabber_conn.conn_status == JABBER_CONNECTED) {
log_debug("Connection handler: Lost connection for unknown reason");
handle_lost_connection();
sv_ev_lost_connection();
if (prefs_get_reconnect() != 0) {
assert(reconnect_timer == NULL);
reconnect_timer = g_timer_new();
@ -498,7 +503,7 @@ _connection_handler(xmpp_conn_t * const conn,
log_debug("Connection handler: Login failed");
if (reconnect_timer == NULL) {
log_debug("Connection handler: No reconnect timer");
handle_failed_login();
sv_ev_failed_login();
_connection_free_saved_account();
_connection_free_saved_details();
_connection_free_session_data();
@ -558,7 +563,7 @@ _xmpp_file_logger(void * const userdata, const xmpp_log_level_t level,
log_level_t prof_level = _get_log_level(level);
log_msg(prof_level, area, msg);
if ((g_strcmp0(area, "xmpp") == 0) || (g_strcmp0(area, "conn")) == 0) {
handle_xmpp_stanza(msg);
sv_ev_xmpp_stanza(msg);
}
}

View File

@ -1,7 +1,7 @@
/*
* connection.h
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*

View File

@ -1,7 +1,7 @@
/*
* form.c
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*
@ -211,7 +211,7 @@ form_create(xmpp_stanza_t * const form_stanza)
field->var = _get_attr(field_stanza, "var");
if (field->type_t != FIELD_HIDDEN && field->var != NULL) {
if (field->type_t != FIELD_HIDDEN && field->var) {
GString *tag = g_string_new("");
g_string_printf(tag, "field%d", tag_num++);
g_hash_table_insert(form->var_to_tag, strdup(field->var), strdup(tag->str));

View File

@ -1,7 +1,7 @@
/*
* form.h
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*

View File

@ -1,7 +1,7 @@
/*
* iq.c
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*
@ -47,8 +47,9 @@
#include "log.h"
#include "muc.h"
#include "profanity.h"
#include "ui/ui.h"
#include "config/preferences.h"
#include "server_events.h"
#include "event/server_events.h"
#include "xmpp/capabilities.h"
#include "xmpp/connection.h"
#include "xmpp/stanza.h"
@ -58,48 +59,35 @@
#define HANDLE(ns, type, func) xmpp_handler_add(conn, func, ns, STANZA_NAME_IQ, type, ctx)
static int _error_handler(xmpp_conn_t * const conn,
xmpp_stanza_t * const stanza, void * const userdata);
static int _ping_get_handler(xmpp_conn_t * const conn,
xmpp_stanza_t * const stanza, void * const userdata);
static int _version_get_handler(xmpp_conn_t * const conn,
xmpp_stanza_t * const stanza, void * const userdata);
static int _disco_info_get_handler(xmpp_conn_t * const conn,
xmpp_stanza_t * const stanza, void * const userdata);
static int _disco_info_response_handler(xmpp_conn_t * const conn,
xmpp_stanza_t * const stanza, void * const userdata);
static int _version_result_handler(xmpp_conn_t * const conn,
xmpp_stanza_t * const stanza, void * const userdata);
static int _disco_items_result_handler(xmpp_conn_t * const conn,
xmpp_stanza_t * const stanza, void * const userdata);
static int _disco_items_get_handler(xmpp_conn_t * const conn,
xmpp_stanza_t * const stanza, void * const userdata);
static int _destroy_room_result_handler(xmpp_conn_t * const conn,
xmpp_stanza_t * const stanza, void * const userdata);
static int _room_config_handler(xmpp_conn_t * const conn,
xmpp_stanza_t * const stanza, void * const userdata);
static int _room_config_submit_handler(xmpp_conn_t * const conn,
xmpp_stanza_t * const stanza, void * const userdata);
static int _room_affiliation_list_result_handler(xmpp_conn_t * const conn,
xmpp_stanza_t * const stanza, void * const userdata);
static int _room_affiliation_set_result_handler(xmpp_conn_t * const conn,
xmpp_stanza_t * const stanza, void * const userdata);
static int _room_role_set_result_handler(xmpp_conn_t * const conn,
xmpp_stanza_t * const stanza, void * const userdata);
static int _room_role_list_result_handler(xmpp_conn_t * const conn,
xmpp_stanza_t * const stanza, void * const userdata);
static int _room_kick_result_handler(xmpp_conn_t * const conn,
xmpp_stanza_t * const stanza, void * const userdata);
static int _manual_pong_handler(xmpp_conn_t *const conn,
xmpp_stanza_t * const stanza, void * const userdata);
static int _ping_timed_handler(xmpp_conn_t * const conn,
void * const userdata);
static int _caps_response_handler(xmpp_conn_t *const conn,
xmpp_stanza_t * const stanza, void * const userdata);
static int _caps_response_handler_for_jid(xmpp_conn_t *const conn,
xmpp_stanza_t * const stanza, void * const userdata);
static int _caps_response_handler_legacy(xmpp_conn_t *const conn,
xmpp_stanza_t * const stanza, void * const userdata);
typedef struct p_room_info_data_t {
char *room;
gboolean display;
} ProfRoomInfoData;
static int _error_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata);
static int _ping_get_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata);
static int _version_get_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata);
static int _disco_info_get_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata);
static int _disco_info_response_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata);
static int _room_info_response_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata);
static int _version_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata);
static int _disco_items_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata);
static int _disco_items_get_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata);
static int _destroy_room_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata);
static int _room_config_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata);
static int _room_config_submit_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata);
static int _room_affiliation_list_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata);
static int _room_affiliation_set_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata);
static int _room_role_set_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata);
static int _room_role_list_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata);
static int _room_kick_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata);
static int _enable_carbons_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata);
static int _disable_carbons_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata);
static int _manual_pong_handler(xmpp_conn_t *const conn, xmpp_stanza_t * const stanza, void * const userdata);
static int _ping_timed_handler(xmpp_conn_t * const conn, void * const userdata);
static int _caps_response_handler(xmpp_conn_t *const conn, xmpp_stanza_t * const stanza, void * const userdata);
static int _caps_response_handler_for_jid(xmpp_conn_t *const conn, xmpp_stanza_t * const stanza, void * const userdata);
static int _caps_response_handler_legacy(xmpp_conn_t *const conn, xmpp_stanza_t * const stanza, void * const userdata);
void
iq_add_handlers(void)
@ -152,6 +140,34 @@ iq_room_list_request(gchar *conferencejid)
xmpp_stanza_release(iq);
}
void
iq_enable_carbons()
{
xmpp_conn_t * const conn = connection_get_conn();
xmpp_ctx_t * const ctx = connection_get_ctx();
xmpp_stanza_t *iq = stanza_enable_carbons(ctx);
char *id = xmpp_stanza_get_id(iq);
xmpp_id_handler_add(conn, _enable_carbons_handler, id, NULL);
xmpp_send(conn, iq);
xmpp_stanza_release(iq);
}
void
iq_disable_carbons()
{
xmpp_conn_t * const conn = connection_get_conn();
xmpp_ctx_t * const ctx = connection_get_ctx();
xmpp_stanza_t *iq = stanza_disable_carbons(ctx);
char *id = xmpp_stanza_get_id(iq);
xmpp_id_handler_add(conn, _disable_carbons_handler, id, NULL);
xmpp_send(conn, iq);
xmpp_stanza_release(iq);
}
void
iq_disco_info_request(gchar *jid)
{
@ -169,14 +185,18 @@ iq_disco_info_request(gchar *jid)
}
void
iq_room_info_request(gchar *room)
iq_room_info_request(const char * const room, gboolean display_result)
{
xmpp_conn_t * const conn = connection_get_conn();
xmpp_ctx_t * const ctx = connection_get_ctx();
char *id = create_unique_id("room_disco_info");
xmpp_stanza_t *iq = stanza_create_disco_info_iq(ctx, id, room, NULL);
xmpp_id_handler_add(conn, _disco_info_response_handler, id, room);
ProfRoomInfoData *cb_data = malloc(sizeof(ProfRoomInfoData));
cb_data->room = strdup(room);
cb_data->display = display_result;
xmpp_id_handler_add(conn, _room_info_response_handler, id, cb_data);
free(id);
@ -456,7 +476,7 @@ _error_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
const char *id = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_ID);
char *error_msg = stanza_get_error_message(stanza);
if (id != NULL) {
if (id) {
log_debug("IQ error handler fired, id: %s, error: %s", id, error_msg);
log_error("IQ error received, id: %s, error: %s", id, error_msg);
} else {
@ -476,13 +496,13 @@ _pong_handler(xmpp_conn_t *const conn, xmpp_stanza_t * const stanza,
char *id = xmpp_stanza_get_id(stanza);
char *type = xmpp_stanza_get_type(stanza);
if (id != NULL) {
if (id) {
log_debug("IQ pong handler fired, id: %s.", id);
} else {
log_debug("IQ pong handler fired.");
}
if (id != NULL && type != NULL) {
if (id && type) {
// show warning if error
if (strcmp(type, STANZA_TYPE_ERROR) == 0) {
char *error_msg = stanza_get_error_message(stanza);
@ -491,12 +511,13 @@ _pong_handler(xmpp_conn_t *const conn, xmpp_stanza_t * const stanza,
// turn off autoping if error type is 'cancel'
xmpp_stanza_t *error = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_ERROR);
if (error != NULL) {
if (error) {
char *errtype = xmpp_stanza_get_type(error);
if (errtype != NULL) {
if (errtype) {
if (strcmp(errtype, "cancel") == 0) {
log_warning("Server ping (id=%s) error type 'cancel', disabling autoping.", id);
handle_autoping_cancel();
prefs_set_autoping(0);
cons_show_error("Server ping not supported, autoping disabled.");
xmpp_timed_handler_delete(conn, _ping_timed_handler);
}
}
@ -586,12 +607,14 @@ static int
_caps_response_handler_for_jid(xmpp_conn_t *const conn, xmpp_stanza_t * const stanza,
void * const userdata)
{
char *jid = (char *)userdata;
const char *id = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_ID);
xmpp_stanza_t *query = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_QUERY);
char *type = xmpp_stanza_get_type(stanza);
// ignore non result
if ((g_strcmp0(type, "get") == 0) || (g_strcmp0(type, "set") == 0)) {
free(jid);
return 1;
}
@ -604,6 +627,7 @@ _caps_response_handler_for_jid(xmpp_conn_t *const conn, xmpp_stanza_t * const st
const char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
if (!from) {
log_info("No from attribute");
free(jid);
return 0;
}
@ -612,25 +636,29 @@ _caps_response_handler_for_jid(xmpp_conn_t *const conn, xmpp_stanza_t * const st
char *error_message = stanza_get_error_message(stanza);
log_warning("Error received for capabilities response from %s: ", from, error_message);
free(error_message);
free(jid);
return 0;
}
if (query == NULL) {
log_warning("No query element found.");
free(jid);
return 0;
}
char *node = xmpp_stanza_get_attribute(query, STANZA_ATTR_NODE);
if (node == NULL) {
log_warning("No node attribute found");
free(jid);
return 0;
}
char *jid = (char *)userdata;
log_info("Associating capabilities with: %s", jid);
Capabilities *capabilities = caps_create(query);
caps_add_by_jid(jid, capabilities);
free(jid);
return 0;
}
@ -640,10 +668,12 @@ _caps_response_handler_legacy(xmpp_conn_t *const conn, xmpp_stanza_t * const sta
{
const char *id = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_ID);
xmpp_stanza_t *query = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_QUERY);
char *expected_node = (char *)userdata;
char *type = xmpp_stanza_get_type(stanza);
// ignore non result
if ((g_strcmp0(type, "get") == 0) || (g_strcmp0(type, "set") == 0)) {
free(expected_node);
return 1;
}
@ -656,6 +686,7 @@ _caps_response_handler_legacy(xmpp_conn_t *const conn, xmpp_stanza_t * const sta
const char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
if (!from) {
log_info("No from attribute");
free(expected_node);
return 0;
}
@ -664,22 +695,23 @@ _caps_response_handler_legacy(xmpp_conn_t *const conn, xmpp_stanza_t * const sta
char *error_message = stanza_get_error_message(stanza);
log_warning("Error received for capabilities response from %s: ", from, error_message);
free(error_message);
free(expected_node);
return 0;
}
if (query == NULL) {
log_warning("No query element found.");
free(expected_node);
return 0;
}
char *node = xmpp_stanza_get_attribute(query, STANZA_ATTR_NODE);
if (node == NULL) {
log_warning("No node attribute found");
free(expected_node);
return 0;
}
char *expected_node = (char *)userdata;
// nodes match
if (g_strcmp0(expected_node, node) == 0) {
log_info("Legacy capabilities, nodes match %s", node);
@ -703,6 +735,36 @@ _caps_response_handler_legacy(xmpp_conn_t *const conn, xmpp_stanza_t * const sta
return 0;
}
static int
_enable_carbons_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata)
{
char *type = xmpp_stanza_get_type(stanza);
if (g_strcmp0(type, "error") == 0) {
char *error_message = stanza_get_error_message(stanza);
cons_show_error("Server error enabling message carbons: %s", error_message);
log_debug("Error enabling carbons: %s", error_message);
} else {
log_debug("Message carbons enabled.");
}
return 0;
}
static int
_disable_carbons_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata)
{
char *type = xmpp_stanza_get_type(stanza);
if (g_strcmp0(type, "error") == 0) {
char *error_message = stanza_get_error_message(stanza);
cons_show_error("Server error disabling message carbons: %s", error_message);
log_debug("Error disabling carbons: %s", error_message);
} else {
log_debug("Message carbons disabled.");
}
return 0;
}
static int
_manual_pong_handler(xmpp_conn_t *const conn, xmpp_stanza_t * const stanza,
void * const userdata)
@ -714,7 +776,12 @@ _manual_pong_handler(xmpp_conn_t *const conn, xmpp_stanza_t * const stanza,
// handle error responses
if (g_strcmp0(type, STANZA_TYPE_ERROR) == 0) {
char *error_message = stanza_get_error_message(stanza);
handle_ping_error_result(from, error_message);
if (!error_message) {
cons_show_error("Error returned from pinging %s.", from);
} else {
cons_show_error("Error returned from pinging %s: %s.", from, error_message);
}
free(error_message);
g_date_time_unref(sent);
return 0;
@ -728,7 +795,11 @@ _manual_pong_handler(xmpp_conn_t *const conn, xmpp_stanza_t * const stanza,
g_date_time_unref(sent);
g_date_time_unref(now);
handle_ping_result(from, elapsed_millis);
if (from == NULL) {
cons_show("Ping response from server: %dms.", elapsed_millis);
} else {
cons_show("Ping response from %s: %dms.", from, elapsed_millis);
}
return 0;
}
@ -759,7 +830,7 @@ _version_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
{
char *id = xmpp_stanza_get_id(stanza);
if (id != NULL) {
if (id) {
log_debug("IQ version result handler fired, id: %s.", id);
} else {
log_debug("IQ version result handler fired.");
@ -784,13 +855,13 @@ _version_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
xmpp_stanza_t *version = xmpp_stanza_get_child_by_name(query, "version");
xmpp_stanza_t *os = xmpp_stanza_get_child_by_name(query, "os");
if (name != NULL) {
if (name) {
name_str = xmpp_stanza_get_text(name);
}
if (version != NULL) {
if (version) {
version_str = xmpp_stanza_get_text(version);
}
if (os != NULL) {
if (os) {
os_str = xmpp_stanza_get_text(os);
}
@ -805,7 +876,7 @@ _version_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
presence = string_from_resource_presence(resource->presence);
}
handle_software_version_result(jid, presence, name_str, version_str, os_str);
cons_show_software_version(jid, presence, name_str, version_str, os_str);
jid_destroy(jidp);
@ -821,7 +892,7 @@ _ping_get_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
const char *to = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_TO);
const char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
if (id != NULL) {
if (id) {
log_debug("IQ ping get handler fired, id: %s.", id);
} else {
log_debug("IQ ping get handler fired.");
@ -837,7 +908,7 @@ _ping_get_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
xmpp_stanza_set_attribute(pong, STANZA_ATTR_FROM, to);
xmpp_stanza_set_attribute(pong, STANZA_ATTR_TYPE, STANZA_TYPE_RESULT);
if (id != NULL) {
if (id) {
xmpp_stanza_set_attribute(pong, STANZA_ATTR_ID, id);
}
@ -855,16 +926,16 @@ _version_get_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
const char *id = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_ID);
const char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
if (id != NULL) {
if (id) {
log_debug("IQ version get handler fired, id: %s.", id);
} else {
log_debug("IQ version get handler fired.");
}
if (from != NULL) {
if (from) {
xmpp_stanza_t *response = xmpp_stanza_new(ctx);
xmpp_stanza_set_name(response, STANZA_NAME_IQ);
if (id != NULL) {
if (id) {
xmpp_stanza_set_id(response, id);
}
xmpp_stanza_set_attribute(response, STANZA_ATTR_TO, from);
@ -923,13 +994,13 @@ _disco_items_get_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
const char *id = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_ID);
const char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
if (id != NULL) {
if (id) {
log_debug("IQ disco items get handler fired, id: %s.", id);
} else {
log_debug("IQ disco items get handler fired.");
}
if (from != NULL) {
if (from) {
xmpp_stanza_t *response = xmpp_stanza_new(ctx);
xmpp_stanza_set_name(response, STANZA_NAME_IQ);
xmpp_stanza_set_id(response, xmpp_stanza_get_id(stanza));
@ -960,20 +1031,20 @@ _disco_info_get_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
const char *id = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_ID);
if (id != NULL) {
if (id) {
log_debug("IQ disco info get handler fired, id: %s.", id);
} else {
log_debug("IQ disco info get handler fired.");
}
if (from != NULL) {
if (from) {
xmpp_stanza_t *response = xmpp_stanza_new(ctx);
xmpp_stanza_set_name(response, STANZA_NAME_IQ);
xmpp_stanza_set_id(response, xmpp_stanza_get_id(stanza));
xmpp_stanza_set_attribute(response, STANZA_ATTR_TO, from);
xmpp_stanza_set_type(response, STANZA_TYPE_RESULT);
xmpp_stanza_t *query = caps_create_query_response_stanza(ctx);
if (node_str != NULL) {
if (node_str) {
xmpp_stanza_set_attribute(query, STANZA_ATTR_NODE, node_str);
}
xmpp_stanza_add_child(response, query);
@ -992,7 +1063,7 @@ _destroy_room_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const sta
{
const char *id = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_ID);
if (id != NULL) {
if (id) {
log_debug("IQ destroy room result handler fired, id: %s.", id);
} else {
log_debug("IQ destroy room result handler fired.");
@ -1002,7 +1073,7 @@ _destroy_room_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const sta
if (from == NULL) {
log_error("No from attribute for IQ destroy room result");
} else {
handle_room_destroy(from);
sv_ev_room_destroy(from);
}
return 0;
@ -1016,7 +1087,7 @@ _room_config_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
const char *type = xmpp_stanza_get_type(stanza);
const char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
if (id != NULL) {
if (id) {
log_debug("IQ room config handler fired, id: %s.", id);
} else {
log_debug("IQ room config handler fired.");
@ -1025,40 +1096,40 @@ _room_config_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
// handle error responses
if (g_strcmp0(type, STANZA_TYPE_ERROR) == 0) {
char *error_message = stanza_get_error_message(stanza);
handle_room_configuration_form_error(from, error_message);
ui_handle_room_configuration_form_error(from, error_message);
free(error_message);
return 0;
}
if (from == NULL) {
log_warning("No from attribute for IQ config request result");
handle_room_configuration_form_error(from, "No from attribute for room cofig response.");
ui_handle_room_configuration_form_error(from, "No from attribute for room cofig response.");
return 0;
}
xmpp_stanza_t *query = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_QUERY);
if (query == NULL) {
log_warning("No query element found parsing room config response");
handle_room_configuration_form_error(from, "No query element found parsing room config response");
ui_handle_room_configuration_form_error(from, "No query element found parsing room config response");
return 0;
}
xmpp_stanza_t *x = xmpp_stanza_get_child_by_ns(query, STANZA_NS_DATA);
if (x == NULL) {
log_warning("No x element found with %s namespace parsing room config response", STANZA_NS_DATA);
handle_room_configuration_form_error(from, "No form configuration options available");
ui_handle_room_configuration_form_error(from, "No form configuration options available");
return 0;
}
char *form_type = xmpp_stanza_get_attribute(x, STANZA_ATTR_TYPE);
if (g_strcmp0(form_type, "form") != 0) {
log_warning("x element not of type 'form' parsing room config response");
handle_room_configuration_form_error(from, "Form not of type 'form' parsing room config response.");
ui_handle_room_configuration_form_error(from, "Form not of type 'form' parsing room config response.");
return 0;
}
DataForm *form = form_create(x);
handle_room_configure(from, form);
ui_handle_room_configuration(from, form);
return 0;
}
@ -1071,7 +1142,7 @@ static int _room_affiliation_set_result_handler(xmpp_conn_t * const conn, xmpp_s
const char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
struct privilege_set_t *affiliation_set = (struct privilege_set_t *)userdata;
if (id != NULL) {
if (id) {
log_debug("IQ affiliation set handler fired, id: %s.", id);
} else {
log_debug("IQ affiliation set handler fired.");
@ -1080,7 +1151,8 @@ static int _room_affiliation_set_result_handler(xmpp_conn_t * const conn, xmpp_s
// handle error responses
if (g_strcmp0(type, STANZA_TYPE_ERROR) == 0) {
char *error_message = stanza_get_error_message(stanza);
handle_room_affiliation_set_error(from, affiliation_set->item, affiliation_set->privilege, error_message);
log_debug("Error setting affiliation %s list for room %s, user %s: %s", affiliation_set->privilege, from, affiliation_set->item, error_message);
ui_handle_room_affiliation_set_error(from, affiliation_set->item, affiliation_set->privilege, error_message);
free(error_message);
}
@ -1099,7 +1171,7 @@ static int _room_role_set_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t
const char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
struct privilege_set_t *role_set = (struct privilege_set_t *)userdata;
if (id != NULL) {
if (id) {
log_debug("IQ role set handler fired, id: %s.", id);
} else {
log_debug("IQ role set handler fired.");
@ -1108,7 +1180,8 @@ static int _room_role_set_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t
// handle error responses
if (g_strcmp0(type, STANZA_TYPE_ERROR) == 0) {
char *error_message = stanza_get_error_message(stanza);
handle_room_role_set_error(from, role_set->item, role_set->privilege, error_message);
log_debug("Error setting role %s list for room %s, user %s: %s", role_set->privilege, from, role_set->item, error_message);
ui_handle_room_role_set_error(from, role_set->item, role_set->privilege, error_message);
free(error_message);
}
@ -1127,7 +1200,7 @@ _room_affiliation_list_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t *
const char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
char *affiliation = (char *)userdata;
if (id != NULL) {
if (id) {
log_debug("IQ affiliation list result handler fired, id: %s.", id);
} else {
log_debug("IQ affiliation list result handler fired.");
@ -1136,7 +1209,8 @@ _room_affiliation_list_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t *
// handle error responses
if (g_strcmp0(type, STANZA_TYPE_ERROR) == 0) {
char *error_message = stanza_get_error_message(stanza);
handle_room_affiliation_list_result_error(from, affiliation, error_message);
log_debug("Error retrieving %s list for room %s: %s", affiliation, from, error_message);
ui_handle_room_affiliation_list_error(from, affiliation, error_message);
free(error_message);
free(affiliation);
return 0;
@ -1158,7 +1232,8 @@ _room_affiliation_list_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t *
}
}
handle_room_affiliation_list(from, affiliation, jids);
muc_jid_autocomplete_add_all(from, jids);
ui_handle_room_affiliation_list(from, affiliation, jids);
free(affiliation);
g_slist_free(jids);
@ -1173,7 +1248,7 @@ _room_role_list_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const s
const char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
char *role = (char *)userdata;
if (id != NULL) {
if (id) {
log_debug("IQ role list result handler fired, id: %s.", id);
} else {
log_debug("IQ role list result handler fired.");
@ -1182,7 +1257,8 @@ _room_role_list_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const s
// handle error responses
if (g_strcmp0(type, STANZA_TYPE_ERROR) == 0) {
char *error_message = stanza_get_error_message(stanza);
handle_room_role_list_result_error(from, role, error_message);
log_debug("Error retrieving %s list for room %s: %s", role, from, error_message);
ui_handle_room_role_list_error(from, role, error_message);
free(error_message);
free(role);
return 0;
@ -1204,7 +1280,7 @@ _room_role_list_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const s
}
}
handle_room_role_list(from, role, nicks);
ui_handle_room_role_list(from, role, nicks);
free(role);
g_slist_free(nicks);
@ -1219,7 +1295,7 @@ _room_config_submit_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stan
const char *type = xmpp_stanza_get_type(stanza);
const char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
if (id != NULL) {
if (id) {
log_debug("IQ room config submit handler fired, id: %s.", id);
} else {
log_debug("IQ room config submit handler fired.");
@ -1228,12 +1304,12 @@ _room_config_submit_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stan
// handle error responses
if (g_strcmp0(type, STANZA_TYPE_ERROR) == 0) {
char *error_message = stanza_get_error_message(stanza);
handle_room_config_submit_result_error(from, error_message);
ui_handle_room_config_submit_result_error(from, error_message);
free(error_message);
return 0;
}
handle_room_config_submit_result(from);
ui_handle_room_config_submit_result(from);
return 0;
}
@ -1246,7 +1322,7 @@ _room_kick_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza
const char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
char *nick = (char *)userdata;
if (id != NULL) {
if (id) {
log_debug("IQ kick result handler fired, id: %s.", id);
} else {
log_debug("IQ kick result handler fired.");
@ -1255,7 +1331,7 @@ _room_kick_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza
// handle error responses
if (g_strcmp0(type, STANZA_TYPE_ERROR) == 0) {
char *error_message = stanza_get_error_message(stanza);
handle_room_kick_result_error(from, nick, error_message);
ui_handle_room_kick_error(from, nick, error_message);
free(error_message);
free(nick);
return 0;
@ -1269,7 +1345,7 @@ _room_kick_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza
static void
_identity_destroy(DiscoIdentity *identity)
{
if (identity != NULL) {
if (identity) {
free(identity->name);
free(identity->type);
free(identity->category);
@ -1280,7 +1356,7 @@ _identity_destroy(DiscoIdentity *identity)
static void
_item_destroy(DiscoItem *item)
{
if (item != NULL) {
if (item) {
free(item->jid);
free(item->name);
free(item);
@ -1288,48 +1364,36 @@ _item_destroy(DiscoItem *item)
}
static int
_disco_info_response_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
_room_info_response_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
void * const userdata)
{
const char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
const char *type = xmpp_stanza_get_type(stanza);
char *room = NULL;
if (userdata) {
room = (char *) userdata;
log_info("Received diso#info response for room: %s", room);
} else {
room = NULL;
if (from) {
log_info("Received diso#info response from: %s", from);
} else {
log_info("Received diso#info response");
}
}
ProfRoomInfoData *cb_data = (ProfRoomInfoData *)userdata;
log_info("Received diso#info response for room: %s", cb_data->room);
// handle error responses
if (g_strcmp0(type, STANZA_TYPE_ERROR) == 0) {
char *error_message = stanza_get_error_message(stanza);
if (room) {
handle_room_info_error(room, error_message);
} else {
handle_disco_info_error(from, error_message);
if (cb_data->display) {
char *error_message = stanza_get_error_message(stanza);
ui_handle_room_info_error(cb_data->room, error_message);
free(error_message);
}
free(error_message);
free(cb_data->room);
free(cb_data);
return 0;
}
xmpp_stanza_t *query = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_QUERY);
if (query != NULL) {
if (query) {
xmpp_stanza_t *child = xmpp_stanza_get_children(query);
GSList *identities = NULL;
GSList *features = NULL;
while (child != NULL) {
while (child) {
const char *stanza_name = xmpp_stanza_get_name(child);
if (g_strcmp0(stanza_name, STANZA_NAME_FEATURE) == 0) {
const char *var = xmpp_stanza_get_attribute(child, STANZA_ATTR_VAR);
if (var != NULL) {
if (var) {
features = g_slist_append(features, strdup(var));
}
} else if (g_strcmp0(stanza_name, STANZA_NAME_IDENTITY) == 0) {
@ -1337,20 +1401,20 @@ _disco_info_response_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const sta
const char *type = xmpp_stanza_get_attribute(child, STANZA_ATTR_TYPE);
const char *category = xmpp_stanza_get_attribute(child, STANZA_ATTR_CATEGORY);
if ((name != NULL) || (category != NULL) || (type != NULL)) {
if (name || category || type) {
DiscoIdentity *identity = malloc(sizeof(struct disco_identity_t));
if (name != NULL) {
if (name) {
identity->name = strdup(name);
} else {
identity->name = NULL;
}
if (category != NULL) {
if (category) {
identity->category = strdup(category);
} else {
identity->category = NULL;
}
if (type != NULL) {
if (type) {
identity->type = strdup(type);
} else {
identity->type = NULL;
@ -1363,16 +1427,97 @@ _disco_info_response_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const sta
child = xmpp_stanza_get_next(child);
}
if (room) {
handle_room_disco_info(room, identities, features);
} else {
handle_disco_info(from, identities, features);
muc_set_features(cb_data->room, features);
if (cb_data->display) {
ui_show_room_disco_info(cb_data->room, identities, features);
}
g_slist_free_full(features, free);
g_slist_free_full(identities, (GDestroyNotify)_identity_destroy);
}
return 1;
free(cb_data->room);
free(cb_data);
return 0;
}
static int
_disco_info_response_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
void * const userdata)
{
const char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
const char *type = xmpp_stanza_get_type(stanza);
if (from) {
log_info("Received diso#info response from: %s", from);
} else {
log_info("Received diso#info response");
}
// handle error responses
if (g_strcmp0(type, STANZA_TYPE_ERROR) == 0) {
char *error_message = stanza_get_error_message(stanza);
if (from) {
cons_show_error("Service discovery failed for %s: %s", from, error_message);
} else {
cons_show_error("Service discovery failed: %s", error_message);
}
free(error_message);
return 0;
}
xmpp_stanza_t *query = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_QUERY);
if (query) {
xmpp_stanza_t *child = xmpp_stanza_get_children(query);
GSList *identities = NULL;
GSList *features = NULL;
while (child) {
const char *stanza_name = xmpp_stanza_get_name(child);
if (g_strcmp0(stanza_name, STANZA_NAME_FEATURE) == 0) {
const char *var = xmpp_stanza_get_attribute(child, STANZA_ATTR_VAR);
if (var) {
features = g_slist_append(features, strdup(var));
}
} else if (g_strcmp0(stanza_name, STANZA_NAME_IDENTITY) == 0) {
const char *name = xmpp_stanza_get_attribute(child, STANZA_ATTR_NAME);
const char *type = xmpp_stanza_get_attribute(child, STANZA_ATTR_TYPE);
const char *category = xmpp_stanza_get_attribute(child, STANZA_ATTR_CATEGORY);
if (name || category || type) {
DiscoIdentity *identity = malloc(sizeof(struct disco_identity_t));
if (name) {
identity->name = strdup(name);
} else {
identity->name = NULL;
}
if (category) {
identity->category = strdup(category);
} else {
identity->category = NULL;
}
if (type) {
identity->type = strdup(type);
} else {
identity->type = NULL;
}
identities = g_slist_append(identities, identity);
}
}
child = xmpp_stanza_get_next(child);
}
cons_show_disco_info(from, identities, features);
g_slist_free_full(features, free);
g_slist_free_full(identities, (GDestroyNotify)_identity_destroy);
}
return 0;
}
static int
@ -1389,17 +1534,17 @@ _disco_items_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stan
log_debug("Response to query: %s", id);
xmpp_stanza_t *query = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_QUERY);
if (query != NULL) {
if (query) {
xmpp_stanza_t *child = xmpp_stanza_get_children(query);
while (child != NULL) {
while (child) {
const char *stanza_name = xmpp_stanza_get_name(child);
if ((stanza_name != NULL) && (g_strcmp0(stanza_name, STANZA_NAME_ITEM) == 0)) {
if (stanza_name && (g_strcmp0(stanza_name, STANZA_NAME_ITEM) == 0)) {
const char *item_jid = xmpp_stanza_get_attribute(child, STANZA_ATTR_JID);
if (item_jid != NULL) {
if (item_jid) {
DiscoItem *item = malloc(sizeof(struct disco_item_t));
item->jid = strdup(item_jid);
const char *item_name = xmpp_stanza_get_attribute(child, STANZA_ATTR_NAME);
if (item_name != NULL) {
if (item_name) {
item->name = strdup(item_name);
} else {
item->name = NULL;
@ -1414,9 +1559,9 @@ _disco_items_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stan
}
if (g_strcmp0(id, "confreq") == 0) {
handle_room_list(items, from);
cons_show_room_list(items, from);
} else if (g_strcmp0(id, "discoitemsreq") == 0) {
handle_disco_items(items, from);
cons_show_disco_items(items, from);
}
g_slist_free_full(items, (GDestroyNotify)_item_destroy);

View File

@ -1,7 +1,7 @@
/*
* iq.h
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*

View File

@ -1,7 +1,7 @@
/*
* message.c
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*
@ -42,7 +42,8 @@
#include "log.h"
#include "muc.h"
#include "profanity.h"
#include "server_events.h"
#include "ui/ui.h"
#include "event/server_events.h"
#include "xmpp/connection.h"
#include "xmpp/message.h"
#include "xmpp/roster.h"
@ -52,18 +53,13 @@
#define HANDLE(ns, type, func) xmpp_handler_add(conn, func, ns, STANZA_NAME_MESSAGE, type, ctx)
static int _groupchat_handler(xmpp_conn_t * const conn,
xmpp_stanza_t * const stanza, void * const userdata);
static int _chat_handler(xmpp_conn_t * const conn,
xmpp_stanza_t * const stanza, void * const userdata);
static int _muc_user_handler(xmpp_conn_t * const conn,
xmpp_stanza_t * const stanza, void * const userdata);
static int _conference_handler(xmpp_conn_t * const conn,
xmpp_stanza_t * const stanza, void * const userdata);
static int _captcha_handler(xmpp_conn_t * const conn,
xmpp_stanza_t * const stanza, void * const userdata);
static int _message_error_handler(xmpp_conn_t * const conn,
xmpp_stanza_t * const stanza, void * const userdata);
static int _groupchat_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata);
static int _chat_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata);
static int _muc_user_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata);
static int _conference_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata);
static int _captcha_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata);
static int _message_error_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata);
static int _receipt_received_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata);
void
message_add_handlers(void)
@ -77,34 +73,89 @@ message_add_handlers(void)
HANDLE(STANZA_NS_MUC_USER, NULL, _muc_user_handler);
HANDLE(STANZA_NS_CONFERENCE, NULL, _conference_handler);
HANDLE(STANZA_NS_CAPTCHA, NULL, _captcha_handler);
HANDLE(STANZA_NS_RECEIPTS, NULL, _receipt_received_handler);
}
void
char *
message_send_chat(const char * const barejid, const char * const msg)
{
xmpp_stanza_t *message;
xmpp_conn_t * const conn = connection_get_conn();
xmpp_ctx_t * const ctx = connection_get_ctx();
ChatSession *session = chat_session_get(barejid);
char *state = NULL;
char *jid = NULL;
if (session) {
char *state = NULL;
if (prefs_get_boolean(PREF_STATES) && session->send_states) {
state = STANZA_NAME_ACTIVE;
}
Jid *jidp = jid_create_from_bare_and_resource(session->barejid, session->resource);
message = stanza_create_message(ctx, jidp->fulljid, STANZA_TYPE_CHAT, msg, state);
jid = strdup(jidp->fulljid);
jid_destroy(jidp);
} else {
char *state = NULL;
if (prefs_get_boolean(PREF_STATES)) {
state = STANZA_NAME_ACTIVE;
}
message = stanza_create_message(ctx, barejid, STANZA_TYPE_CHAT, msg, state);
jid = strdup(barejid);
}
char *id = create_unique_id("msg");
xmpp_stanza_t *message = stanza_create_message(ctx, id, jid, STANZA_TYPE_CHAT, msg);
free(jid);
if (state) {
stanza_attach_state(ctx, message, state);
}
if (prefs_get_boolean(PREF_RECEIPTS_REQUEST)) {
stanza_attach_receipt_request(ctx, message);
}
xmpp_send(conn, message);
xmpp_stanza_release(message);
return id;
}
char *
message_send_chat_encrypted(const char * const barejid, const char * const msg)
{
xmpp_conn_t * const conn = connection_get_conn();
xmpp_ctx_t * const ctx = connection_get_ctx();
ChatSession *session = chat_session_get(barejid);
char *state = NULL;
char *jid = NULL;
if (session) {
if (prefs_get_boolean(PREF_STATES) && session->send_states) {
state = STANZA_NAME_ACTIVE;
}
Jid *jidp = jid_create_from_bare_and_resource(session->barejid, session->resource);
jid = strdup(jidp->fulljid);
jid_destroy(jidp);
} else {
if (prefs_get_boolean(PREF_STATES)) {
state = STANZA_NAME_ACTIVE;
}
jid = strdup(barejid);
}
char *id = create_unique_id("msg");
xmpp_stanza_t *message = stanza_create_message(ctx, id, barejid, STANZA_TYPE_CHAT, msg);
free(jid);
if (state) {
stanza_attach_state(ctx, message, state);
}
stanza_attach_carbons_private(ctx, message);
if (prefs_get_boolean(PREF_RECEIPTS_REQUEST)) {
stanza_attach_receipt_request(ctx, message);
}
xmpp_send(conn, message);
xmpp_stanza_release(message);
return id;
}
void
@ -112,7 +163,9 @@ message_send_private(const char * const fulljid, const char * const msg)
{
xmpp_conn_t * const conn = connection_get_conn();
xmpp_ctx_t * const ctx = connection_get_ctx();
xmpp_stanza_t *message = stanza_create_message(ctx, fulljid, STANZA_TYPE_CHAT, msg, NULL);
char *id = create_unique_id("prv");
xmpp_stanza_t *message = stanza_create_message(ctx, id, fulljid, STANZA_TYPE_CHAT, msg);
free(id);
xmpp_send(conn, message);
xmpp_stanza_release(message);
@ -123,7 +176,9 @@ message_send_groupchat(const char * const roomjid, const char * const msg)
{
xmpp_conn_t * const conn = connection_get_conn();
xmpp_ctx_t * const ctx = connection_get_ctx();
xmpp_stanza_t *message = stanza_create_message(ctx, roomjid, STANZA_TYPE_GROUPCHAT, msg, NULL);
char *id = create_unique_id("muc");
xmpp_stanza_t *message = stanza_create_message(ctx, id, roomjid, STANZA_TYPE_GROUPCHAT, msg);
free(id);
xmpp_send(conn, message);
xmpp_stanza_release(message);
@ -146,7 +201,18 @@ message_send_invite(const char * const roomjid, const char * const contact,
{
xmpp_conn_t * const conn = connection_get_conn();
xmpp_ctx_t * const ctx = connection_get_ctx();
xmpp_stanza_t *stanza = stanza_create_invite(ctx, roomjid, contact, reason);
xmpp_stanza_t *stanza;
muc_member_type_t member_type = muc_member_type(roomjid);
if (member_type == MUC_MEMBER_TYPE_PUBLIC) {
log_debug("Sending direct invite to %s, for %s", contact, roomjid);
char *password = muc_password(roomjid);
stanza = stanza_create_invite(ctx, roomjid, contact, reason, password);
} else {
log_debug("Sending mediated invite to %s, for %s", contact, roomjid);
stanza = stanza_create_mediated_invite(ctx, roomjid, contact, reason);
}
xmpp_send(conn, stanza);
xmpp_stanza_release(stanza);
@ -196,14 +262,13 @@ message_send_gone(const char * const jid)
}
static int
_message_error_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
void * const userdata)
_message_error_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata)
{
char *id = xmpp_stanza_get_id(stanza);
char *jid = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
xmpp_stanza_t *error_stanza = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_ERROR);
char *type = NULL;
if (error_stanza != NULL) {
if (error_stanza) {
type = xmpp_stanza_get_attribute(error_stanza, STANZA_ATTR_TYPE);
}
@ -211,15 +276,15 @@ _message_error_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
char *err_msg = stanza_get_error_message(stanza);
GString *log_msg = g_string_new("message stanza error received");
if (id != NULL) {
if (id) {
g_string_append(log_msg, " id=");
g_string_append(log_msg, id);
}
if (jid != NULL) {
if (jid) {
g_string_append(log_msg, " from=");
g_string_append(log_msg, jid);
}
if (type != NULL) {
if (type) {
g_string_append(log_msg, " type=");
g_string_append(log_msg, type);
}
@ -230,7 +295,16 @@ _message_error_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
g_string_free(log_msg, TRUE);
handle_message_error(jid, type, err_msg);
if (!jid) {
ui_handle_error(err_msg);
} else if (type && (strcmp(type, "cancel") == 0)) {
log_info("Recipient %s not found: %s", jid, err_msg);
Jid *jidp = jid_create(jid);
chat_session_remove(jidp->barejid);
jid_destroy(jidp);
} else {
ui_handle_recipient_error(jid, err_msg);
}
free(err_msg);
@ -238,113 +312,120 @@ _message_error_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
}
static int
_muc_user_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
void * const userdata)
_muc_user_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata)
{
xmpp_ctx_t *ctx = connection_get_ctx();
xmpp_stanza_t *xns_muc_user = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_MUC_USER);
char *room = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
if (room == NULL) {
if (!room) {
log_warning("Message received with no from attribute, ignoring");
return 1;
}
// XEP-0045
xmpp_stanza_t *invite = xmpp_stanza_get_child_by_name(xns_muc_user, STANZA_NAME_INVITE);
if (invite != NULL) {
char *invitor_jid = xmpp_stanza_get_attribute(invite, STANZA_ATTR_FROM);
if (invitor_jid == NULL) {
log_warning("Chat room invite received with no from attribute");
return 1;
}
if (!invite) {
return 1;
}
Jid *jidp = jid_create(invitor_jid);
if (jidp == NULL) {
return 1;
}
char *invitor = jidp->barejid;
char *invitor_jid = xmpp_stanza_get_attribute(invite, STANZA_ATTR_FROM);
if (!invitor_jid) {
log_warning("Chat room invite received with no from attribute");
return 1;
}
char *reason = NULL;
xmpp_stanza_t *reason_st = xmpp_stanza_get_child_by_name(invite, STANZA_NAME_REASON);
if (reason_st != NULL) {
reason = xmpp_stanza_get_text(reason_st);
}
Jid *jidp = jid_create(invitor_jid);
if (!jidp) {
return 1;
}
char *invitor = jidp->barejid;
handle_room_invite(INVITE_MEDIATED, invitor, room, reason);
jid_destroy(jidp);
if (reason != NULL) {
xmpp_free(ctx, reason);
}
char *reason = NULL;
xmpp_stanza_t *reason_st = xmpp_stanza_get_child_by_name(invite, STANZA_NAME_REASON);
if (reason_st) {
reason = xmpp_stanza_get_text(reason_st);
}
char *password = NULL;
xmpp_stanza_t *password_st = xmpp_stanza_get_child_by_name(xns_muc_user, STANZA_NAME_PASSWORD);
if (password_st) {
password = xmpp_stanza_get_text(password_st);
}
sv_ev_room_invite(INVITE_MEDIATED, invitor, room, reason, password);
jid_destroy(jidp);
if (reason) {
xmpp_free(ctx, reason);
}
if (password) {
xmpp_free(ctx, password);
}
return 1;
}
static int
_conference_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
void * const userdata)
_conference_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata)
{
xmpp_stanza_t *xns_conference = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_CONFERENCE);
char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
char *room = NULL;
char *invitor = NULL;
char *reason = NULL;
if (from == NULL) {
char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
if (!from) {
log_warning("Message received with no from attribute, ignoring");
return 1;
}
// XEP-0429
room = xmpp_stanza_get_attribute(xns_conference, STANZA_ATTR_JID);
if (room == NULL) {
return 1;
}
Jid *jidp = jid_create(from);
if (jidp == NULL) {
if (!jidp) {
return 1;
}
invitor = jidp->barejid;
reason = xmpp_stanza_get_attribute(xns_conference, STANZA_ATTR_REASON);
// XEP-0249
char *room = xmpp_stanza_get_attribute(xns_conference, STANZA_ATTR_JID);
if (!room) {
return 1;
}
handle_room_invite(INVITE_DIRECT, invitor, room, reason);
char *reason = xmpp_stanza_get_attribute(xns_conference, STANZA_ATTR_REASON);
char *password = xmpp_stanza_get_attribute(xns_conference, STANZA_ATTR_PASSWORD);
sv_ev_room_invite(INVITE_DIRECT, jidp->barejid, room, reason, password);
jid_destroy(jidp);
return 1;
}
static int
_captcha_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
void * const userdata)
_captcha_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata)
{
xmpp_ctx_t *ctx = connection_get_ctx();
char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
if (from == NULL) {
if (!from) {
log_warning("Message received with no from attribute, ignoring");
return 1;
}
// XEP-0158
xmpp_stanza_t *body = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_BODY);
if (body != NULL) {
char *message = xmpp_stanza_get_text(body);
if (message != NULL) {
handle_room_broadcast(from, message);
xmpp_free(ctx, message);
}
if (!body) {
return 1;
}
char *message = xmpp_stanza_get_text(body);
if (!message) {
return 1;
}
sv_ev_room_broadcast(from, message);
xmpp_free(ctx, message);
return 1;
}
static int
_groupchat_handler(xmpp_conn_t * const conn,
xmpp_stanza_t * const stanza, void * const userdata)
_groupchat_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata)
{
xmpp_ctx_t *ctx = connection_get_ctx();
char *message = NULL;
@ -353,9 +434,9 @@ _groupchat_handler(xmpp_conn_t * const conn,
// handle room subject
xmpp_stanza_t *subject = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_SUBJECT);
if (subject != NULL) {
if (subject) {
message = xmpp_stanza_get_text(subject);
handle_room_subject(jid->barejid, jid->resourcepart, message);
sv_ev_room_subject(jid->barejid, jid->resourcepart, message);
xmpp_free(ctx, message);
jid_destroy(jid);
@ -363,16 +444,22 @@ _groupchat_handler(xmpp_conn_t * const conn,
}
// handle room broadcasts
if (jid->resourcepart == NULL) {
if (!jid->resourcepart) {
xmpp_stanza_t *body = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_BODY);
if (body != NULL) {
message = xmpp_stanza_get_text(body);
if (message != NULL) {
handle_room_broadcast(room_jid, message);
xmpp_free(ctx, message);
}
if (!body) {
jid_destroy(jid);
return 1;
}
message = xmpp_stanza_get_text(body);
if (!message) {
jid_destroy(jid);
return 1;
}
sv_ev_room_broadcast(room_jid, message);
xmpp_free(ctx, message);
jid_destroy(jid);
return 1;
}
@ -390,32 +477,191 @@ _groupchat_handler(xmpp_conn_t * const conn,
return 1;
}
// determine if the notifications happened whilst offline
GTimeVal tv_stamp;
gboolean delayed = stanza_get_delay(stanza, &tv_stamp);
xmpp_stanza_t *body = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_BODY);
// check for and deal with message
if (body != NULL) {
message = xmpp_stanza_get_text(body);
if (message != NULL) {
if (delayed) {
handle_room_history(jid->barejid, jid->resourcepart, tv_stamp, message);
} else {
handle_room_message(jid->barejid, jid->resourcepart, message);
}
xmpp_free(ctx, message);
}
if (!body) {
jid_destroy(jid);
return 1;
}
message = xmpp_stanza_get_text(body);
if (!message) {
jid_destroy(jid);
return 1;
}
// determine if the notifications happened whilst offline
GTimeVal tv_stamp;
gboolean delayed = stanza_get_delay(stanza, &tv_stamp);
if (delayed) {
sv_ev_room_history(jid->barejid, jid->resourcepart, tv_stamp, message);
} else {
sv_ev_room_message(jid->barejid, jid->resourcepart, message);
}
xmpp_free(ctx, message);
jid_destroy(jid);
return 1;
}
void
_message_send_receipt(const char * const fulljid, const char * const message_id)
{
xmpp_conn_t * const conn = connection_get_conn();
xmpp_ctx_t * const ctx = connection_get_ctx();
xmpp_stanza_t *message = xmpp_stanza_new(ctx);
char *id = create_unique_id("receipt");
xmpp_stanza_set_name(message, STANZA_NAME_MESSAGE);
xmpp_stanza_set_id(message, id);
xmpp_stanza_set_attribute(message, STANZA_ATTR_TO, fulljid);
xmpp_stanza_t *receipt = xmpp_stanza_new(ctx);
xmpp_stanza_set_name(receipt, "received");
xmpp_stanza_set_ns(receipt, STANZA_NS_RECEIPTS);
xmpp_stanza_set_attribute(receipt, STANZA_ATTR_ID, message_id);
xmpp_stanza_add_child(message, receipt);
xmpp_stanza_release(receipt);
xmpp_send(conn, message);
xmpp_stanza_release(message);
}
static int
_chat_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
void * const userdata)
_receipt_received_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata)
{
xmpp_stanza_t *receipt = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_RECEIPTS);
char *name = xmpp_stanza_get_name(receipt);
if (g_strcmp0(name, "received") != 0) {
return 1;
}
char *id = xmpp_stanza_get_attribute(receipt, STANZA_ATTR_ID);
if (!id) {
return 1;
}
char *fulljid = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
if (!fulljid) {
return 1;
}
Jid *jidp = jid_create(fulljid);
sv_ev_message_receipt(jidp->barejid, id);
jid_destroy(jidp);
return 1;
}
void
_receipt_request_handler(xmpp_stanza_t * const stanza)
{
if (!prefs_get_boolean(PREF_RECEIPTS_SEND)) {
return;
}
char *id = xmpp_stanza_get_id(stanza);
if (!id) {
return;
}
xmpp_stanza_t *receipts = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_RECEIPTS);
if (!receipts) {
return;
}
char *receipts_name = xmpp_stanza_get_name(receipts);
if (g_strcmp0(receipts_name, "request") != 0) {
return;
}
gchar *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
Jid *jid = jid_create(from);
_message_send_receipt(jid->fulljid, id);
jid_destroy(jid);
}
void
_private_chat_handler(xmpp_stanza_t * const stanza, const char * const fulljid)
{
xmpp_stanza_t *body = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_BODY);
if (!body) {
return;
}
char *message = xmpp_stanza_get_text(body);
if (!message) {
return;
}
GTimeVal tv_stamp;
gboolean delayed = stanza_get_delay(stanza, &tv_stamp);
if (delayed) {
sv_ev_delayed_private_message(fulljid, message, tv_stamp);
} else {
sv_ev_incoming_private_message(fulljid, message);
}
xmpp_ctx_t *ctx = connection_get_ctx();
xmpp_free(ctx, message);
}
static gboolean
_handle_carbons(xmpp_stanza_t * const stanza)
{
xmpp_stanza_t *carbons = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_CARBONS);
if (!carbons) {
return FALSE;
}
char *name = xmpp_stanza_get_name(carbons);
if ((g_strcmp0(name, "received") == 0) || (g_strcmp0(name, "sent")) == 0) {
xmpp_stanza_t *forwarded = xmpp_stanza_get_child_by_ns(carbons, STANZA_NS_FORWARD);
xmpp_stanza_t *message = xmpp_stanza_get_child_by_name(forwarded, STANZA_NAME_MESSAGE);
xmpp_ctx_t *ctx = connection_get_ctx();
gchar *to = xmpp_stanza_get_attribute(message, STANZA_ATTR_TO);
gchar *from = xmpp_stanza_get_attribute(message, STANZA_ATTR_FROM);
// happens when receive a carbon of a self sent message
if (!to) to = from;
Jid *jid_from = jid_create(from);
Jid *jid_to = jid_create(to);
Jid *my_jid = jid_create(jabber_get_fulljid());
// check for and deal with message
xmpp_stanza_t *body = xmpp_stanza_get_child_by_name(message, STANZA_NAME_BODY);
if (body) {
char *message = xmpp_stanza_get_text(body);
if (message) {
// if we are the recipient, treat as standard incoming message
if(g_strcmp0(my_jid->barejid, jid_to->barejid) == 0){
sv_ev_incoming_message(jid_from->barejid, jid_from->resourcepart, message);
}
// else treat as a sent message
else{
sv_ev_carbon(jid_to->barejid, message);
}
xmpp_free(ctx, message);
}
}
jid_destroy(jid_from);
jid_destroy(jid_to);
jid_destroy(my_jid);
return TRUE;
}
return FALSE;
}
static int
_chat_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata)
{
// ignore if type not chat or absent
char *type = xmpp_stanza_get_type(stanza);
@ -423,6 +669,12 @@ _chat_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
return 1;
}
// check if carbon message
gboolean res = _handle_carbons(stanza);
if (res) {
return 1;
}
// ignore handled namespaces
xmpp_stanza_t *conf = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_CONFERENCE);
xmpp_stanza_t *mucuser = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_MUC_USER);
@ -431,76 +683,57 @@ _chat_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
return 1;
}
xmpp_ctx_t *ctx = connection_get_ctx();
gchar *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
Jid *jid = jid_create(from);
// private message from chat room use full jid (room/nick)
if (muc_active(jid->barejid)) {
// determine if the notifications happened whilst offline
GTimeVal tv_stamp;
gboolean delayed = stanza_get_delay(stanza, &tv_stamp);
// check for and deal with message
xmpp_stanza_t *body = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_BODY);
if (body != NULL) {
char *message = xmpp_stanza_get_text(body);
if (message != NULL) {
if (delayed) {
handle_delayed_private_message(jid->str, message, tv_stamp);
} else {
handle_incoming_private_message(jid->str, message);
}
xmpp_free(ctx, message);
}
}
jid_destroy(jid);
return 1;
// standard chat message, use jid without resource
} else {
// determine if the notifications happened whilst offline
GTimeVal tv_stamp;
gboolean delayed = stanza_get_delay(stanza, &tv_stamp);
// check for and deal with message
xmpp_stanza_t *body = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_BODY);
if (body != NULL) {
char *message = xmpp_stanza_get_text(body);
if (message != NULL) {
if (delayed) {
handle_delayed_message(jid->barejid, message, tv_stamp);
} else {
handle_incoming_message(jid->barejid, jid->resourcepart, message);
}
xmpp_free(ctx, message);
}
}
// handle chat sessions and states
if (!delayed && jid->resourcepart) {
gboolean gone = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_GONE) != NULL;
gboolean typing = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_COMPOSING) != NULL;
gboolean paused = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_PAUSED) != NULL;
gboolean inactive = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_INACTIVE) != NULL;
if (gone) {
handle_gone(jid->barejid, jid->resourcepart);
} else if (typing) {
handle_typing(jid->barejid, jid->resourcepart);
} else if (paused) {
handle_paused(jid->barejid, jid->resourcepart);
} else if (inactive) {
handle_inactive(jid->barejid, jid->resourcepart);
} else if (stanza_contains_chat_state(stanza)) {
handle_activity(jid->barejid, jid->resourcepart, TRUE);
} else {
handle_activity(jid->barejid, jid->resourcepart, FALSE);
}
}
jid_destroy(jid);
_private_chat_handler(stanza, jid->fulljid);
return 1;
}
}
// standard chat message, use jid without resource
GTimeVal tv_stamp;
gboolean delayed = stanza_get_delay(stanza, &tv_stamp);
xmpp_stanza_t *body = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_BODY);
if (body) {
char *message = xmpp_stanza_get_text(body);
if (message) {
if (delayed) {
sv_ev_delayed_message(jid->barejid, message, tv_stamp);
} else {
sv_ev_incoming_message(jid->barejid, jid->resourcepart, message);
}
_receipt_request_handler(stanza);
xmpp_ctx_t *ctx = connection_get_ctx();
xmpp_free(ctx, message);
}
}
// handle chat sessions and states
if (!delayed && jid->resourcepart) {
gboolean gone = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_GONE) != NULL;
gboolean typing = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_COMPOSING) != NULL;
gboolean paused = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_PAUSED) != NULL;
gboolean inactive = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_INACTIVE) != NULL;
if (gone) {
sv_ev_gone(jid->barejid, jid->resourcepart);
} else if (typing) {
sv_ev_typing(jid->barejid, jid->resourcepart);
} else if (paused) {
sv_ev_paused(jid->barejid, jid->resourcepart);
} else if (inactive) {
sv_ev_inactive(jid->barejid, jid->resourcepart);
} else if (stanza_contains_chat_state(stanza)) {
sv_ev_activity(jid->barejid, jid->resourcepart, TRUE);
} else {
sv_ev_activity(jid->barejid, jid->resourcepart, FALSE);
}
}
jid_destroy(jid);
return 1;
}

View File

@ -1,7 +1,7 @@
/*
* message.h
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*

View File

@ -1,7 +1,7 @@
/*
* presence.c
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*
@ -44,7 +44,8 @@
#include "log.h"
#include "muc.h"
#include "profanity.h"
#include "server_events.h"
#include "ui/ui.h"
#include "event/server_events.h"
#include "xmpp/capabilities.h"
#include "xmpp/connection.h"
#include "xmpp/stanza.h"
@ -170,7 +171,7 @@ presence_sub_request_exists(const char * const bare_jid)
GSList *requests_p = autocomplete_create_list(sub_requests_ac);
GSList *requests = requests_p;
while (requests != NULL) {
while (requests) {
if (strcmp(requests->data, bare_jid) == 0) {
result = TRUE;
break;
@ -178,7 +179,7 @@ presence_sub_request_exists(const char * const bare_jid)
requests = g_slist_next(requests);
}
if (requests_p != NULL) {
if (requests_p) {
g_slist_free_full(requests_p, free);
}
@ -192,27 +193,22 @@ presence_reset_sub_request_search(void)
}
void
presence_update(const resource_presence_t presence_type, const char * const msg,
const int idle)
presence_send(const resource_presence_t presence_type, const char * const msg, const int idle)
{
if (jabber_get_connection_status() != JABBER_CONNECTED) {
log_warning("Error setting presence, not connected.");
return;
}
if (msg != NULL) {
log_debug("Updating presence: %s, \"%s\"",
string_from_resource_presence(presence_type), msg);
if (msg) {
log_debug("Updating presence: %s, \"%s\"", string_from_resource_presence(presence_type), msg);
} else {
log_debug("Updating presence: %s",
string_from_resource_presence(presence_type));
log_debug("Updating presence: %s", string_from_resource_presence(presence_type));
}
xmpp_ctx_t * const ctx = connection_get_ctx();
xmpp_conn_t * const conn = connection_get_conn();
const int pri =
accounts_get_priority_for_presence_type(jabber_get_account_name(),
presence_type);
const int pri = accounts_get_priority_for_presence_type(jabber_get_account_name(), presence_type);
const char *show = stanza_get_presence_string_from_type(presence_type);
connection_set_presence_message(msg);
@ -245,11 +241,11 @@ _send_room_presence(xmpp_conn_t *conn, xmpp_stanza_t *presence)
GList *rooms_p = muc_rooms();
GList *rooms = rooms_p;
while (rooms != NULL) {
while (rooms) {
const char *room = rooms->data;
const char *nick = muc_nick(room);
if (nick != NULL) {
if (nick) {
char *full_room_jid = create_fulljid(room, nick);
xmpp_stanza_set_attribute(presence, STANZA_ATTR_TO, full_room_jid);
@ -261,7 +257,7 @@ _send_room_presence(xmpp_conn_t *conn, xmpp_stanza_t *presence)
rooms = g_list_next(rooms);
}
if (rooms_p != NULL) {
if (rooms_p) {
g_list_free(rooms_p);
}
}
@ -333,7 +329,7 @@ presence_leave_chat_room(const char * const room_jid)
xmpp_conn_t *conn = connection_get_conn();
char *nick = muc_nick(room_jid);
if (nick != NULL) {
if (nick) {
xmpp_stanza_t *presence = stanza_create_room_leave_presence(ctx, room_jid,
nick);
xmpp_send(conn, presence);
@ -350,11 +346,11 @@ _presence_error_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
xmpp_stanza_t *error_stanza = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_ERROR);
xmpp_stanza_t *x = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_X);
char *xmlns = NULL;
if (x != NULL) {
if (x) {
xmlns = xmpp_stanza_get_ns(x);
}
char *type = NULL;
if (error_stanza != NULL) {
if (error_stanza) {
type = xmpp_stanza_get_attribute(error_stanza, STANZA_ATTR_TYPE);
}
@ -364,7 +360,7 @@ _presence_error_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
char *error_cond = NULL;
xmpp_stanza_t *reason_st = xmpp_stanza_get_child_by_ns(error_stanza, STANZA_NS_STANZAS);
if (reason_st != NULL) {
if (reason_st) {
error_cond = xmpp_stanza_get_name(reason_st);
}
if (error_cond == NULL) {
@ -372,7 +368,10 @@ _presence_error_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
}
log_info("Error joining room: %s, reason: %s", fulljid->barejid, error_cond);
handle_room_join_error(fulljid->barejid, error_cond);
if (muc_active(fulljid->barejid)) {
muc_leave(fulljid->barejid);
}
ui_handle_room_join_error(fulljid->barejid, error_cond);
jid_destroy(fulljid);
return 1;
}
@ -381,15 +380,15 @@ _presence_error_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
char *err_msg = stanza_get_error_message(stanza);
GString *log_msg = g_string_new("presence stanza error received");
if (id != NULL) {
if (id) {
g_string_append(log_msg, " id=");
g_string_append(log_msg, id);
}
if (from != NULL) {
if (from) {
g_string_append(log_msg, " from=");
g_string_append(log_msg, from);
}
if (type != NULL) {
if (type) {
g_string_append(log_msg, " type=");
g_string_append(log_msg, type);
}
@ -400,7 +399,11 @@ _presence_error_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
g_string_free(log_msg, TRUE);
handle_presence_error(from, type, err_msg);
if (from) {
ui_handle_recipient_error(from, err_msg);
} else {
ui_handle_error(err_msg);
}
free(err_msg);
@ -416,7 +419,7 @@ _unsubscribed_handler(xmpp_conn_t * const conn,
Jid *from_jid = jid_create(from);
log_debug("Unsubscribed presence handler fired for %s", from);
handle_subscription(from_jid->barejid, PRESENCE_UNSUBSCRIBED);
sv_ev_subscription(from_jid->barejid, PRESENCE_UNSUBSCRIBED);
autocomplete_remove(sub_requests_ac, from_jid->barejid);
jid_destroy(from_jid);
@ -432,7 +435,7 @@ _subscribed_handler(xmpp_conn_t * const conn,
Jid *from_jid = jid_create(from);
log_debug("Subscribed presence handler fired for %s", from);
handle_subscription(from_jid->barejid, PRESENCE_SUBSCRIBED);
sv_ev_subscription(from_jid->barejid, PRESENCE_SUBSCRIBED);
autocomplete_remove(sub_requests_ac, from_jid->barejid);
jid_destroy(from_jid);
@ -452,7 +455,7 @@ _subscribe_handler(xmpp_conn_t * const conn,
return 1;
}
handle_subscription(from_jid->barejid, PRESENCE_SUBSCRIBE);
sv_ev_subscription(from_jid->barejid, PRESENCE_SUBSCRIBE);
autocomplete_add(sub_requests_ac, from_jid->barejid);
jid_destroy(from_jid);
@ -464,6 +467,8 @@ static int
_unavailable_handler(xmpp_conn_t * const conn,
xmpp_stanza_t * const stanza, void * const userdata)
{
ui_input_nonblocking(TRUE);
const char *jid = xmpp_conn_get_jid(conn);
char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
log_debug("Unavailable presence handler fired for %s", from);
@ -479,15 +484,15 @@ _unavailable_handler(xmpp_conn_t * const conn,
char *status_str = stanza_get_status(stanza, NULL);
if (strcmp(my_jid->barejid, from_jid->barejid) !=0) {
if (from_jid->resourcepart != NULL) {
handle_contact_offline(from_jid->barejid, from_jid->resourcepart, status_str);
if (from_jid->resourcepart) {
sv_ev_contact_offline(from_jid->barejid, from_jid->resourcepart, status_str);
// hack for servers that do not send full jid with unavailable presence
} else {
handle_contact_offline(from_jid->barejid, "__prof_default", status_str);
sv_ev_contact_offline(from_jid->barejid, "__prof_default", status_str);
}
} else {
if (from_jid->resourcepart != NULL) {
if (from_jid->resourcepart) {
connection_remove_available_resource(from_jid->resourcepart);
}
}
@ -517,7 +522,7 @@ _handle_caps(char *jid, XMPPCaps *caps)
}
}
// unsupported hash, xep-0115, assoiciate with JID, no cache
// unsupported hash, xep-0115, associate with JID, no cache
} else if (caps->hash) {
log_info("Hash %s not supported: %s, sending service discovery request", caps->hash, jid);
char *id = create_unique_id("caps");
@ -539,6 +544,8 @@ static int
_available_handler(xmpp_conn_t * const conn,
xmpp_stanza_t * const stanza, void * const userdata)
{
ui_input_nonblocking(TRUE);
// handler still fires if error
if (g_strcmp0(xmpp_stanza_get_type(stanza), STANZA_TYPE_ERROR) == 0) {
return 1;
@ -596,7 +603,7 @@ _available_handler(xmpp_conn_t * const conn,
if (g_strcmp0(xmpp_presence->jid->barejid, my_jid->barejid) == 0) {
connection_add_available_resource(resource);
} else {
handle_contact_online(xmpp_presence->jid->barejid, resource, xmpp_presence->last_activity);
sv_ev_contact_online(xmpp_presence->jid->barejid, resource, xmpp_presence->last_activity);
}
jid_destroy(my_jid);
@ -611,7 +618,7 @@ _send_caps_request(char *node, char *caps_key, char *id, char *from)
xmpp_ctx_t *ctx = connection_get_ctx();
xmpp_conn_t *conn = connection_get_conn();
if (node != NULL) {
if (node) {
log_debug("Node string: %s.", node);
if (!caps_contains(caps_key)) {
log_debug("Capabilities not cached for '%s', sending discovery IQ.", from);
@ -629,6 +636,8 @@ _send_caps_request(char *node, char *caps_key, char *id, char *from)
static int
_muc_user_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata)
{
ui_input_nonblocking(TRUE);
char *type = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_TYPE);
char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
@ -682,27 +691,27 @@ _muc_user_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void *
char *new_jid = stanza_get_muc_destroy_alternative_room(stanza);
char *password = stanza_get_muc_destroy_alternative_password(stanza);
char *reason = stanza_get_muc_destroy_reason(stanza);
handle_room_destroyed(room, new_jid, password, reason);
sv_ev_room_destroyed(room, new_jid, password, reason);
free(password);
free(reason);
// kicked from room
} else if (g_slist_find_custom(status_codes, "307", (GCompareFunc)g_strcmp0) != NULL) {
} else if (g_slist_find_custom(status_codes, "307", (GCompareFunc)g_strcmp0)) {
char *actor = stanza_get_actor(stanza);
char *reason = stanza_get_reason(stanza);
handle_room_kicked(room, actor, reason);
sv_ev_room_kicked(room, actor, reason);
free(reason);
// banned from room
} else if (g_slist_find_custom(status_codes, "301", (GCompareFunc)g_strcmp0) != NULL) {
} else if (g_slist_find_custom(status_codes, "301", (GCompareFunc)g_strcmp0)) {
char *actor = stanza_get_actor(stanza);
char *reason = stanza_get_reason(stanza);
handle_room_banned(room, actor, reason);
sv_ev_room_banned(room, actor, reason);
free(reason);
// normal exit
} else {
handle_leave_room(room);
sv_ev_leave_room(room);
}
g_slist_free_full(status_codes, free);
@ -713,7 +722,7 @@ _muc_user_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void *
gboolean config_required = stanza_muc_requires_config(stanza);
char *actor = stanza_get_actor(stanza);
char *reason = stanza_get_reason(stanza);
handle_muc_self_online(room, nick, config_required, role, affiliation, actor, reason, jid, show_str, status_str);
sv_ev_muc_self_online(room, nick, config_required, role, affiliation, actor, reason, jid, show_str, status_str);
}
// handle presence from room members
@ -732,22 +741,22 @@ _muc_user_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void *
GSList *status_codes = stanza_get_status_codes_by_ns(stanza, STANZA_NS_MUC_USER);
// kicked from room
if (g_slist_find_custom(status_codes, "307", (GCompareFunc)g_strcmp0) != NULL) {
if (g_slist_find_custom(status_codes, "307", (GCompareFunc)g_strcmp0)) {
char *actor = stanza_get_actor(stanza);
char *reason = stanza_get_reason(stanza);
handle_room_occupent_kicked(room, nick, actor, reason);
sv_ev_room_occupent_kicked(room, nick, actor, reason);
free(reason);
// banned from room
} else if (g_slist_find_custom(status_codes, "301", (GCompareFunc)g_strcmp0) != NULL) {
} else if (g_slist_find_custom(status_codes, "301", (GCompareFunc)g_strcmp0)) {
char *actor = stanza_get_actor(stanza);
char *reason = stanza_get_reason(stanza);
handle_room_occupent_banned(room, nick, actor, reason);
sv_ev_room_occupent_banned(room, nick, actor, reason);
free(reason);
// normal exit
} else {
handle_room_occupant_offline(room, nick, "offline", status_str);
sv_ev_room_occupant_offline(room, nick, "offline", status_str);
}
g_slist_free_full(status_codes, free);
@ -765,7 +774,7 @@ _muc_user_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void *
char *actor = stanza_get_actor(stanza);
char *reason = stanza_get_reason(stanza);
handle_muc_occupant_online(room, nick, jid, role, affiliation, actor, reason, show_str, status_str);
sv_ev_muc_occupant_online(room, nick, jid, role, affiliation, actor, reason, show_str, status_str);
}
}

View File

@ -1,7 +1,7 @@
/*
* presence.h
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*

View File

@ -1,7 +1,7 @@
/*
* roster.c
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*
@ -41,7 +41,9 @@
#include "log.h"
#include "profanity.h"
#include "server_events.h"
#include "ui/ui.h"
#include "event/server_events.h"
#include "event/client_events.h"
#include "tools/autocomplete.h"
#include "xmpp/connection.h"
#include "xmpp/roster.h"
@ -131,7 +133,7 @@ roster_send_add_to_group(const char * const group, PContact contact)
{
GSList *groups = p_contact_groups(contact);
GSList *new_groups = NULL;
while (groups != NULL) {
while (groups) {
new_groups = g_slist_append(new_groups, strdup(groups->data));
groups = g_slist_next(groups);
}
@ -141,7 +143,7 @@ roster_send_add_to_group(const char * const group, PContact contact)
char *unique_id = create_unique_id(NULL);
GroupData *data = malloc(sizeof(GroupData));
data->group = strdup(group);
if (p_contact_name(contact) != NULL) {
if (p_contact_name(contact)) {
data->name = strdup(p_contact_name(contact));
} else {
data->name = strdup(p_contact_barejid(contact));
@ -161,9 +163,9 @@ static int
_group_add_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
void * const userdata)
{
if (userdata != NULL) {
if (userdata) {
GroupData *data = userdata;
handle_group_add(data->name, data->group);
ui_group_added(data->name, data->group);
free(data->name);
free(data->group);
free(userdata);
@ -176,7 +178,7 @@ roster_send_remove_from_group(const char * const group, PContact contact)
{
GSList *groups = p_contact_groups(contact);
GSList *new_groups = NULL;
while (groups != NULL) {
while (groups) {
if (strcmp(groups->data, group) != 0) {
new_groups = g_slist_append(new_groups, strdup(groups->data));
}
@ -190,7 +192,7 @@ roster_send_remove_from_group(const char * const group, PContact contact)
char *unique_id = create_unique_id(NULL);
GroupData *data = malloc(sizeof(GroupData));
data->group = strdup(group);
if (p_contact_name(contact) != NULL) {
if (p_contact_name(contact)) {
data->name = strdup(p_contact_name(contact));
} else {
data->name = strdup(p_contact_barejid(contact));
@ -208,9 +210,9 @@ static int
_group_remove_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
void * const userdata)
{
if (userdata != NULL) {
if (userdata) {
GroupData *data = userdata;
handle_group_remove(data->name, data->group);
ui_group_removed(data->name, data->group);
free(data->name);
free(data->group);
free(userdata);
@ -234,13 +236,14 @@ _roster_set_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
// if from attribute exists and it is not current users barejid, ignore push
Jid *my_jid = jid_create(jabber_get_fulljid());
const char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
if ((from != NULL) && (strcmp(from, my_jid->barejid) != 0)) {
if (from && (strcmp(from, my_jid->barejid) != 0)) {
jid_destroy(my_jid);
return 1;
}
jid_destroy(my_jid);
const char *barejid = xmpp_stanza_get_attribute(item, STANZA_ATTR_JID);
gchar *barejid_lower = g_utf8_strdown(barejid, -1);
const char *name = xmpp_stanza_get_attribute(item, STANZA_ATTR_NAME);
const char *sub = xmpp_stanza_get_attribute(item, STANZA_ATTR_SUBSCRIPTION);
const char *ask = xmpp_stanza_get_attribute(item, STANZA_ATTR_ASK);
@ -254,83 +257,83 @@ _roster_set_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
if (g_strcmp0(sub, "remove") == 0) {
// remove barejid and name
if (name == NULL) {
name = barejid;
name = barejid_lower;
}
roster_remove(name, barejid);
handle_roster_remove(barejid);
roster_remove(name, barejid_lower);
ui_roster_remove(barejid_lower);
// otherwise update local roster
} else {
// check for pending out subscriptions
gboolean pending_out = FALSE;
if ((ask != NULL) && (strcmp(ask, "subscribe") == 0)) {
if (ask && (strcmp(ask, "subscribe") == 0)) {
pending_out = TRUE;
}
GSList *groups = _get_groups_from_item(item);
// update the local roster
PContact contact = roster_get_contact(barejid);
PContact contact = roster_get_contact(barejid_lower);
if (contact == NULL) {
gboolean added = roster_add(barejid, name, groups, sub, pending_out);
gboolean added = roster_add(barejid_lower, name, groups, sub, pending_out);
if (added) {
handle_roster_add(barejid, name);
ui_roster_add(barejid_lower, name);
}
} else {
handle_roster_update(barejid, name, groups, sub, pending_out);
sv_ev_roster_update(barejid_lower, name, groups, sub, pending_out);
}
}
g_free(barejid_lower);
return 1;
}
static int
_roster_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
void * const userdata)
_roster_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata)
{
const char *id = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_ID);
if (g_strcmp0(id, "roster") != 0) {
return 1;
}
// handle initial roster response
if (g_strcmp0(id, "roster") == 0) {
xmpp_stanza_t *query = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_QUERY);
xmpp_stanza_t *item = xmpp_stanza_get_children(query);
xmpp_stanza_t *query = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_QUERY);
xmpp_stanza_t *item = xmpp_stanza_get_children(query);
while (item != NULL) {
const char *barejid = xmpp_stanza_get_attribute(item, STANZA_ATTR_JID);
const char *name = xmpp_stanza_get_attribute(item, STANZA_ATTR_NAME);
const char *sub = xmpp_stanza_get_attribute(item, STANZA_ATTR_SUBSCRIPTION);
while (item) {
const char *barejid = xmpp_stanza_get_attribute(item, STANZA_ATTR_JID);
gchar *barejid_lower = g_utf8_strdown(barejid, -1);
const char *name = xmpp_stanza_get_attribute(item, STANZA_ATTR_NAME);
const char *sub = xmpp_stanza_get_attribute(item, STANZA_ATTR_SUBSCRIPTION);
// do not set nickname to empty string, set to NULL instead
if (name && (strlen(name) == 0)) {
name = NULL;
}
// do not set nickname to empty string, set to NULL instead
if (name && (strlen(name) == 0)) name = NULL;
gboolean pending_out = FALSE;
const char *ask = xmpp_stanza_get_attribute(item, STANZA_ATTR_ASK);
if (g_strcmp0(ask, "subscribe") == 0) {
pending_out = TRUE;
}
GSList *groups = _get_groups_from_item(item);
gboolean added = roster_add(barejid, name, groups, sub, pending_out);
if (!added) {
log_warning("Attempt to add contact twice: %s", barejid);
}
item = xmpp_stanza_get_next(item);
gboolean pending_out = FALSE;
const char *ask = xmpp_stanza_get_attribute(item, STANZA_ATTR_ASK);
if (g_strcmp0(ask, "subscribe") == 0) {
pending_out = TRUE;
}
handle_roster_received();
GSList *groups = _get_groups_from_item(item);
resource_presence_t conn_presence = accounts_get_login_presence(jabber_get_account_name());
presence_update(conn_presence, NULL, 0);
gboolean added = roster_add(barejid_lower, name, groups, sub, pending_out);
if (!added) {
log_warning("Attempt to add contact twice: %s", barejid_lower);
}
g_free(barejid_lower);
item = xmpp_stanza_get_next(item);
}
sv_ev_roster_received();
resource_presence_t conn_presence = accounts_get_login_presence(jabber_get_account_name());
cl_ev_presence_send(conn_presence, NULL, 0);
return 1;
}
@ -340,10 +343,10 @@ _get_groups_from_item(xmpp_stanza_t *item)
GSList *groups = NULL;
xmpp_stanza_t *group_element = xmpp_stanza_get_children(item);
while (group_element != NULL) {
while (group_element) {
if (strcmp(xmpp_stanza_get_name(group_element), STANZA_NAME_GROUP) == 0) {
char *groupname = xmpp_stanza_get_text(group_element);
if (groupname != NULL) {
if (groupname) {
groups = g_slist_append(groups, groupname);
}
}

View File

@ -1,7 +1,7 @@
/*
* roster.h
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*

View File

@ -1,7 +1,7 @@
/*
* stanza.c
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*
@ -141,7 +141,7 @@ stanza_create_bookmarks_pubsub_add(xmpp_ctx_t *ctx, const char * const jid,
xmpp_stanza_set_attribute(conference, STANZA_ATTR_AUTOJOIN, "false");
}
if (nick != NULL) {
if (nick) {
xmpp_stanza_t *nick_st = xmpp_stanza_new(ctx);
xmpp_stanza_set_name(nick_st, STANZA_NAME_NICK);
xmpp_stanza_set_text(nick_st, nick);
@ -198,6 +198,44 @@ stanza_create_bookmarks_pubsub_add(xmpp_ctx_t *ctx, const char * const jid,
}
#endif
xmpp_stanza_t *
stanza_enable_carbons(xmpp_ctx_t *ctx){
xmpp_stanza_t *iq = xmpp_stanza_new(ctx);
char *id = create_unique_id("carbons");
xmpp_stanza_set_name(iq, STANZA_NAME_IQ);
xmpp_stanza_set_type(iq, STANZA_TYPE_SET);
xmpp_stanza_set_id(iq, id);
free(id);
xmpp_stanza_t *carbons_enable = xmpp_stanza_new(ctx);
xmpp_stanza_set_name(carbons_enable, STANZA_NAME_ENABLE);
xmpp_stanza_set_ns(carbons_enable, STANZA_NS_CARBONS);
xmpp_stanza_add_child(iq, carbons_enable);
return iq;
}
xmpp_stanza_t *
stanza_disable_carbons(xmpp_ctx_t *ctx){
xmpp_stanza_t *iq = xmpp_stanza_new(ctx);
char *id = create_unique_id("carbons");
xmpp_stanza_set_name(iq, STANZA_NAME_IQ);
xmpp_stanza_set_type(iq, STANZA_TYPE_SET);
xmpp_stanza_set_id(iq, id);
free(id);
xmpp_stanza_t *carbons_disable = xmpp_stanza_new(ctx);
xmpp_stanza_set_name(carbons_disable, STANZA_NAME_DISABLE);
xmpp_stanza_set_ns(carbons_disable, STANZA_NS_CARBONS);
xmpp_stanza_add_child(iq, carbons_disable);
return iq;
}
xmpp_stanza_t *
stanza_create_chat_state(xmpp_ctx_t *ctx, const char * const fulljid, const char * const state)
{
@ -244,9 +282,44 @@ stanza_create_room_subject_message(xmpp_ctx_t *ctx, const char * const room, con
}
xmpp_stanza_t *
stanza_create_message(xmpp_ctx_t *ctx, const char * const recipient,
const char * const type, const char * const message,
const char * const state)
stanza_attach_state(xmpp_ctx_t *ctx, xmpp_stanza_t *stanza, const char * const state)
{
xmpp_stanza_t *chat_state = xmpp_stanza_new(ctx);
xmpp_stanza_set_name(chat_state, state);
xmpp_stanza_set_ns(chat_state, STANZA_NS_CHATSTATES);
xmpp_stanza_add_child(stanza, chat_state);
xmpp_stanza_release(chat_state);
return stanza;
}
xmpp_stanza_t *
stanza_attach_carbons_private(xmpp_ctx_t *ctx, xmpp_stanza_t *stanza)
{
xmpp_stanza_t *private_carbon = xmpp_stanza_new(ctx);
xmpp_stanza_set_name(private_carbon, "private");
xmpp_stanza_set_ns(private_carbon, STANZA_NS_CARBONS);
xmpp_stanza_add_child(stanza, private_carbon);
xmpp_stanza_release(private_carbon);
return stanza;
}
xmpp_stanza_t *
stanza_attach_receipt_request(xmpp_ctx_t *ctx, xmpp_stanza_t *stanza)
{
xmpp_stanza_t *receipet_request = xmpp_stanza_new(ctx);
xmpp_stanza_set_name(receipet_request, "request");
xmpp_stanza_set_ns(receipet_request, STANZA_NS_RECEIPTS);
xmpp_stanza_add_child(stanza, receipet_request);
xmpp_stanza_release(receipet_request);
return stanza;
}
xmpp_stanza_t *
stanza_create_message(xmpp_ctx_t *ctx, char *id, const char * const recipient,
const char * const type, const char * const message)
{
xmpp_stanza_t *msg, *body, *text;
@ -254,9 +327,7 @@ stanza_create_message(xmpp_ctx_t *ctx, const char * const recipient,
xmpp_stanza_set_name(msg, STANZA_NAME_MESSAGE);
xmpp_stanza_set_type(msg, type);
xmpp_stanza_set_attribute(msg, STANZA_ATTR_TO, recipient);
char *id = create_unique_id(NULL);
xmpp_stanza_set_id(msg, id);
free(id);
body = xmpp_stanza_new(ctx);
xmpp_stanza_set_name(body, STANZA_NAME_BODY);
@ -268,14 +339,6 @@ stanza_create_message(xmpp_ctx_t *ctx, const char * const recipient,
xmpp_stanza_add_child(msg, body);
xmpp_stanza_release(body);
if (state != NULL) {
xmpp_stanza_t *chat_state = xmpp_stanza_new(ctx);
xmpp_stanza_set_name(chat_state, state);
xmpp_stanza_set_ns(chat_state, STANZA_NS_CHATSTATES);
xmpp_stanza_add_child(msg, chat_state);
xmpp_stanza_release(chat_state);
}
return msg;
}
@ -311,7 +374,7 @@ stanza_create_roster_set(xmpp_ctx_t *ctx, const char * const id,
xmpp_stanza_t *iq = xmpp_stanza_new(ctx);
xmpp_stanza_set_name(iq, STANZA_NAME_IQ);
xmpp_stanza_set_type(iq, STANZA_TYPE_SET);
if (id != NULL) {
if (id) {
xmpp_stanza_set_id(iq, id);
}
@ -323,13 +386,13 @@ stanza_create_roster_set(xmpp_ctx_t *ctx, const char * const id,
xmpp_stanza_set_name(item, STANZA_NAME_ITEM);
xmpp_stanza_set_attribute(item, STANZA_ATTR_JID, jid);
if (handle != NULL) {
if (handle) {
xmpp_stanza_set_attribute(item, STANZA_ATTR_NAME, handle);
} else {
xmpp_stanza_set_attribute(item, STANZA_ATTR_NAME, "");
}
while (groups != NULL) {
while (groups) {
xmpp_stanza_t *group = xmpp_stanza_new(ctx);
xmpp_stanza_t *groupname = xmpp_stanza_new(ctx);
xmpp_stanza_set_name(group, STANZA_NAME_GROUP);
@ -351,7 +414,7 @@ stanza_create_roster_set(xmpp_ctx_t *ctx, const char * const id,
xmpp_stanza_t *
stanza_create_invite(xmpp_ctx_t *ctx, const char * const room,
const char * const contact, const char * const reason)
const char * const contact, const char * const reason, const char * const password)
{
xmpp_stanza_t *message, *x;
@ -367,9 +430,12 @@ stanza_create_invite(xmpp_ctx_t *ctx, const char * const room,
xmpp_stanza_set_ns(x, STANZA_NS_CONFERENCE);
xmpp_stanza_set_attribute(x, STANZA_ATTR_JID, room);
if (reason != NULL) {
if (reason) {
xmpp_stanza_set_attribute(x, STANZA_ATTR_REASON, reason);
}
if (password) {
xmpp_stanza_set_attribute(x, STANZA_ATTR_PASSWORD, password);
}
xmpp_stanza_add_child(message, x);
xmpp_stanza_release(x);
@ -377,6 +443,46 @@ stanza_create_invite(xmpp_ctx_t *ctx, const char * const room,
return message;
}
xmpp_stanza_t *
stanza_create_mediated_invite(xmpp_ctx_t *ctx, const char * const room,
const char * const contact, const char * const reason)
{
xmpp_stanza_t *message, *x, *invite;
message = xmpp_stanza_new(ctx);
xmpp_stanza_set_name(message, STANZA_NAME_MESSAGE);
xmpp_stanza_set_attribute(message, STANZA_ATTR_TO, room);
char *id = create_unique_id(NULL);
xmpp_stanza_set_id(message, id);
free(id);
x = xmpp_stanza_new(ctx);
xmpp_stanza_set_name(x, STANZA_NAME_X);
xmpp_stanza_set_ns(x, STANZA_NS_MUC_USER);
invite = xmpp_stanza_new(ctx);
xmpp_stanza_set_name(invite, STANZA_NAME_INVITE);
xmpp_stanza_set_attribute(invite, STANZA_ATTR_TO, contact);
if (reason) {
xmpp_stanza_t *reason_st = xmpp_stanza_new(ctx);
xmpp_stanza_set_name(reason_st, STANZA_NAME_REASON);
xmpp_stanza_t *reason_txt = xmpp_stanza_new(ctx);
xmpp_stanza_set_text(reason_txt, reason);
xmpp_stanza_add_child(reason_st, reason_txt);
xmpp_stanza_release(reason_txt);
xmpp_stanza_add_child(invite, reason_st);
xmpp_stanza_release(reason_st);
}
xmpp_stanza_add_child(x, invite);
xmpp_stanza_release(invite);
xmpp_stanza_add_child(message, x);
xmpp_stanza_release(x);
return message;
}
xmpp_stanza_t *
stanza_create_room_join_presence(xmpp_ctx_t * const ctx,
const char * const full_room_jid, const char * const passwd)
@ -393,7 +499,7 @@ stanza_create_room_join_presence(xmpp_ctx_t * const ctx,
xmpp_stanza_set_ns(x, STANZA_NS_MUC);
// if a password was given
if (passwd != NULL) {
if (passwd) {
xmpp_stanza_t *pass = xmpp_stanza_new(ctx);
xmpp_stanza_set_name(pass, "password");
xmpp_stanza_t *text = xmpp_stanza_new(ctx);
@ -787,7 +893,7 @@ stanza_create_disco_info_iq(xmpp_ctx_t *ctx, const char * const id, const char *
xmpp_stanza_t *query = xmpp_stanza_new(ctx);
xmpp_stanza_set_name(query, STANZA_NAME_QUERY);
xmpp_stanza_set_ns(query, XMPP_NS_DISCO_INFO);
if (node != NULL) {
if (node) {
xmpp_stanza_set_attribute(query, STANZA_ATTR_NODE, node);
}
@ -858,7 +964,7 @@ stanza_create_ping_iq(xmpp_ctx_t *ctx, const char * const target)
xmpp_stanza_t *iq = xmpp_stanza_new(ctx);
xmpp_stanza_set_name(iq, STANZA_NAME_IQ);
xmpp_stanza_set_type(iq, STANZA_TYPE_GET);
if (target != NULL) {
if (target) {
xmpp_stanza_set_attribute(iq, STANZA_ATTR_TO, target);
}
char *id = create_unique_id("ping");
@ -881,11 +987,11 @@ stanza_get_delay(xmpp_stanza_t * const stanza, GTimeVal *tv_stamp)
{
// first check for XEP-0203 delayed delivery
xmpp_stanza_t *delay = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_DELAY);
if (delay != NULL) {
if (delay) {
char *xmlns = xmpp_stanza_get_attribute(delay, STANZA_ATTR_XMLNS);
if ((xmlns != NULL) && (strcmp(xmlns, "urn:xmpp:delay") == 0)) {
if (xmlns && (strcmp(xmlns, "urn:xmpp:delay") == 0)) {
char *stamp = xmpp_stanza_get_attribute(delay, STANZA_ATTR_STAMP);
if ((stamp != NULL) && (g_time_val_from_iso8601(stamp, tv_stamp))) {
if (stamp && (g_time_val_from_iso8601(stamp, tv_stamp))) {
return TRUE;
}
}
@ -894,11 +1000,11 @@ stanza_get_delay(xmpp_stanza_t * const stanza, GTimeVal *tv_stamp)
// otherwise check for XEP-0091 legacy delayed delivery
// stanp format : CCYYMMDDThh:mm:ss
xmpp_stanza_t *x = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_X);
if (x != NULL) {
if (x) {
char *xmlns = xmpp_stanza_get_attribute(x, STANZA_ATTR_XMLNS);
if ((xmlns != NULL) && (strcmp(xmlns, "jabber:x:delay") == 0)) {
if (xmlns && (strcmp(xmlns, "jabber:x:delay") == 0)) {
char *stamp = xmpp_stanza_get_attribute(x, STANZA_ATTR_STAMP);
if ((stamp != NULL) && (g_time_val_from_iso8601(stamp, tv_stamp))) {
if (stamp && (g_time_val_from_iso8601(stamp, tv_stamp))) {
return TRUE;
}
}
@ -914,17 +1020,17 @@ stanza_get_status(xmpp_stanza_t *stanza, char *def)
xmpp_stanza_t *status =
xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_STATUS);
if (status != NULL) {
if (status) {
// xmpp_free and free may be different functions so convert all to
// libc malloc
char *s1, *s2 = NULL;
s1 = xmpp_stanza_get_text(status);
if (s1 != NULL) {
if (s1) {
s2 = strdup(s1);
xmpp_free(ctx, s1);
}
return s2;
} else if (def != NULL) {
} else if (def) {
return strdup(def);
} else {
return NULL;
@ -938,17 +1044,17 @@ stanza_get_show(xmpp_stanza_t *stanza, char *def)
xmpp_stanza_t *show =
xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_SHOW);
if (show != NULL) {
if (show) {
// xmpp_free and free may be different functions so convert all to
// libc malloc
char *s1, *s2 = NULL;
s1 = xmpp_stanza_get_text(show);
if (s1 != NULL) {
if (s1) {
s2 = strdup(s1);
xmpp_free(ctx, s1);
}
return s2;
} else if (def != NULL) {
} else if (def) {
return strdup(def);
} else {
return NULL;
@ -984,7 +1090,7 @@ stanza_muc_requires_config(xmpp_stanza_t * const stanza)
// muc user namespaced x element
xmpp_stanza_t *x = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_MUC_USER);
if (x != NULL) {
if (x) {
// check for item element with owner affiliation
xmpp_stanza_t *item = xmpp_stanza_get_child_by_name(x, "item");
@ -998,7 +1104,7 @@ stanza_muc_requires_config(xmpp_stanza_t * const stanza)
// check for status code 201
xmpp_stanza_t *x_children = xmpp_stanza_get_children(x);
while (x_children != NULL) {
while (x_children) {
if (g_strcmp0(xmpp_stanza_get_name(x_children), STANZA_NAME_STATUS) == 0) {
char *code = xmpp_stanza_get_attribute(x_children, STANZA_ATTR_CODE);
if (g_strcmp0(code, "201") == 0) {
@ -1240,11 +1346,11 @@ stanza_is_room_nick_change(xmpp_stanza_t * const stanza)
// muc user namespaced x element
xmpp_stanza_t *x = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_MUC_USER);
if (x != NULL) {
if (x) {
// check for status child element with 303 code
xmpp_stanza_t *x_children = xmpp_stanza_get_children(x);
while (x_children != NULL) {
while (x_children) {
if (g_strcmp0(xmpp_stanza_get_name(x_children), STANZA_NAME_STATUS) == 0) {
char *code = xmpp_stanza_get_attribute(x_children, STANZA_ATTR_CODE);
if (g_strcmp0(code, "303") == 0) {
@ -1268,7 +1374,7 @@ stanza_get_new_nick(xmpp_stanza_t * const stanza)
xmpp_stanza_t *x = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_X);
xmpp_stanza_t *x_children = xmpp_stanza_get_children(x);
while (x_children != NULL) {
while (x_children) {
if (strcmp(xmpp_stanza_get_name(x_children), STANZA_NAME_ITEM) == 0) {
char *nick = xmpp_stanza_get_attribute(x_children, STANZA_ATTR_NICK);
if (nick) {
@ -1382,9 +1488,9 @@ stanza_get_error_message(xmpp_stanza_t *stanza)
xmpp_stanza_t *text_stanza = xmpp_stanza_get_child_by_name(error_stanza, STANZA_NAME_TEXT);
// check for text
if (text_stanza != NULL) {
if (text_stanza) {
gchar *err_msg = xmpp_stanza_get_text(text_stanza);
if (err_msg != NULL) {
if (err_msg) {
char *result = strdup(err_msg);
xmpp_free(ctx, err_msg);
return result;
@ -1419,7 +1525,7 @@ stanza_get_error_message(xmpp_stanza_t *stanza)
int i;
for (i = 0; i < ARRAY_SIZE(defined_conditions); i++) {
xmpp_stanza_t *cond_stanza = xmpp_stanza_get_child_by_name(error_stanza, defined_conditions[i]);
if (cond_stanza != NULL) {
if (cond_stanza) {
char *result = strdup(xmpp_stanza_get_name(cond_stanza));
return result;
}
@ -1456,7 +1562,7 @@ void
stanza_attach_show(xmpp_ctx_t * const ctx, xmpp_stanza_t * const presence,
const char * const show)
{
if (show != NULL) {
if (show) {
xmpp_stanza_t *show_stanza = xmpp_stanza_new(ctx);
xmpp_stanza_set_name(show_stanza, STANZA_NAME_SHOW);
xmpp_stanza_t *text = xmpp_stanza_new(ctx);
@ -1472,7 +1578,7 @@ void
stanza_attach_status(xmpp_ctx_t * const ctx, xmpp_stanza_t * const presence,
const char * const status)
{
if (status != NULL) {
if (status) {
xmpp_stanza_t *status_stanza = xmpp_stanza_new(ctx);
xmpp_stanza_set_name(status_stanza, STANZA_NAME_STATUS);
xmpp_stanza_t *text = xmpp_stanza_new(ctx);
@ -1619,9 +1725,9 @@ stanza_parse_presence(xmpp_stanza_t *stanza, int *err)
result->priority = 0;
xmpp_stanza_t *priority_stanza = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_PRIORITY);
if (priority_stanza != NULL) {
if (priority_stanza) {
char *priority_str = xmpp_stanza_get_text(priority_stanza);
if (priority_str != NULL) {
if (priority_str) {
result->priority = atoi(priority_str);
}
free(priority_str);

View File

@ -1,7 +1,7 @@
/*
* stanza.h
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*
@ -77,6 +77,8 @@
#define STANZA_NAME_VALUE "value"
#define STANZA_NAME_DESTROY "destroy"
#define STANZA_NAME_ACTOR "actor"
#define STANZA_NAME_ENABLE "enable"
#define STANZA_NAME_DISABLE "disable"
// error conditions
#define STANZA_NAME_BAD_REQUEST "bad-request"
@ -133,6 +135,7 @@
#define STANZA_ATTR_CATEGORY "category"
#define STANZA_ATTR_REASON "reason"
#define STANZA_ATTR_AUTOJOIN "autojoin"
#define STANZA_ATTR_PASSWORD "password"
#define STANZA_TEXT_AWAY "away"
#define STANZA_TEXT_DND "dnd"
@ -154,6 +157,9 @@
#define STANZA_NS_CONFERENCE "jabber:x:conference"
#define STANZA_NS_CAPTCHA "urn:xmpp:captcha"
#define STANZA_NS_PUBSUB "http://jabber.org/protocol/pubsub"
#define STANZA_NS_CARBONS "urn:xmpp:carbons:2"
#define STANZA_NS_FORWARD "urn:xmpp:forward:0"
#define STANZA_NS_RECEIPTS "urn:xmpp:receipts"
#define STANZA_DATAFORM_SOFTWARE "urn:xmpp:dataforms:softwareinfo"
@ -178,12 +184,19 @@ typedef enum {
xmpp_stanza_t* stanza_create_bookmarks_storage_request(xmpp_ctx_t *ctx);
xmpp_stanza_t * stanza_enable_carbons(xmpp_ctx_t *ctx);
xmpp_stanza_t * stanza_disable_carbons(xmpp_ctx_t *ctx);
xmpp_stanza_t* stanza_create_chat_state(xmpp_ctx_t *ctx,
const char * const fulljid, const char * const state);
xmpp_stanza_t* stanza_create_message(xmpp_ctx_t *ctx,
const char * const recipient, const char * const type,
const char * const message, const char * const state);
xmpp_stanza_t * stanza_attach_state(xmpp_ctx_t *ctx, xmpp_stanza_t *stanza, const char * const state);
xmpp_stanza_t * stanza_attach_carbons_private(xmpp_ctx_t *ctx, xmpp_stanza_t *stanza);
xmpp_stanza_t * stanza_attach_receipt_request(xmpp_ctx_t *ctx, xmpp_stanza_t *stanza);
xmpp_stanza_t* stanza_create_message(xmpp_ctx_t *ctx, char *id,
const char * const recipient, const char * const type, const char * const message);
xmpp_stanza_t* stanza_create_room_join_presence(xmpp_ctx_t * const ctx,
const char * const full_room_jid, const char * const passwd);
@ -202,6 +215,8 @@ xmpp_stanza_t* stanza_create_disco_info_iq(xmpp_ctx_t *ctx, const char * const i
const char * const to, const char * const node);
xmpp_stanza_t* stanza_create_invite(xmpp_ctx_t *ctx, const char * const room,
const char * const contact, const char * const reason, const char * const password);
xmpp_stanza_t* stanza_create_mediated_invite(xmpp_ctx_t *ctx, const char * const room,
const char * const contact, const char * const reason);
gboolean stanza_contains_chat_state(xmpp_stanza_t *stanza);

View File

@ -1,7 +1,7 @@
/*
* xmpp.h
*
* Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
* Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*
@ -145,7 +145,8 @@ char* jabber_get_account_name(void);
GList * jabber_get_available_resources(void);
// message functions
void message_send_chat(const char * const barejid, const char * const msg);
char* message_send_chat(const char * const barejid, const char * const msg);
char* message_send_chat_encrypted(const char * const barejid, const char * const msg);
void message_send_private(const char * const fulljid, const char * const msg);
void message_send_groupchat(const char * const roomjid, const char * const msg);
void message_send_groupchat_subject(const char * const roomjid, const char * const subject);
@ -167,11 +168,13 @@ char * presence_sub_request_find(const char * const search_str);
void presence_join_room(char *room, char *nick, char * passwd);
void presence_change_room_nick(const char * const room, const char * const nick);
void presence_leave_chat_room(const char * const room_jid);
void presence_update(resource_presence_t status, const char * const msg,
void presence_send(resource_presence_t status, const char * const msg,
int idle);
gboolean presence_sub_request_exists(const char * const bare_jid);
// iq functions
void iq_enable_carbons();
void iq_disable_carbons();
void iq_send_software_version(const char * const fulljid);
void iq_room_list_request(gchar *conferencejid);
void iq_disco_info_request(gchar *jid);
@ -189,7 +192,7 @@ void iq_send_caps_request_for_jid(const char * const to, const char * const id,
const char * const node, const char * const ver);
void iq_send_caps_request_legacy(const char * const to, const char * const id,
const char * const node, const char * const ver);
void iq_room_info_request(gchar *room);
void iq_room_info_request(const char * const room, gboolean display_result);
void iq_room_affiliation_list(const char * const room, char *affiliation);
void iq_room_affiliation_set(const char * const room, const char * const jid, char *affiliation,
const char * const reason);

View File

@ -85,6 +85,24 @@ void close_chat_sessions(void **state)
close_preferences(NULL);
}
int
utf8_pos_to_col(char *str, int utf8_pos)
{
int col = 0;
int i = 0;
for (i = 0; i<utf8_pos; i++) {
col++;
gchar *ch = g_utf8_offset_to_pointer(str, i);
gunichar uni = g_utf8_get_char(ch);
if (g_unichar_iswide(uni)) {
col++;
}
}
return col;
}
static GCompareFunc cmp_func;
void

View File

@ -6,5 +6,7 @@ void close_preferences(void **state);
void init_chat_sessions(void **state);
void close_chat_sessions(void **state);
int utf8_pos_to_col(char *str, int utf8_pos);
void glist_set_cmp(GCompareFunc func);
int glist_contents_equal(const void *actual, const void *expected);

Some files were not shown because too many files have changed in this diff Show More