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

View File

@ -1,7 +1,7 @@
language: c language: c
install: install:
- sudo apt-get update - 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 - git clone git://github.com/strophe/libstrophe.git
- cd libstrophe - cd libstrophe
- mkdir m4 - mkdir m4
@ -11,15 +11,15 @@ install:
- sudo make install - sudo make install
- cd .. - cd ..
- rm -rf libstrophe - rm -rf libstrophe
- wget https://open.cryptomilk.org/attachments/download/42/cmocka-0.4.1.tar.xz - wget https://cmocka.org/files/1.0/cmocka-1.0.0.tar.xz
- tar -xvf cmocka-0.4.1.tar.xz - tar -xvf cmocka-1.0.0.tar.xz
- cd cmocka-0.4.1 - cd cmocka-1.0.0
- mkdir build - mkdir build
- cd build - cd build
- cmake -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Debug .. - cmake -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Debug ..
- make - make
- sudo make install - sudo make install
- cd ../.. - cd ../..
- rm -rf cmocka-0.4.1 - rm -rf cmocka-1.0.0
- ./bootstrap.sh - ./bootstrap.sh
script: ./configure && make && make check 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 0.4.6
===== =====
- 16 colour support - 16 colour support (/theme colours)
- UI preferences included in themes - UI preferences included in themes
- Word wrapping (/wrap) - /wrap - Word wrapping
- Show hide time (/time) - /time - Show/hide time in main window, and configure precision
- Show or hide and customise roster panel (/roster) - /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 - /account remove
- Added default account for /connect - /presence - Show/hide contact presence in titlebar
- Additional readline style shortcuts - /resource - Override resource during chat, resource display settings
- Improved chat session handling - Improved chat session handling <http://xmpp.org/rfcs/rfc6121.html#message-chat>
- Override resource during chat and resource display settings (/resource) - Lower CPU usage with dynamic input blocking timeout
- Disable terminal title by default, additonal title on exit - Keychain/keyring integration using account eval_password property
- Dynamic input blocking timeout to use less CPU - Disable term window title by default
- eval_password property on accounts for retrieving password from keyring/keychain - Fixed remote code execution bug on OSX when desktop notifications configured to show message text

View File

@ -1,5 +1,5 @@
Profanity 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 Profanity is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by 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/roster.c src/xmpp/roster.h \
src/xmpp/bookmark.c src/xmpp/bookmark.h \ src/xmpp/bookmark.c src/xmpp/bookmark.h \
src/xmpp/form.c src/xmpp/form.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/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.c src/ui/statusbar.c src/ui/inputwin.c \
src/ui/titlebar.h src/ui/statusbar.h src/ui/inputwin.h \ src/ui/titlebar.h src/ui/statusbar.h src/ui/inputwin.h \
@ -27,7 +29,6 @@ core_sources = \
src/tools/parser.h \ src/tools/parser.h \
src/tools/p_sha1.h src/tools/p_sha1.c \ src/tools/p_sha1.h src/tools/p_sha1.c \
src/tools/autocomplete.c src/tools/autocomplete.h \ 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/tools/tinyurl.c src/tools/tinyurl.h \
src/config/accounts.c src/config/accounts.h \ src/config/accounts.c src/config/accounts.h \
src/config/account.c src/config/account.h \ src/config/account.c src/config/account.h \
@ -44,13 +45,13 @@ tests_sources = \
src/roster_list.c src/roster_list.h \ src/roster_list.c src/roster_list.h \
src/xmpp/xmpp.h src/xmpp/form.c \ src/xmpp/xmpp.h src/xmpp/form.c \
src/ui/ui.h \ src/ui/ui.h \
src/otr/otr.h \
src/command/command.h src/command/command.c \ src/command/command.h src/command/command.c \
src/command/commands.h src/command/commands.c \ src/command/commands.h src/command/commands.c \
src/tools/parser.c \ src/tools/parser.c \
src/tools/parser.h \ src/tools/parser.h \
src/tools/p_sha1.h src/tools/p_sha1.c \ src/tools/p_sha1.h src/tools/p_sha1.c \
src/tools/autocomplete.c src/tools/autocomplete.h \ 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/tools/tinyurl.c src/tools/tinyurl.h \
src/config/accounts.h \ src/config/accounts.h \
src/config/account.c src/config/account.h \ src/config/account.c src/config/account.h \
@ -61,9 +62,10 @@ tests_sources = \
src/ui/buffer.c \ src/ui/buffer.c \
src/ui/titlebar.c src/ui/statusbar.c src/ui/inputwin.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/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/xmpp/stub_xmpp.c \
tests/otr/stub_otr.c \
tests/ui/stub_ui.c \ tests/ui/stub_ui.c \
tests/log/stub_log.c \ tests/log/stub_log.c \
tests/config/stub_accounts.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_roster.c tests/test_cmd_roster.h \
tests/test_cmd_statuses.c tests/test_cmd_statuses.h \ tests/test_cmd_statuses.c tests/test_cmd_statuses.h \
tests/test_cmd_sub.c tests/test_cmd_sub.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_cmd_disconnect.c tests/test_cmd_disconnect.h \
tests/test_common.c tests/test_common.h \ tests/test_common.c tests/test_common.h \
tests/test_contact.c tests/test_contact.h \ tests/test_contact.c tests/test_contact.h \
tests/test_form.c tests/test_form.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_jid.c tests/test_jid.h \
tests/test_muc.c tests/test_muc.h \ tests/test_muc.c tests/test_muc.h \
tests/test_parser.c tests/test_parser.h \ tests/test_parser.c tests/test_parser.h \
@ -104,6 +104,9 @@ otr3_sources = \
otr4_sources = \ otr4_sources = \
src/otr/otrlib.h src/otr/otrlibv4.c src/otr/otr.h src/otr/otr.c 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/* themes_sources = themes/*
script_sources = bootstrap.sh configure-debug install-all.sh 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 man_sources = docs/profanity.1
if BUILD_OTR if BUILD_OTR
tests_sources += $(otr_test_sources)
if BUILD_OTR3 if BUILD_OTR3
core_sources += $(otr3_sources) core_sources += $(otr3_sources)
endif endif

View File

@ -1,7 +1,7 @@
# -*- Autoconf -*- # -*- Autoconf -*-
# Process this file with autoconf to produce a configure script. # 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_MACRO_DIR([m4])
AC_CONFIG_SRCDIR([src/main.c]) AC_CONFIG_SRCDIR([src/main.c])
AC_CONFIG_HEADERS([src/config.h]) 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], AS_IF([test "x$PLATFORM" = xcygwin],
[AC_DEFINE([PLATFORM_CYGWIN], [1], [Cygwin])]) [AC_DEFINE([PLATFORM_CYGWIN], [1], [Cygwin])])
AS_IF([test "x$PLATFORM" = xosx],
[AC_DEFINE([PLATFORM_OSX], [1], [OSx])])
### Options ### Options
AC_ARG_ENABLE([notifications], AC_ARG_ENABLE([notifications],
@ -134,10 +136,23 @@ PKG_CHECK_MODULES([glib], [glib-2.0 >= 2.26], [],
PKG_CHECK_MODULES([curl], [libcurl], [], PKG_CHECK_MODULES([curl], [libcurl], [],
[AC_MSG_ERROR([libcurl is required for profanity])]) [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"]) AS_IF([test "x$PLATFORM" = xosx], [LIBS="-lcurl $LIBS"])
### Check for desktop notification support ### Check for desktop notification support
### Linux requires libnotify ### Linux/FreeBSD require libnotify
### Windows uses native OS calls ### Windows uses native OS calls
### OSX requires terminal-notifier ### 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_ERROR([terminal-notifier not found, required for desktop notifications.])],
[AC_MSG_NOTICE([Desktop notifications not supported.])])], [AC_MSG_NOTICE([Desktop notifications not supported.])])],
[AC_DEFINE([HAVE_OSXNOTIFY], [1], [terminal notifier])])])], [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], [AS_IF([test "x$enable_notifications" != xno],
[PKG_CHECK_MODULES([libnotify], [libnotify], [PKG_CHECK_MODULES([libnotify], [libnotify],
[AC_DEFINE([HAVE_LIBNOTIFY], [1], [libnotify module])], [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 .SH NAME
Profanity \- a simple console based XMPP chat client. Profanity \- a simple console based XMPP chat client.
.SH SYNOPSIS .SH SYNOPSIS
.B profanity .B profanity
[\-vhd] [\-l level] [\-vhd] [\-l level] [\-a account]
.SH DESCRIPTION .SH DESCRIPTION
.B Profanity .B Profanity
is a simple lightweight console based XMPP chat client. Its emphasis is is a simple lightweight console based XMPP chat client. Its emphasis is
@ -15,19 +15,21 @@ at:
.SH OPTIONS .SH OPTIONS
.TP .TP
.BI "\-v, \-\-version" .BI "\-v, \-\-version"
Show version information. Show version and build information.
.TP .TP
.BI "\-h, \-\-help" .BI "\-h, \-\-help"
Show help on command line arguments. Show help on command line arguments.
.TP .TP
.BI "\-a, \-\-account" .BI "\-a, \-\-account "ACCOUNT
Auto connect to an account on startup. Auto connect to an account on startup,
.I ACCOUNT
must be an existing account.
.TP .TP
.BI "\-d, \-\-disable\-tls" .BI "\-d, \-\-disable\-tls"
Disable TLS for servers that either don't support it, or claim to but do not Disable TLS for servers that either don't support it, or claim to but do not
complete the handshake. complete the handshake.
.TP .TP
.BI "\-l, \-\-log="LEVEL .BI "\-l, \-\-log "LEVEL
Set the logging level, Set the logging level,
.I LEVEL .I LEVEL
may be set to DEBUG, INFO (the default), WARN or ERROR. 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>. , details on configuring Profanity can be found at <http://www.profanity.im/configuration.html>.
.PP .PP
.SH BUGS .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 .br
.PP .PP
<boothj5web@gmail.com> <https://github.com/boothj5/profanity/issues>
.br .br
.PP .PP
or to the mailing list at: or to the mailing list at:
@ -57,12 +59,14 @@ or to the mailing list at:
<https://groups.google.com/forum/#!forum/profanitydev> <https://groups.google.com/forum/#!forum/profanitydev>
.br .br
.PP .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 .br
.PP .PP
<https://github.com/boothj5/profanity>
.SH LICENSE .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> 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. This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. There is NO WARRANTY, to the extent permitted by law.

View File

@ -24,7 +24,7 @@ debian_prepare()
echo echo
echo Profanity installer... installing dependencies echo Profanity installer... installing dependencies
echo 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` 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() opensuse_prepare()
@ -44,7 +44,7 @@ opensuse_prepare()
echo echo
echo Profanity installer...installing dependencies echo Profanity installer...installing dependencies
echo 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() cygwin_prepare()
@ -60,9 +60,9 @@ cygwin_prepare()
mv apt-cyg /usr/local/bin/ mv apt-cyg /usr/local/bin/
if [ -n "$CYG_MIRROR" ]; then 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 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 fi
} }

View File

@ -1,7 +1,7 @@
/* /*
* chat_session.c * 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. * This file is part of Profanity.
* *
@ -64,7 +64,7 @@ _chat_session_new(const char * const barejid, const char * const resource,
static void static void
_chat_session_free(ChatSession *session) _chat_session_free(ChatSession *session)
{ {
if (session != NULL) { if (session) {
free(session->barejid); free(session->barejid);
free(session->resource); free(session->resource);
free(session); free(session);
@ -81,7 +81,7 @@ chat_sessions_init(void)
void void
chat_sessions_clear(void) chat_sessions_clear(void)
{ {
if (sessions != NULL) if (sessions)
g_hash_table_remove_all(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 // session exists with resource, update chat_states
if (g_strcmp0(session->resource, resource) == 0) { if (g_strcmp0(session->resource, resource) == 0) {
session->send_states = send_states; 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) { } else if (!session->resource_override) {
_chat_session_new(barejid, resource, FALSE, send_states); _chat_session_new(barejid, resource, FALSE, send_states);
} }

View File

@ -1,7 +1,7 @@
/* /*
* chat_session.h * 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. * This file is part of Profanity.
* *

View File

@ -1,7 +1,7 @@
/* /*
* chat_state.c * 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. * This file is part of Profanity.
* *

View File

@ -1,7 +1,7 @@
/* /*
* chat_state.h * 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. * This file is part of Profanity.
* *

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
/* /*
* command.h * 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. * 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_previous(char *inp);
char *cmd_history_next(char *inp); char *cmd_history_next(char *inp);
void command_docgen(void);
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
/* /*
* commands.h * 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. * This file is part of Profanity.
* *
@ -62,6 +62,9 @@ typedef struct cmd_t {
CommandHelp help; CommandHelp help;
} Command; } 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_about(gchar **args, struct cmd_help_t help);
gboolean cmd_account(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); 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_group(gchar **args, struct cmd_help_t help);
gboolean cmd_help(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_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_info(gchar **args, struct cmd_help_t help);
gboolean cmd_intype(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); gboolean cmd_invite(gchar **args, struct cmd_help_t help);

View File

@ -1,7 +1,7 @@
/* /*
* common.c * 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. * This file is part of Profanity.
* *
@ -202,6 +202,33 @@ str_contains(const char str[], int size, char ch)
return 0; 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 int
utf8_display_len(const char * const str) utf8_display_len(const char * const str)
{ {
@ -224,6 +251,18 @@ utf8_display_len(const char * const str)
return len; 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 * char *
prof_getline(FILE *stream) prof_getline(FILE *stream)
{ {
@ -248,7 +287,7 @@ prof_getline(FILE *stream)
result = (char *)realloc(s, s_size + buf_size); result = (char *)realloc(s, s_size + buf_size);
if (result == NULL) { if (result == NULL) {
if (s != NULL) { if (s) {
free(s); free(s);
s = NULL; s = NULL;
} }
@ -286,7 +325,7 @@ release_get_latest()
curl_easy_perform(handle); curl_easy_perform(handle);
curl_easy_cleanup(handle); curl_easy_cleanup(handle);
if (output.buffer != NULL) { if (output.buffer) {
output.buffer[output.size++] = '\0'; output.buffer[output.size++] = '\0';
return output.buffer; return output.buffer;
} else { } else {
@ -393,10 +432,10 @@ gchar *
xdg_get_config_home(void) xdg_get_config_home(void)
{ {
gchar *xdg_config_home = getenv("XDG_CONFIG_HOME"); gchar *xdg_config_home = getenv("XDG_CONFIG_HOME");
if (xdg_config_home != NULL) if (xdg_config_home)
g_strstrip(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); return strdup(xdg_config_home);
} else { } else {
GString *default_path = g_string_new(getenv("HOME")); GString *default_path = g_string_new(getenv("HOME"));
@ -412,10 +451,10 @@ gchar *
xdg_get_data_home(void) xdg_get_data_home(void)
{ {
gchar *xdg_data_home = getenv("XDG_DATA_HOME"); gchar *xdg_data_home = getenv("XDG_DATA_HOME");
if (xdg_data_home != NULL) if (xdg_data_home)
g_strstrip(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); return strdup(xdg_data_home);
} else { } else {
GString *default_path = g_string_new(getenv("HOME")); GString *default_path = g_string_new(getenv("HOME"));
@ -435,7 +474,7 @@ create_unique_id(char *prefix)
GString *result_str = g_string_new(""); GString *result_str = g_string_new("");
unique_id++; unique_id++;
if (prefix != NULL) { if (prefix) {
g_string_printf(result_str, "prof_%s_%lu", prefix, unique_id); g_string_printf(result_str, "prof_%s_%lu", prefix, unique_id);
} else { } else {
g_string_printf(result_str, "prof_%lu", unique_id); g_string_printf(result_str, "prof_%lu", unique_id);
@ -488,25 +527,34 @@ cmp_win_num(gconstpointer a, gconstpointer b)
int int
get_next_available_win_num(GList *used) get_next_available_win_num(GList *used)
{ {
used = g_list_sort(used, cmp_win_num);
// only console used // only console used
if (g_list_length(used) == 1) { if (g_list_length(used) == 1) {
return 2; return 2;
} else { } 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 result = 0;
int last_num = 1; int last_num = 1;
GList *curr = used; curr = sorted;
// skip console // skip console
curr = g_list_next(curr); curr = g_list_next(curr);
while (curr != NULL) { while (curr) {
int curr_num = GPOINTER_TO_INT(curr->data); int curr_num = GPOINTER_TO_INT(curr->data);
if (((last_num != 9) && ((last_num + 1) != curr_num)) || if (((last_num != 9) && ((last_num + 1) != curr_num)) ||
((last_num == 9) && (curr_num != 0))) { ((last_num == 9) && (curr_num != 0))) {
result = last_num + 1; result = last_num + 1;
if (result == 10) { if (result == 10) {
result = 0; result = 0;
} }
g_list_free(sorted);
return (result); return (result);
} else { } else {
last_num = curr_num; last_num = curr_num;
if (last_num == 0) { if (last_num == 0) {
@ -520,6 +568,7 @@ get_next_available_win_num(GList *used)
result = 0; result = 0;
} }
g_list_free(sorted);
return result; return result;
} }
} }
@ -566,3 +615,25 @@ get_file_or_linked(char *loc, char *basedir)
return true_loc; 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 * 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. * This file is part of Profanity.
* *
@ -36,6 +36,13 @@
#define COMMON_H #define COMMON_H
#include <stdio.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> #include <glib.h>
@ -104,7 +111,9 @@ gboolean mkdir_recursive(const char *dir);
char * str_replace(const char *string, const char *substr, char * str_replace(const char *string, const char *substr,
const char *replacement); const char *replacement);
int str_contains(const char str[], int size, char ch); 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); int utf8_display_len(const char * const str);
gboolean utf8_is_printable(const wint_t ch);
char * prof_getline(FILE *stream); char * prof_getline(FILE *stream);
char* release_get_latest(void); char* release_get_latest(void);
gboolean release_is_new(char *found_version); 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); int get_next_available_win_num(GList *used);
char* get_file_or_linked(char *loc, char *basedir); char* get_file_or_linked(char *loc, char *basedir);
char * strip_arg_quotes(const char * const input);
#endif #endif

View File

@ -1,7 +1,7 @@
/* /*
* account.c * 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. * This file is part of Profanity.
* *
@ -34,12 +34,14 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <assert.h>
#include <glib.h> #include <glib.h>
#include "jid.h" #include "jid.h"
#include "config/account.h" #include "config/account.h"
#include "common.h" #include "common.h"
#include "log.h"
ProfAccount* ProfAccount*
account_new(const gchar * const name, const gchar * const jid, 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); new_account->name = strdup(name);
if (jid != NULL) { if (jid) {
new_account->jid = strdup(jid); new_account->jid = strdup(jid);
} else { } else {
new_account->jid = strdup(name); new_account->jid = strdup(name);
} }
if (password != NULL) { if (password) {
new_account->password = strdup(password); new_account->password = strdup(password);
} else { } else {
new_account->password = NULL; new_account->password = NULL;
} }
if (eval_password != NULL) { if (eval_password) {
new_account->eval_password = strdup(eval_password); new_account->eval_password = strdup(eval_password);
} else { } else {
new_account->eval_password = NULL; new_account->eval_password = NULL;
@ -75,13 +77,13 @@ account_new(const gchar * const name, const gchar * const jid,
new_account->enabled = enabled; new_account->enabled = enabled;
if (server != NULL) { if (server) {
new_account->server = strdup(server); new_account->server = strdup(server);
} else { } else {
new_account->server = NULL; new_account->server = NULL;
} }
if (resource != NULL) { if (resource) {
new_account->resource = strdup(resource); new_account->resource = strdup(resource);
} else { } else {
new_account->resource = NULL; 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); new_account->muc_nick = strdup(muc_nick);
} }
if (otr_policy != NULL) { if (otr_policy) {
new_account->otr_policy = strdup(otr_policy); new_account->otr_policy = strdup(otr_policy);
} else { } else {
new_account->otr_policy = NULL; new_account->otr_policy = NULL;
@ -148,17 +150,55 @@ account_new(const gchar * const name, const gchar * const jid,
char * char *
account_create_full_jid(ProfAccount *account) account_create_full_jid(ProfAccount *account)
{ {
if (account->resource != NULL) { if (account->resource) {
return create_fulljid(account->jid, account->resource); return create_fulljid(account->jid, account->resource);
} else { } else {
return strdup(account->jid); 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 void
account_free(ProfAccount *account) account_free(ProfAccount *account)
{ {
if (account != NULL) { if (account) {
free(account->name); free(account->name);
free(account->jid); free(account->jid);
free(account->password); free(account->password);

View File

@ -1,7 +1,7 @@
/* /*
* account.h * 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. * 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 muc_service, const gchar * const muc_nick,
const gchar * const otr_policy, GList *otr_manual, GList *otr_opportunistic, const gchar * const otr_policy, GList *otr_manual, GList *otr_opportunistic,
GList *otr_always); GList *otr_always);
char* account_create_full_jid(ProfAccount *account); char* account_create_full_jid(ProfAccount *account);
gboolean account_eval_password(ProfAccount *account);
void account_free(ProfAccount *account); void account_free(ProfAccount *account);
#endif #endif

View File

@ -1,7 +1,7 @@
/* /*
* accounts.c * 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. * 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 *barejid = account_name;
const char *resource = "profanity"; const char *resource = "profanity";
Jid *jid = jid_create(account_name); Jid *jid = jid_create(account_name);
if (jid != NULL) { if (jid) {
barejid = jid->barejid; barejid = jid->barejid;
if (jid->resourcepart != NULL) { if (jid->resourcepart) {
resource = 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_boolean(accounts, account_name, "enabled", TRUE);
g_key_file_set_string(accounts, account_name, "jid", barejid); g_key_file_set_string(accounts, account_name, "jid", barejid);
g_key_file_set_string(accounts, account_name, "resource", resource); 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); g_key_file_set_string(accounts, account_name, "server", altdomain);
} }
if (port != 0) { if (port != 0) {
@ -252,7 +252,7 @@ accounts_get_account(const char * const name)
gsize length; gsize length;
GList *otr_manual = NULL; GList *otr_manual = NULL;
gchar **manual = g_key_file_get_string_list(accounts, name, "otr.manual", &length, NULL); gchar **manual = g_key_file_get_string_list(accounts, name, "otr.manual", &length, NULL);
if (manual != NULL) { if (manual) {
int i = 0; int i = 0;
for (i = 0; i < length; i++) { for (i = 0; i < length; i++) {
otr_manual = g_list_append(otr_manual, strdup(manual[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; GList *otr_opportunistic = NULL;
gchar **opportunistic = g_key_file_get_string_list(accounts, name, "otr.opportunistic", &length, NULL); gchar **opportunistic = g_key_file_get_string_list(accounts, name, "otr.opportunistic", &length, NULL);
if (opportunistic != NULL) { if (opportunistic) {
int i = 0; int i = 0;
for (i = 0; i < length; i++) { for (i = 0; i < length; i++) {
otr_opportunistic = g_list_append(otr_opportunistic, strdup(opportunistic[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; GList *otr_always = NULL;
gchar **always = g_key_file_get_string_list(accounts, name, "otr.always", &length, NULL); gchar **always = g_key_file_get_string_list(accounts, name, "otr.always", &length, NULL);
if (always != NULL) { if (always) {
int i = 0; int i = 0;
for (i = 0; i < length; i++) { for (i = 0; i < length; i++) {
otr_always = g_list_append(otr_always, strdup(always[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; int i;
for (i = 0; i < ARRAY_SIZE(string_keys); i++) { for (i = 0; i < ARRAY_SIZE(string_keys); i++) {
char *value = g_key_file_get_string(accounts, account_name, string_keys[i], NULL); 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_key_file_set_string(accounts, new_name, string_keys[i], value);
g_free(value); g_free(value);
} }
@ -386,10 +386,10 @@ void
accounts_set_jid(const char * const account_name, const char * const value) accounts_set_jid(const char * const account_name, const char * const value)
{ {
Jid *jid = jid_create(value); Jid *jid = jid_create(value);
if (jid != NULL) { if (jid) {
if (accounts_account_exists(account_name)) { if (accounts_account_exists(account_name)) {
g_key_file_set_string(accounts, account_name, "jid", jid->barejid); 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); 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; GList *glist = NULL;
// list found // list found
if (list != NULL) { if (list) {
int i = 0; int i = 0;
for (i = 0; i < length; i++) { for (i = 0; i < length; i++) {
// item already in list, exit function // 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]; const gchar* new_list[g_list_length(glist)+1];
GList *curr = glist; GList *curr = glist;
i = 0; i = 0;
while (curr != NULL) { while (curr) {
new_list[i++] = strdup(curr->data); new_list[i++] = strdup(curr->data);
curr = g_list_next(curr); curr = g_list_next(curr);
} }
@ -572,7 +572,7 @@ _remove_from_list(GKeyFile *accounts, const char * const account_name, const cha
gsize length; gsize length;
gchar **list = g_key_file_get_string_list(accounts, account_name, key, &length, NULL); gchar **list = g_key_file_get_string_list(accounts, account_name, key, &length, NULL);
if (list != NULL) { if (list) {
int i = 0; int i = 0;
GList *glist = NULL; GList *glist = NULL;
gboolean deleted = FALSE; 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]; const gchar* new_list[g_list_length(glist)+1];
GList *curr = glist; GList *curr = glist;
i = 0; i = 0;
while (curr != NULL) { while (curr) {
new_list[i++] = strdup(curr->data); new_list[i++] = strdup(curr->data);
curr = g_list_next(curr); curr = g_list_next(curr);
} }
@ -766,7 +766,7 @@ accounts_get_last_presence(const char * const account_name)
result = RESOURCE_ONLINE; result = RESOURCE_ONLINE;
} }
if (setting != NULL) { if (setting) {
g_free(setting); g_free(setting);
} }
return result; return result;
@ -796,7 +796,7 @@ accounts_get_login_presence(const char * const account_name)
result = RESOURCE_ONLINE; result = RESOURCE_ONLINE;
} }
if (setting != NULL) { if (setting) {
g_free(setting); g_free(setting);
} }
return result; return result;
@ -809,9 +809,9 @@ _fix_legacy_accounts(const char * const account_name)
const char *barejid = account_name; const char *barejid = account_name;
const char *resource = "profanity"; const char *resource = "profanity";
Jid *jid = jid_create(account_name); Jid *jid = jid_create(account_name);
if (jid != NULL) { if (jid) {
barejid = jid->barejid; barejid = jid->barejid;
if (jid->resourcepart != NULL) { if (jid->resourcepart) {
resource = jid->resourcepart; resource = jid->resourcepart;
} }
} }
@ -828,7 +828,7 @@ _fix_legacy_accounts(const char * const account_name)
_save_accounts(); _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)) { 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); gchar *account_jid = g_key_file_get_string(accounts, account_name, "jid", NULL);
Jid *jidp = jid_create(account_jid); Jid *jidp = jid_create(account_jid);

View File

@ -1,7 +1,7 @@
/* /*
* accounts.h * 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. * This file is part of Profanity.
* *

View File

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

View File

@ -1,7 +1,7 @@
/* /*
* preferences.h * 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. * This file is part of Profanity.
* *
@ -59,9 +59,13 @@ typedef enum {
PREF_FLASH, PREF_FLASH,
PREF_INTYPE, PREF_INTYPE,
PREF_HISTORY, PREF_HISTORY,
PREF_CARBONS,
PREF_RECEIPTS_SEND,
PREF_RECEIPTS_REQUEST,
PREF_MOUSE, PREF_MOUSE,
PREF_OCCUPANTS, PREF_OCCUPANTS,
PREF_OCCUPANTS_SIZE, PREF_OCCUPANTS_SIZE,
PREF_OCCUPANTS_JID,
PREF_ROSTER, PREF_ROSTER,
PREF_ROSTER_SIZE, PREF_ROSTER_SIZE,
PREF_ROSTER_OFFLINE, PREF_ROSTER_OFFLINE,
@ -71,6 +75,7 @@ typedef enum {
PREF_PRESENCE, PREF_PRESENCE,
PREF_WRAP, PREF_WRAP,
PREF_TIME, PREF_TIME,
PREF_TIME_STATUSBAR,
PREF_STATUSES, PREF_STATUSES,
PREF_STATUSES_CONSOLE, PREF_STATUSES_CONSOLE,
PREF_STATUSES_CHAT, PREF_STATUSES_CHAT,

View File

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

View File

@ -1,7 +1,7 @@
/* /*
* theme.h * 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. * This file is part of Profanity.
* *
@ -90,6 +90,7 @@ typedef enum {
THEME_OTR_UNTRUSTED, THEME_OTR_UNTRUSTED,
THEME_OCCUPANTS_HEADER, THEME_OCCUPANTS_HEADER,
THEME_ROSTER_HEADER, THEME_ROSTER_HEADER,
THEME_RECEIPT_SENT,
THEME_NONE, THEME_NONE,
THEME_WHITE, THEME_WHITE,
THEME_WHITE_BOLD, THEME_WHITE_BOLD,

View File

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

View File

@ -1,7 +1,7 @@
/* /*
* contact.h * 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. * 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); gboolean p_contact_remove_resource(PContact contact, const char * const resource);
void p_contact_free(PContact contact); void p_contact_free(PContact contact);
const char* p_contact_barejid(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(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_name_or_jid(const PContact contact);
const char* p_contact_presence(PContact contact); const char* p_contact_presence(PContact contact);
const char* p_contact_status(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. * This file is part of Profanity.
* *
@ -32,14 +32,11 @@
* *
*/ */
#ifndef HISTORY_H #ifndef UI_EVENTS_H
#define HISTORY_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); #endif
char * history_previous(History history, char *item);
char * history_next(History history, char *item);
void history_append(History history, char *item);
#endif

View File

@ -1,7 +1,7 @@
/* /*
* jid.c * 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. * This file is part of Profanity.
* *
@ -80,19 +80,20 @@ jid_create(const gchar * const str)
gchar *domain_start = trimmed; gchar *domain_start = trimmed;
if (atp != NULL) { if (atp) {
result->localpart = g_utf8_substring(trimmed, 0, g_utf8_pointer_to_offset(trimmed, atp)); result->localpart = g_utf8_substring(trimmed, 0, g_utf8_pointer_to_offset(trimmed, atp));
domain_start = atp + 1; domain_start = atp + 1;
} }
if (slashp != NULL) { if (slashp) {
result->resourcepart = g_strdup(slashp + 1); result->resourcepart = g_strdup(slashp + 1);
result->domainpart = g_utf8_substring(domain_start, 0, g_utf8_pointer_to_offset(domain_start, slashp)); 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); result->fulljid = g_strdup(trimmed);
} else { } else {
result->domainpart = g_strdup(domain_start); result->domainpart = g_strdup(domain_start);
result->barejid = g_strdup(trimmed); result->barejid = g_utf8_strdown(trimmed, -1);
} }
if (result->domainpart == NULL) { if (result->domainpart == NULL) {
@ -119,7 +120,7 @@ jid_create_from_bare_and_resource(const char * const room, const char * const ni
void void
jid_destroy(Jid *jid) jid_destroy(Jid *jid)
{ {
if (jid != NULL) { if (jid) {
g_free(jid->str); g_free(jid->str);
g_free(jid->localpart); g_free(jid->localpart);
g_free(jid->domainpart); g_free(jid->domainpart);
@ -144,7 +145,9 @@ jid_is_valid_room_form(Jid *jid)
char * char *
create_fulljid(const char * const barejid, const char * const resource) 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, "/");
g_string_append(full_jid, resource); 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 **tokens = g_strsplit(full_room_jid, "/", 0);
char *nick_part = NULL; char *nick_part = NULL;
if (tokens != NULL) { if (tokens) {
if (tokens[0] != NULL && tokens[1] != NULL) { if (tokens[0] && tokens[1]) {
nick_part = strdup(tokens[1]); nick_part = strdup(tokens[1]);
} }

View File

@ -1,7 +1,7 @@
/* /*
* jid.h * 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. * This file is part of Profanity.
* *

104
src/log.c
View File

@ -1,7 +1,7 @@
/* /*
* log.c * 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. * This file is part of Profanity.
* *
@ -46,6 +46,7 @@
#include "common.h" #include "common.h"
#include "config/preferences.h" #include "config/preferences.h"
#include "xmpp/xmpp.h"
#define PROF "prof" #define PROF "prof"
@ -66,7 +67,7 @@ struct dated_chat_log {
}; };
static gboolean _log_roll_needed(struct dated_chat_log *dated_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 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 void _free_chat_log(struct dated_chat_log *dated_log);
static gboolean _key_equals(void *key1, void *key2); 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 gchar * _get_main_log_file(void);
static void _rotate_log_file(void); static void _rotate_log_file(void);
static char* _log_string_from_level(log_level_t level); 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 void
log_debug(const char * const msg, ...) log_debug(const char * const msg, ...)
@ -163,7 +166,7 @@ log_close(void)
{ {
g_string_free(mainlogfile, TRUE); g_string_free(mainlogfile, TRUE);
g_time_zone_unref(tz); g_time_zone_unref(tz);
if (logp != NULL) { if (logp) {
fclose(logp); fclose(logp);
} }
} }
@ -171,7 +174,7 @@ log_close(void)
void void
log_msg(log_level_t level, const char * const area, const char * const msg) 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); dt = g_date_time_new_now(tz);
char *level_str = _log_string_from_level(level); char *level_str = _log_string_from_level(level);
@ -236,7 +239,7 @@ chat_log_init(void)
{ {
session_started = g_date_time_new_now_local(); session_started = g_date_time_new_now_local();
log_info("Initialising chat logs"); 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); (GDestroyNotify)_free_chat_log);
} }
@ -244,13 +247,80 @@ void
groupchat_log_init(void) groupchat_log_init(void)
{ {
log_info("Initialising groupchat logs"); 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); (GDestroyNotify)_free_chat_log);
} }
void void
chat_log_chat(const gchar * const login, gchar *other, chat_log_msg_out(const char * const barejid, const char * const msg)
const gchar * const msg, chat_log_direction_t direction, 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_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); 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"); FILE *logp = fopen(dated_log->filename, "a");
g_chmod(dated_log->filename, S_IRUSR | S_IWUSR); g_chmod(dated_log->filename, S_IRUSR | S_IWUSR);
if (logp != NULL) { if (logp) {
if (direction == PROF_IN_LOG) { if (direction == PROF_IN_LOG) {
if (strncmp(msg, "/me ", 4) == 0) { if (strncmp(msg, "/me ", 4) == 0) {
fprintf(logp, "%s - *%s %s\n", date_fmt, other, msg + 4); 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"); FILE *logp = fopen(dated_log->filename, "a");
g_chmod(dated_log->filename, S_IRUSR | S_IWUSR); g_chmod(dated_log->filename, S_IRUSR | S_IWUSR);
if (logp != NULL) { if (logp) {
if (strncmp(msg, "/me ", 4) == 0) { if (strncmp(msg, "/me ", 4) == 0) {
fprintf(logp, "%s - *%s %s\n", date_fmt, nick, msg + 4); fprintf(logp, "%s - *%s %s\n", date_fmt, nick, msg + 4);
} else { } 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); char *filename = _get_log_filename(recipient, login, log_date, FALSE);
FILE *logp = fopen(filename, "r"); FILE *logp = fopen(filename, "r");
if (logp != NULL) { if (logp) {
GString *header = g_string_new(""); GString *header = g_string_new("");
g_string_append_printf(header, "%d/%d/%d:", g_string_append_printf(header, "%d/%d/%d:",
g_date_time_get_day_of_month(log_date), 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 void
chat_log_close(void) chat_log_close(void)
{ {
g_hash_table_remove_all(logs); g_hash_table_destroy(logs);
g_hash_table_remove_all(groupchat_logs); g_hash_table_destroy(groupchat_logs);
g_date_time_unref(session_started); g_date_time_unref(session_started);
} }
static struct dated_chat_log * 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(); GDateTime *now = g_date_time_new_now_local();
char *filename = _get_log_filename(other, login, now, TRUE); char *filename = _get_log_filename(other, login, now, TRUE);
@ -448,12 +518,12 @@ _log_roll_needed(struct dated_chat_log *dated_log)
static void static void
_free_chat_log(struct dated_chat_log *dated_log) _free_chat_log(struct dated_chat_log *dated_log)
{ {
if (dated_log != NULL) { if (dated_log) {
if (dated_log->filename != NULL) { if (dated_log->filename) {
g_free(dated_log->filename); g_free(dated_log->filename);
dated_log->filename = NULL; dated_log->filename = NULL;
} }
if (dated_log->date != NULL) { if (dated_log->date) {
g_date_time_unref(dated_log->date); g_date_time_unref(dated_log->date);
dated_log->date = NULL; dated_log->date = NULL;
} }

View File

@ -1,7 +1,7 @@
/* /*
* log.h * 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. * 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); log_level_t log_level_from_string(char *log_level);
void chat_log_init(void); 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); void chat_log_close(void);
GSList * chat_log_get_previous(const gchar * const login, GSList * chat_log_get_previous(const gchar * const login,
const gchar * const recipient); const gchar * const recipient);

View File

@ -1,7 +1,7 @@
/* /*
* main.c * 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. * This file is part of Profanity.
* *
@ -40,13 +40,7 @@
#endif #endif
#include "profanity.h" #include "profanity.h"
#include "command/command.h"
#ifdef HAVE_LIBOTR
#include "otr/otr.h"
#endif
#include "xmpp/xmpp.h"
#include "ui/ui.h"
static gboolean disable_tls = FALSE; static gboolean disable_tls = FALSE;
static gboolean version = FALSE; static gboolean version = FALSE;
@ -56,6 +50,11 @@ static char *account_name = NULL;
int int
main(int argc, char **argv) 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[] = static GOptionEntry entries[] =
{ {
{ "version", 'v', 0, G_OPTION_ARG_NONE, &version, "Show version information", NULL }, { "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("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("License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>\n");
g_print("\n"); g_print("\n");
g_print("This is free software; you are free to change and redistribute it.\n"); g_print("This is free software; you are free to change and redistribute it.\n");

View File

@ -1,7 +1,7 @@
/* /*
* muc.c * 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. * This file is part of Profanity.
* *
@ -62,9 +62,11 @@ typedef struct _muc_room_t {
Autocomplete jid_ac; Autocomplete jid_ac;
GHashTable *nick_changes; GHashTable *nick_changes;
gboolean roster_received; gboolean roster_received;
muc_member_type_t member_type;
} ChatRoom; } ChatRoom;
GHashTable *rooms = NULL; GHashTable *rooms = NULL;
GHashTable *invite_passwords = NULL;
Autocomplete invite_ac; Autocomplete invite_ac;
static void _free_room(ChatRoom *room); static void _free_room(ChatRoom *room);
@ -82,6 +84,7 @@ muc_init(void)
{ {
invite_ac = autocomplete_new(); invite_ac = autocomplete_new();
rooms = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify)_free_room); 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 void
@ -89,19 +92,25 @@ muc_close(void)
{ {
autocomplete_free(invite_ac); autocomplete_free(invite_ac);
g_hash_table_destroy(rooms); g_hash_table_destroy(rooms);
g_hash_table_destroy(invite_passwords);
rooms = NULL; rooms = NULL;
invite_passwords = NULL;
} }
void void
muc_invites_add(const char * const room) muc_invites_add(const char * const room, const char * const password)
{ {
autocomplete_add(invite_ac, room); autocomplete_add(invite_ac, room);
if (password) {
g_hash_table_replace(invite_passwords, strdup(room), strdup(password));
}
} }
void void
muc_invites_remove(const char * const room) muc_invites_remove(const char * const room)
{ {
autocomplete_remove(invite_ac, room); autocomplete_remove(invite_ac, room);
g_hash_table_remove(invite_passwords, room);
} }
gint gint
@ -116,6 +125,12 @@ muc_invites(void)
return autocomplete_create_list(invite_ac); return autocomplete_create_list(invite_ac);
} }
char *
muc_invite_password(const char * const room)
{
return g_hash_table_lookup(invite_passwords, room);
}
gboolean gboolean
muc_invites_contain(const char * const room) muc_invites_contain(const char * const room)
{ {
@ -150,6 +165,7 @@ void
muc_invites_clear(void) muc_invites_clear(void)
{ {
autocomplete_clear(invite_ac); autocomplete_clear(invite_ac);
g_hash_table_remove_all(invite_passwords);
} }
void void
@ -177,6 +193,7 @@ muc_join(const char * const room, const char * const nick,
new_room->roster_received = FALSE; new_room->roster_received = FALSE;
new_room->pending_nick_change = FALSE; new_room->pending_nick_change = FALSE;
new_room->autojoin = autojoin; new_room->autojoin = autojoin;
new_room->member_type = MUC_MEMBER_TYPE_UNKNOWN;
g_hash_table_insert(rooms, strdup(room), new_room); 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 * 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 * the service has responded
*/ */
void 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 static void
_free_room(ChatRoom *room) _free_room(ChatRoom *room)
{ {
@ -790,16 +832,10 @@ _free_room(ChatRoom *room)
static static
gint _compare_occupants(Occupant *a, Occupant *b) gint _compare_occupants(Occupant *a, Occupant *b)
{ {
const char * utf8_str_a = a->nick; const char * utf8_str_a = a->nick_collate_key;
const char * utf8_str_b = b->nick; const char * utf8_str_b = b->nick_collate_key;
gchar *key_a = g_utf8_collate_key(utf8_str_a, -1); gint result = g_strcmp0(utf8_str_a, utf8_str_b);
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);
return result; return result;
} }
@ -905,8 +941,10 @@ _muc_occupant_new(const char *const nick, const char * const jid, muc_role_t rol
if (nick) { if (nick) {
occupant->nick = strdup(nick); occupant->nick = strdup(nick);
occupant->nick_collate_key = g_utf8_collate_key(occupant->nick, -1);
} else { } else {
occupant->nick = NULL; occupant->nick = NULL;
occupant->nick_collate_key = NULL;
} }
if (jid) { if (jid) {
@ -934,6 +972,7 @@ _occupant_free(Occupant *occupant)
{ {
if (occupant) { if (occupant) {
free(occupant->nick); free(occupant->nick);
free(occupant->nick_collate_key);
free(occupant->jid); free(occupant->jid);
free(occupant->status); free(occupant->status);
free(occupant); free(occupant);

View File

@ -1,7 +1,7 @@
/* /*
* muc.h * 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. * This file is part of Profanity.
* *
@ -56,8 +56,15 @@ typedef enum {
MUC_AFFILIATION_OWNER MUC_AFFILIATION_OWNER
} muc_affiliation_t; } 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 { typedef struct _muc_occupant_t {
char *nick; char *nick;
gchar *nick_collate_key;
char *jid; char *jid;
muc_role_t role; muc_role_t role;
muc_affiliation_t affiliation; muc_affiliation_t affiliation;
@ -76,6 +83,8 @@ gboolean muc_autojoin(const char * const room);
GList* muc_rooms(void); GList* muc_rooms(void);
void muc_set_features(const char * const room, GSList *features);
char* muc_nick(const char * const room); char* muc_nick(const char * const room);
char* muc_password(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); 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); 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); void muc_invites_remove(const char * const room);
gint muc_invites_count(void); gint muc_invites_count(void);
GSList* muc_invites(void); GSList* muc_invites(void);
@ -116,6 +125,7 @@ gboolean muc_invites_contain(const char * const room);
void muc_invites_reset_ac(void); void muc_invites_reset_ac(void);
char* muc_invites_find(const char * const search_str); char* muc_invites_find(const char * const search_str);
void muc_invites_clear(void); 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); void muc_set_subject(const char * const room, const char * const subject);
char* muc_subject(const char * const room); 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_role_str(const char * const room);
char *muc_affiliation_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 #endif

View File

@ -1,7 +1,7 @@
/* /*
* otr.c * 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. * This file is part of Profanity.
* *
@ -110,7 +110,7 @@ static void
cb_inject_message(void *opdata, const char *accountname, cb_inject_message(void *opdata, const char *accountname,
const char *protocol, const char *recipient, const char *message) const char *protocol, const char *recipient, const char *message)
{ {
message_send_chat(recipient, message); message_send_chat_encrypted(recipient, message);
} }
static void static void
@ -179,7 +179,7 @@ otr_init(void)
void void
otr_shutdown(void) otr_shutdown(void)
{ {
if (jid != NULL) { if (jid) {
free(jid); free(jid);
} }
} }
@ -193,7 +193,7 @@ otr_poll(void)
void void
otr_on_connect(ProfAccount *account) otr_on_connect(ProfAccount *account)
{ {
if (jid != NULL) { if (jid) {
free(jid); free(jid);
} }
jid = strdup(account->jid); jid = strdup(account->jid);
@ -269,6 +269,89 @@ otr_on_connect(ProfAccount *account)
return; 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 void
otr_keygen(ProfAccount *account) otr_keygen(ProfAccount *account)
{ {
@ -277,7 +360,7 @@ otr_keygen(ProfAccount *account)
return; return;
} }
if (jid != NULL) { if (jid) {
free(jid); free(jid);
} }
jid = strdup(account->jid); jid = strdup(account->jid);
@ -365,6 +448,18 @@ otr_key_loaded(void)
return data_loaded; 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 gboolean
otr_is_secure(const char * const recipient) 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) {
if (context->active_fingerprint->trust != NULL) { if (context->active_fingerprint->trust) {
free(context->active_fingerprint->trust); free(context->active_fingerprint->trust);
} }
context->active_fingerprint->trust = strdup("trusted"); context->active_fingerprint->trust = strdup("trusted");
@ -445,7 +540,7 @@ otr_untrust(const char * const recipient)
} }
if (context->active_fingerprint) { if (context->active_fingerprint) {
if (context->active_fingerprint->trust != NULL) { if (context->active_fingerprint->trust) {
free(context->active_fingerprint->trust); free(context->active_fingerprint->trust);
} }
context->active_fingerprint->trust = NULL; 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); ConnContext *context = otrlib_context_find(user_state, recipient, jid);
if (context != NULL) { if (context) {
Fingerprint *fingerprint = context->active_fingerprint; Fingerprint *fingerprint = context->active_fingerprint;
char readable[45]; char readable[45];
otrl_privkey_hash_to_human(readable, fingerprint->fingerprint); otrl_privkey_hash_to_human(readable, fingerprint->fingerprint);
@ -563,7 +658,7 @@ otr_get_policy(const char * const recipient)
} }
// check default account setting // check default account setting
if (account->otr_policy != NULL) { if (account->otr_policy) {
prof_otrpolicy_t result; prof_otrpolicy_t result;
if (g_strcmp0(account->otr_policy, "manual") == 0) { if (g_strcmp0(account->otr_policy, "manual") == 0) {
result = PROF_OTRPOLICY_MANUAL; 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); OtrlTLV *tlv = otrl_tlv_find(tlvs, OTRL_TLV_DISCONNECTED);
if (tlv) { if (tlv) {
if (context != NULL) { if (context) {
otrl_context_force_plaintext(context); otrl_context_force_plaintext(context);
ui_gone_insecure(from); ui_gone_insecure(from);
} }
@ -637,7 +732,7 @@ otr_decrypt_message(const char * const from, const char * const message, gboolea
return NULL; return NULL;
// message was decrypted, return to user // message was decrypted, return to user
} else if (decrypted != NULL) { } else if (decrypted) {
*was_decrypted = TRUE; *was_decrypted = TRUE;
return decrypted; return decrypted;

View File

@ -1,7 +1,7 @@
/* /*
* otr.h * 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. * This file is part of Profanity.
* *
@ -39,6 +39,7 @@
#include <libotr/message.h> #include <libotr/message.h>
#include "config/accounts.h" #include "config/accounts.h"
#include "ui/window.h"
typedef enum { typedef enum {
PROF_OTRPOLICY_MANUAL, PROF_OTRPOLICY_MANUAL,
@ -56,8 +57,14 @@ char* otr_libotr_version(void);
char* otr_start_query(void); char* otr_start_query(void);
void otr_poll(void); void otr_poll(void);
void otr_on_connect(ProfAccount *account); 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); void otr_keygen(ProfAccount *account);
char* otr_tag_message(const char * const msg);
gboolean otr_key_loaded(void); gboolean otr_key_loaded(void);
gboolean otr_is_secure(const char * const recipient); gboolean otr_is_secure(const char * const recipient);

View File

@ -1,7 +1,7 @@
/* /*
* otrlib.h * 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. * This file is part of Profanity.
* *

View File

@ -1,7 +1,7 @@
/* /*
* otrlibv3.c * 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. * 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", ConnContext *context = otrl_context_find(user_state, recipient, jid, "xmpp",
0, NULL, NULL, NULL); 0, NULL, NULL, NULL);
if (context != NULL) { if (context) {
otrl_message_disconnect(user_state, ops, NULL, jid, "xmpp", recipient); otrl_message_disconnect(user_state, ops, NULL, jid, "xmpp", recipient);
} }
} }
@ -171,7 +171,7 @@ otrlib_handle_tlvs(OtrlUserState user_state, OtrlMessageAppOps *ops, ConnContext
} else { } else {
context->smstate->nextExpected = OTRL_SMP_EXPECT1; context->smstate->nextExpected = OTRL_SMP_EXPECT1;
if (context->smstate->received_question == 0) { 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_smp_successful(context->username);
ui_trust(context->username); ui_trust(context->username);
} else { } else {
@ -193,7 +193,7 @@ otrlib_handle_tlvs(OtrlUserState user_state, OtrlMessageAppOps *ops, ConnContext
otrl_message_abort_smp(user_state, ops, NULL, context); otrl_message_abort_smp(user_state, ops, NULL, context);
} else { } else {
context->smstate->nextExpected = OTRL_SMP_EXPECT1; 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_smp_successful(context->username);
ui_trust(context->username); ui_trust(context->username);
} else { } else {

View File

@ -1,7 +1,7 @@
/* /*
* otrlibv4.c * 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. * This file is part of Profanity.
* *
@ -113,12 +113,57 @@ cb_handle_msg_event(void *opdata, OtrlMessageEvent msg_event,
ConnContext *context, const char *message, ConnContext *context, const char *message,
gcry_error_t err) gcry_error_t err)
{ {
if (err != 0) { GString *err_msg;
if (message != NULL) { switch (msg_event)
cons_show_error("%s", message); {
} else { case OTRL_MSGEVENT_ENCRYPTION_REQUIRED:
cons_show_error("OTR error event with no message."); 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", ConnContext *context = otrl_context_find(user_state, recipient, jid, "xmpp",
OTRL_INSTAG_MASTER, 0, NULL, NULL, NULL); OTRL_INSTAG_MASTER, 0, NULL, NULL, NULL);
if (context != NULL) { if (context) {
otrl_message_disconnect(user_state, ops, NULL, jid, "xmpp", recipient, 0); otrl_message_disconnect(user_state, ops, NULL, jid, "xmpp", recipient, 0);
} }
} }

View File

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

View File

@ -1,7 +1,7 @@
/* /*
* profanity.h * 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. * This file is part of Profanity.
* *

View File

@ -1,7 +1,7 @@
/* /*
* resource.c * 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. * 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)); Resource *new_resource = malloc(sizeof(struct resource_t));
new_resource->name = strdup(name); new_resource->name = strdup(name);
new_resource->presence = presence; new_resource->presence = presence;
if (status != NULL) { if (status) {
new_resource->status = strdup(status); new_resource->status = strdup(status);
} else { } else {
new_resource->status = NULL; new_resource->status = NULL;
@ -88,7 +88,7 @@ resource_compare_availability(Resource *first, Resource *second)
void resource_destroy(Resource *resource) void resource_destroy(Resource *resource)
{ {
if (resource != NULL) { if (resource) {
free(resource->name); free(resource->name);
free(resource->status); free(resource->status);
free(resource); free(resource);

View File

@ -1,7 +1,7 @@
/* /*
* resource.h * 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. * This file is part of Profanity.
* *

View File

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

View File

@ -1,7 +1,7 @@
/* /*
* roster_list.h * 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. * 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); char * roster_barejid_autocomplete(const char * const search_str);
GSList * roster_get_contacts_by_presence(const char * const presence); GSList * roster_get_contacts_by_presence(const char * const presence);
GSList * roster_get_nogroup(void); GSList * roster_get_nogroup(void);
char * roster_get_msg_display_name(const char * const barejid, const char * const resource);
#endif #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 * 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. * This file is part of Profanity.
* *

View File

@ -1,7 +1,7 @@
/* /*
* autocomplete.h * 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. * 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 * 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. * This file is part of Profanity.
* *
@ -47,9 +47,9 @@
* *
* inp - The line of input * inp - The line of input
* min - The minimum allowed number of arguments * 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. * of the command, or NULL if the validation fails.
* *
* E.g. the following input line: * E.g. the following input line:
@ -69,7 +69,7 @@ parse_args(const char * const inp, int min, int max, gboolean *result)
return NULL; return NULL;
} }
// copy and strip input of leading/trailing whitepsace // copy and strip input of leading/trailing whitespace
char *copy = strdup(inp); char *copy = strdup(inp);
g_strstrip(copy); g_strstrip(copy);
@ -156,7 +156,7 @@ parse_args(const char * const inp, int min, int max, gboolean *result)
token = g_slist_next(token); token = g_slist_next(token);
int arg_count = 0; int arg_count = 0;
while (token != NULL) { while (token) {
args[arg_count++] = strdup(token->data); args[arg_count++] = strdup(token->data);
token = g_slist_next(token); 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 * inp - The line of input
* min - The minimum allowed number of arguments * 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. * of the command, or NULL if the validation fails.
* *
* E.g. the following input line: * 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); token = g_slist_next(token);
int arg_count = 0; int arg_count = 0;
while (token != NULL) { while (token) {
args[arg_count++] = strdup(token->data); args[arg_count++] = strdup(token->data);
token = g_slist_next(token); token = g_slist_next(token);
} }
@ -419,7 +419,7 @@ parse_options(gchar **args, gchar **opt_keys, gboolean *res)
} }
// check if duplicate // 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; *res = FALSE;
g_list_free(keys); g_list_free(keys);
return options; return options;
@ -450,7 +450,7 @@ parse_options(gchar **args, gchar **opt_keys, gboolean *res)
void void
options_destroy(GHashTable *options) options_destroy(GHashTable *options)
{ {
if (options != NULL) { if (options) {
g_hash_table_destroy(options); g_hash_table_destroy(options);
} }
} }

View File

@ -1,7 +1,7 @@
/* /*
* parser.h * 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. * This file is part of Profanity.
* *

View File

@ -1,7 +1,7 @@
/* /*
* tinyurl.c * 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. * This file is part of Profanity.
* *
@ -74,7 +74,7 @@ tinyurl_get(char *url)
g_string_free(full_url, TRUE); g_string_free(full_url, TRUE);
if (output.buffer != NULL) { if (output.buffer) {
output.buffer[output.size++] = '\0'; output.buffer[output.size++] = '\0';
return output.buffer; return output.buffer;
} else { } else {

View File

@ -1,7 +1,7 @@
/* /*
* tinyurl.h * 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. * This file is part of Profanity.
* *

View File

@ -1,7 +1,7 @@
/* /*
* buffer.c * 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. * This file is part of Profanity.
* *
@ -81,7 +81,7 @@ buffer_free(ProfBuff buffer)
void void
buffer_push(ProfBuff buffer, const char show_char, GDateTime *time, 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)); ProfBuffEntry *e = malloc(sizeof(struct prof_buff_entry_t));
e->show_char = show_char; e->show_char = show_char;
@ -90,6 +90,7 @@ buffer_push(ProfBuff buffer, const char show_char, GDateTime *time,
e->time = time; e->time = time;
e->from = strdup(from); e->from = strdup(from);
e->message = strdup(message); e->message = strdup(message);
e->receipt = receipt;
if (g_slist_length(buffer->entries) == BUFF_SIZE) { if (g_slist_length(buffer->entries) == BUFF_SIZE) {
_free_entry(buffer->entries->data); _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); 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* ProfBuffEntry*
buffer_yield_entry(ProfBuff buffer, int entry) buffer_yield_entry(ProfBuff buffer, int entry)
{ {
@ -112,5 +131,9 @@ _free_entry(ProfBuffEntry *entry)
free(entry->message); free(entry->message);
free(entry->from); free(entry->from);
g_date_time_unref(entry->time); g_date_time_unref(entry->time);
if (entry->receipt) {
free(entry->receipt->id);
free(entry->receipt);
}
free(entry); free(entry);
} }

View File

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

View File

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

View File

@ -1,7 +1,7 @@
/* /*
* notifier.c * 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. * This file is part of Profanity.
* *
@ -48,10 +48,10 @@
#include "log.h" #include "log.h"
#include "muc.h" #include "muc.h"
#include "ui/ui.h" #include "ui/ui.h"
#include "ui/windows.h"
#include "config/preferences.h" #include "config/preferences.h"
static void _notify(const char * const message, int timeout, static void _notify(const char * const message, int timeout, const char * const category);
const char * const category);
static GTimer *remind_timer; 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, from);
g_string_append(message, "\nto: "); g_string_append(message, "\nto: ");
g_string_append(message, room); g_string_append(message, room);
if (reason != NULL) { if (reason) {
g_string_append_printf(message, "\n\"%s\"", reason); g_string_append_printf(message, "\n\"%s\"", reason);
} }
@ -99,17 +99,25 @@ notify_invite(const char * const from, const char * const room,
} }
void 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(""); int num = wins_get_num(window);
g_string_append_printf(message, "%s (win %d)", handle, win); if (num == 10) {
if (text != NULL) { num = 0;
g_string_append_printf(message, "\n%s", text);
} }
_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 void
@ -117,7 +125,7 @@ notify_room_message(const char * const handle, const char * const room, int win,
{ {
GString *message = g_string_new(""); GString *message = g_string_new("");
g_string_append_printf(message, "%s in %s (win %d)", handle, room, win); 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); g_string_append_printf(message, "\n%s", text);
} }
@ -243,10 +251,9 @@ _notify(const char * const message, int timeout,
Shell_NotifyIcon(NIM_MODIFY, &nid); Shell_NotifyIcon(NIM_MODIFY, &nid);
#endif #endif
#ifdef HAVE_OSXNOTIFY #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(message, "'", "'\\''");
char *escaped_single = str_replace(escaped_double, "`", "\\`");
if (escaped_single[0] == '<') { if (escaped_single[0] == '<') {
g_string_append(notify_command, "\\<"); 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, escaped_single);
} }
g_string_append(notify_command, "\""); g_string_append(notify_command, "'");
free(escaped_double);
free(escaped_single); free(escaped_single);
char *term_name = getenv("TERM_PROGRAM"); char *term_name = getenv("TERM_PROGRAM");
@ -276,7 +282,7 @@ _notify(const char * const message, int timeout,
app_id = "com.googlecode.iterm2"; app_id = "com.googlecode.iterm2";
} }
if (app_id != NULL) { if (app_id) {
g_string_append(notify_command, " -sender "); g_string_append(notify_command, " -sender ");
g_string_append(notify_command, app_id); g_string_append(notify_command, app_id);
} }
@ -288,4 +294,4 @@ _notify(const char * const message, int timeout,
g_string_free(notify_command, TRUE); g_string_free(notify_command, TRUE);
#endif #endif
} }

View File

@ -1,7 +1,7 @@
/* /*
* occupantswin.c * 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. * This file is part of Profanity.
* *
@ -40,7 +40,7 @@
#include "config/preferences.h" #include "config/preferences.h"
static void 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); const char *presence_str = string_from_resource_presence(occupant->presence);
theme_item_t presence_colour = theme_main_presence_attrs(presence_str); 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); win_printline_nowrap(layout->subwin, msg->str);
g_string_free(msg, TRUE); 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)); wattroff(layout->subwin, theme_attrs(presence_colour));
} }
@ -74,7 +81,7 @@ occupantswin_occupants(const char * const roomjid)
while (roster_curr) { while (roster_curr) {
Occupant *occupant = roster_curr->data; Occupant *occupant = roster_curr->data;
if (occupant->role == MUC_ROLE_MODERATOR) { if (occupant->role == MUC_ROLE_MODERATOR) {
_occuptantswin_occupant(layout, occupant); _occuptantswin_occupant(layout, occupant, mucwin->showjid);
} }
roster_curr = g_list_next(roster_curr); roster_curr = g_list_next(roster_curr);
} }
@ -86,7 +93,7 @@ occupantswin_occupants(const char * const roomjid)
while (roster_curr) { while (roster_curr) {
Occupant *occupant = roster_curr->data; Occupant *occupant = roster_curr->data;
if (occupant->role == MUC_ROLE_PARTICIPANT) { if (occupant->role == MUC_ROLE_PARTICIPANT) {
_occuptantswin_occupant(layout, occupant); _occuptantswin_occupant(layout, occupant, mucwin->showjid);
} }
roster_curr = g_list_next(roster_curr); roster_curr = g_list_next(roster_curr);
} }
@ -98,7 +105,7 @@ occupantswin_occupants(const char * const roomjid)
while (roster_curr) { while (roster_curr) {
Occupant *occupant = roster_curr->data; Occupant *occupant = roster_curr->data;
if (occupant->role == MUC_ROLE_VISITOR) { if (occupant->role == MUC_ROLE_VISITOR) {
_occuptantswin_occupant(layout, occupant); _occuptantswin_occupant(layout, occupant, mucwin->showjid);
} }
roster_curr = g_list_next(roster_curr); roster_curr = g_list_next(roster_curr);
} }
@ -109,7 +116,7 @@ occupantswin_occupants(const char * const roomjid)
GList *roster_curr = occupants; GList *roster_curr = occupants;
while (roster_curr) { while (roster_curr) {
Occupant *occupant = roster_curr->data; Occupant *occupant = roster_curr->data;
_occuptantswin_occupant(layout, occupant); _occuptantswin_occupant(layout, occupant, mucwin->showjid);
roster_curr = g_list_next(roster_curr); roster_curr = g_list_next(roster_curr);
} }
} }

View File

@ -1,7 +1,7 @@
/* /*
* rosterwin.c * 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. * This file is part of Profanity.
* *

View File

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

View File

@ -1,7 +1,7 @@
/* /*
* statusbar.h * 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. * This file is part of Profanity.
* *

View File

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

View File

@ -1,7 +1,7 @@
/* /*
* titlebar.h * 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. * This file is part of Profanity.
* *

View File

@ -1,7 +1,7 @@
/* /*
* ui.h * 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. * This file is part of Profanity.
* *
@ -59,9 +59,8 @@ void ui_close(void);
void ui_redraw(void); void ui_redraw(void);
void ui_resize(void); void ui_resize(void);
GSList* ui_get_chat_recipients(void); GSList* ui_get_chat_recipients(void);
gboolean ui_switch_win(const int i); void ui_switch_win(ProfWin *window);
void ui_next_win(void); void ui_sigwinch_handler(int sig);
void ui_previous_win(void);
void ui_gone_secure(const char * const barejid, gboolean trusted); void ui_gone_secure(const char * const barejid, gboolean trusted);
void ui_gone_insecure(const char * const barejid); 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_authenticating(const char * const barejid);
void ui_otr_authetication_waiting(const char * const recipient); 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); unsigned long ui_get_idle_time(void);
void ui_reset_idle_time(void); void ui_reset_idle_time(void);
void ui_new_chat_win(const char * const barejid); ProfPrivateWin* ui_new_private_win(const char * const fulljid);
void 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); void ui_print_system_msg_from_recipient(const char * const barejid, const char *message);
gint ui_unread(void); gint ui_unread(void);
void ui_close_connected_win(int index); void ui_close_connected_win(int index);
@ -94,7 +95,6 @@ int ui_close_read_wins(void);
// current window actions // current window actions
void ui_clear_current(void); void ui_clear_current(void);
win_type_t ui_current_win_type(void); win_type_t ui_current_win_type(void);
int ui_current_win_index(void);
gboolean ui_current_win_is_otr(void); gboolean ui_current_win_is_otr(void);
ProfChatWin *ui_get_current_chat(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_line(const char * const msg, ...);
void ui_current_print_formatted_line(const char show_char, int attrs, 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_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); win_type_t ui_win_type(int index);
void ui_close_win(int index); void ui_close_win(int index);
gboolean ui_win_exists(int index);
int ui_win_unread(int index); int ui_win_unread(int index);
char * ui_ask_password(void); char * ui_ask_password(void);
void ui_handle_stanza(const char * const msg); void ui_handle_stanza(const char * const msg);
// ui events // 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_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_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_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_disconnected(void);
void ui_recipient_gone(const char * const barejid, const char * const resource); 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, void ui_outgoing_chat_msg(ProfChatWin *chatwin, const char * const message, char *id);
const char * const message); void ui_outgoing_chat_msg_carbon(const char * const barejid, const char * const message);
void ui_outgoing_private_msg(const char * const from, const char * const fulljid, void ui_outgoing_private_msg(ProfPrivateWin *privwin, const char * const message);
const char * const message);
void ui_room_join(const char * const roomjid, gboolean focus); void ui_room_join(const char * const roomjid, gboolean focus);
void ui_switch_to_room(const char * const roomjid); 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_nick_change(const char * const roomjid, const char * const nick);
void ui_room_member_presence(const char * const roomjid, void ui_room_member_presence(const char * const roomjid,
const char * const nick, const char * const show, const char * const status); 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_show_occupants(const char * const roomjid);
void ui_room_hide_occupants(const char * const roomjid); void ui_room_hide_occupants(const char * const roomjid);
void ui_show_roster(void); void ui_show_roster(void);
@ -218,6 +220,11 @@ void ui_tidy_wins(void);
void ui_prune_wins(void); void ui_prune_wins(void);
gboolean ui_swap_wins(int source_win, int target_win); 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_auto_away(void);
void ui_end_auto_away(void); void ui_end_auto_away(void);
void ui_titlebar_presence(contact_presence_t presence); 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_about(void);
void ui_statusbar_new(const int win); void ui_statusbar_new(const int win);
char * ui_readline(void); char* ui_readline(void);
void ui_input_clear(void); void ui_input_clear(void);
void ui_input_nonblocking(gboolean); 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)); 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_intype_setting(void);
void cons_gone_setting(void); void cons_gone_setting(void);
void cons_history_setting(void); void cons_history_setting(void);
void cons_carbons_setting(void);
void cons_receipts_setting(void);
void cons_log_setting(void); void cons_log_setting(void);
void cons_chlog_setting(void); void cons_chlog_setting(void);
void cons_grlog_setting(void); void cons_grlog_setting(void);
@ -332,7 +342,7 @@ void notifier_initialise(void);
void notifier_uninit(void); void notifier_uninit(void);
void notify_typing(const char * const handle); 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, void notify_room_message(const char * const handle, const char * const room,
int win, const char * const text); int win, const char * const text);
void notify_remind(void); void notify_remind(void);

View File

@ -1,7 +1,7 @@
/* /*
* window.c * 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. * This file is part of Profanity.
* *
@ -38,6 +38,7 @@
#include <string.h> #include <string.h>
#include <time.h> #include <time.h>
#include <assert.h> #include <assert.h>
#include <wchar.h>
#include <glib.h> #include <glib.h>
#ifdef HAVE_NCURSESW_NCURSES_H #ifdef HAVE_NCURSESW_NCURSES_H
@ -59,7 +60,7 @@
#define CEILING(X) (X-(int)(X) > 0 ? (int)(X+1) : (int)(X)) #define CEILING(X) (X-(int)(X) > 0 ? (int)(X+1) : (int)(X))
static void _win_print(ProfWin *window, const char show_char, GDateTime *time, 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); static void _win_print_wrapped(WINDOW *win, const char * const message);
int int
@ -134,7 +135,7 @@ win_create_chat(const char * const barejid)
new_win->barejid = strdup(barejid); new_win->barejid = strdup(barejid);
new_win->resource_override = NULL; new_win->resource_override = NULL;
new_win->is_otr = FALSE; new_win->enc_mode = PROF_ENC_NONE;
new_win->is_trusted = FALSE; new_win->is_trusted = FALSE;
new_win->history_shown = FALSE; new_win->history_shown = FALSE;
new_win->unread = 0; new_win->unread = 0;
@ -177,6 +178,11 @@ win_create_muc(const char * const roomjid)
new_win->roomjid = strdup(roomjid); new_win->roomjid = strdup(roomjid);
new_win->unread = 0; 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; new_win->memcheck = PROFMUCWIN_MEMCHECK;
@ -331,12 +337,13 @@ win_free(ProfWin* window)
buffer_free(window->layout->buffer); buffer_free(window->layout->buffer);
delwin(window->layout->win); delwin(window->layout->win);
} }
free(window->layout);
if (window->type == WIN_CHAT) { if (window->type == WIN_CHAT) {
ProfChatWin *chatwin = (ProfChatWin*)window; ProfChatWin *chatwin = (ProfChatWin*)window;
free(chatwin->barejid); free(chatwin->barejid);
free(chatwin->resource_override); free(chatwin->resource_override);
free(chatwin->state); chat_state_free(chatwin->state);
} }
if (window->type == WIN_MUC) { if (window->type == WIN_MUC) {
@ -359,7 +366,101 @@ win_free(ProfWin* window)
} }
void 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 rows = getmaxy(stdscr);
int y = getcury(window->layout->win); 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 void
@ -515,14 +553,14 @@ win_show_occupant(ProfWin *window, Occupant *occupant)
theme_item_t presence_colour = theme_main_presence_attrs(presence_str); theme_item_t presence_colour = theme_main_presence_attrs(presence_str);
win_save_print(window, '-', NULL, NO_EOL, presence_colour, "", occupant->nick); win_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_vprint(window, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", " is %s", presence_str);
if (occupant->status) { 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 void
@ -536,15 +574,15 @@ win_show_contact(ProfWin *window, PContact contact)
theme_item_t presence_colour = theme_main_presence_attrs(presence); theme_item_t presence_colour = theme_main_presence_attrs(presence);
if (name != NULL) { if (name) {
win_save_print(window, '-', NULL, NO_EOL, presence_colour, "", name); win_print(window, '-', NULL, NO_EOL, presence_colour, "", name);
} else { } 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(); GDateTime *now = g_date_time_new_now_local();
GTimeSpan span = g_date_time_difference(now, last_activity); 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; int seconds = span / G_TIME_SPAN_SECOND;
if (hours > 0) { 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 { 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) { if (status) {
win_save_vprint(window, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", ", \"%s\"", p_contact_status(contact)); 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 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); theme_item_t presence_colour = theme_main_presence_attrs(presence_str);
win_save_print(window, '!', NULL, NO_EOL, presence_colour, "", occupant->nick); win_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_vprint(window, '!', NULL, NO_DATE | NO_EOL, presence_colour, "", " is %s", presence_str);
if (occupant->status) { 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) { 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_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, "", " Role: %s", occupant_role);
Jid *jidp = jid_create_from_bare_and_resource(room, occupant->nick); Jid *jidp = jid_create_from_bare_and_resource(room, occupant->nick);
Capabilities *caps = caps_lookup(jidp->fulljid); Capabilities *caps = caps_lookup(jidp->fulljid);
@ -600,47 +638,47 @@ win_show_occupant_info(ProfWin *window, const char * const room, Occupant *occup
if (caps) { if (caps) {
// show identity // show identity
if ((caps->category != NULL) || (caps->type != NULL) || (caps->name != NULL)) { if (caps->category || caps->type || caps->name) {
win_save_print(window, '!', NULL, NO_EOL, 0, "", " Identity: "); win_print(window, '!', NULL, NO_EOL, 0, "", " Identity: ");
if (caps->name != NULL) { if (caps->name) {
win_save_print(window, '!', NULL, NO_DATE | NO_EOL, 0, "", caps->name); win_print(window, '!', NULL, NO_DATE | NO_EOL, 0, "", caps->name);
if ((caps->category != NULL) || (caps->type != NULL)) { if (caps->category || caps->type) {
win_save_print(window, '-', NULL, NO_DATE | NO_EOL, 0, "", " "); win_print(window, '-', NULL, NO_DATE | NO_EOL, 0, "", " ");
} }
} }
if (caps->type != NULL) { if (caps->type) {
win_save_print(window, '!', NULL, NO_DATE | NO_EOL, 0, "", caps->type); win_print(window, '!', NULL, NO_DATE | NO_EOL, 0, "", caps->type);
if (caps->category != NULL) { if (caps->category) {
win_save_print(window, '!', NULL, NO_DATE | NO_EOL, 0, "", " "); win_print(window, '!', NULL, NO_DATE | NO_EOL, 0, "", " ");
} }
} }
if (caps->category != NULL) { if (caps->category) {
win_save_print(window, '!', NULL, NO_DATE | NO_EOL, 0, "", caps->category); win_print(window, '!', NULL, NO_DATE | NO_EOL, 0, "", caps->category);
} }
win_save_newline(window); win_newline(window);
} }
if (caps->software != NULL) { if (caps->software) {
win_save_vprint(window, '!', NULL, NO_EOL, 0, "", " Software: %s", caps->software); win_vprint(window, '!', NULL, NO_EOL, 0, "", " Software: %s", caps->software);
} }
if (caps->software_version != NULL) { if (caps->software_version) {
win_save_vprint(window, '!', NULL, NO_DATE | NO_EOL, 0, "", ", %s", caps->software_version); win_vprint(window, '!', NULL, NO_DATE | NO_EOL, 0, "", ", %s", caps->software_version);
} }
if ((caps->software != NULL) || (caps->software_version != NULL)) { if (caps->software || caps->software_version) {
win_save_newline(window); win_newline(window);
} }
if (caps->os != NULL) { if (caps->os) {
win_save_vprint(window, '!', NULL, NO_EOL, 0, "", " OS: %s", caps->os); win_vprint(window, '!', NULL, NO_EOL, 0, "", " OS: %s", caps->os);
} }
if (caps->os_version != NULL) { if (caps->os_version) {
win_save_vprint(window, '!', NULL, NO_DATE | NO_EOL, 0, "", ", %s", caps->os_version); win_vprint(window, '!', NULL, NO_DATE | NO_EOL, 0, "", ", %s", caps->os_version);
} }
if ((caps->os != NULL) || (caps->os_version != NULL)) { if (caps->os || caps->os_version) {
win_save_newline(window); win_newline(window);
} }
caps_destroy(caps); caps_destroy(caps);
} }
win_save_print(window, '-', NULL, 0, 0, "", ""); win_print(window, '-', NULL, 0, 0, "", "");
} }
void void
@ -650,24 +688,22 @@ win_show_info(ProfWin *window, PContact contact)
const char *name = p_contact_name(contact); const char *name = p_contact_name(contact);
const char *presence = p_contact_presence(contact); const char *presence = p_contact_presence(contact);
const char *sub = p_contact_subscription(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); GDateTime *last_activity = p_contact_last_activity(contact);
theme_item_t presence_colour = theme_main_presence_attrs(presence); theme_item_t presence_colour = theme_main_presence_attrs(presence);
win_save_print(window, '-', NULL, 0, 0, "", ""); win_print(window, '-', NULL, 0, 0, "", "");
win_save_print(window, '-', NULL, NO_EOL, presence_colour, "", barejid); win_print(window, '-', NULL, NO_EOL, presence_colour, "", barejid);
if (name != NULL) { if (name) {
win_save_vprint(window, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", " (%s)", 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) { if (sub) {
win_save_vprint(window, '-', NULL, 0, 0, "", "Subscription: %s", 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(); GDateTime *now = g_date_time_new_now_local();
GTimeSpan span = g_date_time_difference(now, last_activity); 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; int seconds = span / G_TIME_SPAN_SECOND;
if (hours > 0) { 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 { 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); g_date_time_unref(now);
} }
if (resources != NULL) { GList *resources = p_contact_get_available_resources(contact);
win_save_print(window, '-', NULL, 0, 0, "", "Resources:"); GList *ordered_resources = NULL;
if (resources) {
win_print(window, '-', NULL, 0, 0, "", "Resources:");
// sort in order of availabiltiy // sort in order of availability
while (resources != NULL) { GList *curr = resources;
Resource *resource = resources->data; while (curr) {
Resource *resource = curr->data;
ordered_resources = g_list_insert_sorted(ordered_resources, ordered_resources = g_list_insert_sorted(ordered_resources,
resource, (GCompareFunc)resource_compare_availability); resource, (GCompareFunc)resource_compare_availability);
resources = g_list_next(resources); curr = g_list_next(curr);
} }
} }
g_list_free(resources);
while (ordered_resources != NULL) { GList *curr = ordered_resources;
Resource *resource = ordered_resources->data; while (curr) {
Resource *resource = curr->data;
const char *resource_presence = string_from_resource_presence(resource->presence); const char *resource_presence = string_from_resource_presence(resource->presence);
theme_item_t presence_colour = theme_main_presence_attrs(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); win_vprint(window, '-', NULL, NO_EOL, presence_colour, "", " %s (%d), %s", resource->name, resource->priority, resource_presence);
if (resource->status != NULL) { if (resource->status) {
win_save_vprint(window, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", ", \"%s\"", 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); Jid *jidp = jid_create_from_bare_and_resource(barejid, resource->name);
Capabilities *caps = caps_lookup(jidp->fulljid); Capabilities *caps = caps_lookup(jidp->fulljid);
@ -715,48 +756,49 @@ win_show_info(ProfWin *window, PContact contact)
if (caps) { if (caps) {
// show identity // show identity
if ((caps->category != NULL) || (caps->type != NULL) || (caps->name != NULL)) { if (caps->category || caps->type || caps->name) {
win_save_print(window, '-', NULL, NO_EOL, 0, "", " Identity: "); win_print(window, '-', NULL, NO_EOL, 0, "", " Identity: ");
if (caps->name != NULL) { if (caps->name) {
win_save_print(window, '-', NULL, NO_DATE | NO_EOL, 0, "", caps->name); win_print(window, '-', NULL, NO_DATE | NO_EOL, 0, "", caps->name);
if ((caps->category != NULL) || (caps->type != NULL)) { if (caps->category || caps->type) {
win_save_print(window, '-', NULL, NO_DATE | NO_EOL, 0, "", " "); win_print(window, '-', NULL, NO_DATE | NO_EOL, 0, "", " ");
} }
} }
if (caps->type != NULL) { if (caps->type) {
win_save_print(window, '-', NULL, NO_DATE | NO_EOL, 0, "", caps->type); win_print(window, '-', NULL, NO_DATE | NO_EOL, 0, "", caps->type);
if (caps->category != NULL) { if (caps->category) {
win_save_print(window, '-', NULL, NO_DATE | NO_EOL, 0, "", " "); win_print(window, '-', NULL, NO_DATE | NO_EOL, 0, "", " ");
} }
} }
if (caps->category != NULL) { if (caps->category) {
win_save_print(window, '-', NULL, NO_DATE | NO_EOL, 0, "", caps->category); win_print(window, '-', NULL, NO_DATE | NO_EOL, 0, "", caps->category);
} }
win_save_newline(window); win_newline(window);
} }
if (caps->software != NULL) { if (caps->software) {
win_save_vprint(window, '-', NULL, NO_EOL, 0, "", " Software: %s", caps->software); win_vprint(window, '-', NULL, NO_EOL, 0, "", " Software: %s", caps->software);
} }
if (caps->software_version != NULL) { if (caps->software_version) {
win_save_vprint(window, '-', NULL, NO_DATE | NO_EOL, 0, "", ", %s", caps->software_version); win_vprint(window, '-', NULL, NO_DATE | NO_EOL, 0, "", ", %s", caps->software_version);
} }
if ((caps->software != NULL) || (caps->software_version != NULL)) { if (caps->software || caps->software_version) {
win_save_newline(window); win_newline(window);
} }
if (caps->os != NULL) { if (caps->os) {
win_save_vprint(window, '-', NULL, NO_EOL, 0, "", " OS: %s", caps->os); win_vprint(window, '-', NULL, NO_EOL, 0, "", " OS: %s", caps->os);
} }
if (caps->os_version != NULL) { if (caps->os_version) {
win_save_vprint(window, '-', NULL, NO_DATE | NO_EOL, 0, "", ", %s", caps->os_version); win_vprint(window, '-', NULL, NO_DATE | NO_EOL, 0, "", ", %s", caps->os_version);
} }
if ((caps->os != NULL) || (caps->os_version != NULL)) { if (caps->os || caps->os_version) {
win_save_newline(window); win_newline(window);
} }
caps_destroy(caps); caps_destroy(caps);
} }
ordered_resources = g_list_next(ordered_resources); curr = g_list_next(curr);
} }
g_list_free(ordered_resources);
} }
void void
@ -767,7 +809,7 @@ win_show_status_string(ProfWin *window, const char * const from,
{ {
theme_item_t presence_colour; theme_item_t presence_colour;
if (show != NULL) { if (show) {
presence_colour = theme_main_presence_attrs(show); presence_colour = theme_main_presence_attrs(show);
} else if (strcmp(default_show, "online") == 0) { } else if (strcmp(default_show, "online") == 0) {
presence_colour = THEME_ONLINE; 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) if (show)
win_save_vprint(window, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", " is %s", show); win_vprint(window, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", " is %s", show);
else 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(); GDateTime *now = g_date_time_new_now_local();
GTimeSpan span = g_date_time_difference(now, last_activity); GTimeSpan span = g_date_time_difference(now, last_activity);
g_date_time_unref(now); 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; int seconds = span / G_TIME_SPAN_SECOND;
if (hours > 0) { 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 { 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) if (status)
win_save_vprint(window, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", ", \"%s\"", 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_CHAT:
case WIN_PRIVATE: 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; break;
default: default:
assert(FALSE); assert(FALSE);
@ -826,19 +868,19 @@ win_print_incoming_message(ProfWin *window, GTimeVal *tv_stamp,
} }
void 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, ...) int flags, theme_item_t theme_item, const char * const from, const char * const message, ...)
{ {
va_list arg; va_list arg;
va_start(arg, message); va_start(arg, message);
GString *fmt_msg = g_string_new(NULL); GString *fmt_msg = g_string_new(NULL);
g_string_vprintf(fmt_msg, message, arg); 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); g_string_free(fmt_msg, TRUE);
} }
void 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) int flags, theme_item_t theme_item, const char * const from, const char * const message)
{ {
GDateTime *time; 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); time = g_date_time_new_from_timeval_utc(tstamp);
} }
buffer_push(window->layout->buffer, 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); _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 // TODO: cross-reference.. this should be replaced by a real event-based system
ui_input_nonblocking(TRUE); ui_input_nonblocking(TRUE);
} }
void 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 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 static void
_win_print(ProfWin *window, const char show_char, GDateTime *time, _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 // flags : 1st bit = 0/1 - me/not me
// 2nd bit = 0/1 - date/no date // 2nd bit = 0/1 - date/no date
@ -907,6 +980,10 @@ _win_print(ProfWin *window, const char show_char, GDateTime *time,
colour = 0; colour = 0;
} }
if (receipt && !receipt->received) {
colour = theme_attrs(THEME_RECEIPT_SENT);
}
wattron(window->layout->win, colour); wattron(window->layout->win, colour);
if (strncmp(message, "/me ", 4) == 0) { if (strncmp(message, "/me ", 4) == 0) {
wprintw(window->layout->win, "*%s ", from); wprintw(window->layout->win, "*%s ", from);
@ -919,7 +996,11 @@ _win_print(ProfWin *window, const char show_char, GDateTime *time,
} }
if (!me_message) { 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)) { if (prefs_get_boolean(PREF_WRAP)) {
@ -935,7 +1016,11 @@ _win_print(ProfWin *window, const char show_char, GDateTime *time,
if (me_message) { if (me_message) {
wattroff(window->layout->win, colour); wattroff(window->layout->win, colour);
} else { } 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 static void
_win_print_wrapped(WINDOW *win, const char * const message) _win_print_wrapped(WINDOW *win, const char * const message)
{ {
int linei = 0;
int wordi = 0; int wordi = 0;
char *word = malloc(strlen(message) + 1); char *word = malloc(strlen(message) + 1);
@ -964,18 +1048,26 @@ _win_print_wrapped(WINDOW *win, const char * const message)
} }
free(time_pref); free(time_pref);
while (message[linei] != '\0') { gchar *curr_ch = g_utf8_offset_to_pointer(message, 0);
if (message[linei] == ' ') {
while (*curr_ch != '\0') {
if (*curr_ch == ' ') {
waddch(win, ' '); waddch(win, ' ');
linei++; curr_ch = g_utf8_next_char(curr_ch);
} else if (message[linei] == '\n') { } else if (*curr_ch == '\n') {
waddch(win, '\n'); waddch(win, '\n');
_win_indent(win, indent); _win_indent(win, indent);
linei++; curr_ch = g_utf8_next_char(curr_ch);
} else { } else {
// get word
wordi = 0; wordi = 0;
while (message[linei] != ' ' && message[linei] != '\n' && message[linei] != '\0') { while (*curr_ch != ' ' && *curr_ch != '\n' && *curr_ch != '\0') {
word[wordi++] = message[linei++]; 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'; word[wordi] = '\0';
@ -983,17 +1075,27 @@ _win_print_wrapped(WINDOW *win, const char * const message)
int maxx = getmaxx(win); int maxx = getmaxx(win);
// word larger than line // word larger than line
if (strlen(word) > (maxx - indent)) { if (utf8_display_len(word) > (maxx - indent)) {
int i; gchar *word_ch = g_utf8_offset_to_pointer(word, 0);
for (i = 0; i < wordi; i++) { while(*word_ch != '\0') {
curx = getcurx(win); curx = getcurx(win);
if (curx < indent) { if (curx < indent) {
_win_indent(win, 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 { } else {
if (curx + strlen(word) > maxx) { if (curx + utf8_display_len(word) > maxx) {
waddch(win, '\n'); waddch(win, '\n');
_win_indent(win, indent); _win_indent(win, indent);
} }
@ -1017,7 +1119,7 @@ win_redraw(ProfWin *window)
for (i = 0; i < size; i++) { for (i = 0; i < size; i++) {
ProfBuffEntry *e = buffer_yield_entry(window->layout->buffer, 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 * 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. * This file is part of Profanity.
* *
@ -99,6 +99,11 @@ typedef enum {
WIN_XML WIN_XML
} win_type_t; } win_type_t;
typedef enum {
PROF_ENC_NONE,
PROF_ENC_OTR
} prof_enc_t;
typedef struct prof_win_t { typedef struct prof_win_t {
win_type_t type; win_type_t type;
ProfLayout *layout; ProfLayout *layout;
@ -113,7 +118,7 @@ typedef struct prof_chat_win_t {
char *barejid; char *barejid;
int unread; int unread;
ChatState *state; ChatState *state;
gboolean is_otr; prof_enc_t enc_mode;
gboolean is_trusted; gboolean is_trusted;
char *resource_override; char *resource_override;
gboolean history_shown; gboolean history_shown;
@ -124,6 +129,7 @@ typedef struct prof_muc_win_t {
ProfWin window; ProfWin window;
char *roomjid; char *roomjid;
int unread; int unread;
gboolean showjid;
unsigned long memcheck; unsigned long memcheck;
} ProfMucWin; } ProfMucWin;
@ -168,19 +174,27 @@ void win_print_incoming_message(ProfWin *window, GTimeVal *tv_stamp,
const char * const from, const char * const message); const char * const from, const char * const message);
void win_show_info(ProfWin *window, PContact contact); void win_show_info(ProfWin *window, PContact contact);
void win_show_occupant_info(ProfWin *window, const char * const room, Occupant *occupant); 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_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_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_print_with_receipt(ProfWin *window, const char show_char, GTimeVal *tstamp, int flags,
void win_save_newline(ProfWin *window); 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_redraw(ProfWin *window);
void win_hide_subwin(ProfWin *window); void win_hide_subwin(ProfWin *window);
void win_show_subwin(ProfWin *window); void win_show_subwin(ProfWin *window);
int win_roster_cols(void); int win_roster_cols(void);
int win_occpuants_cols(void); int win_occpuants_cols(void);
void win_printline_nowrap(WINDOW *win, char *msg); 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); int win_unread(ProfWin *window);
gboolean win_has_active_subwin(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 #endif

View File

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

View File

@ -1,7 +1,7 @@
/* /*
* windows.h * 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. * This file is part of Profanity.
* *

View File

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

View File

@ -1,7 +1,7 @@
/* /*
* bookmark.h * 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. * This file is part of Profanity.
* *

View File

@ -1,7 +1,7 @@
/* /*
* capabilities.c * 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. * 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); char *category = g_key_file_get_string(cache, ver, "category", NULL);
if (category) { if (category) {
new_caps->category = strdup(category); new_caps->category = category;
} else { } else {
new_caps->category = NULL; new_caps->category = NULL;
} }
char *type = g_key_file_get_string(cache, ver, "type", NULL); char *type = g_key_file_get_string(cache, ver, "type", NULL);
if (type) { if (type) {
new_caps->type = strdup(type); new_caps->type = type;
} else { } else {
new_caps->type = NULL; new_caps->type = NULL;
} }
char *name = g_key_file_get_string(cache, ver, "name", NULL); char *name = g_key_file_get_string(cache, ver, "name", NULL);
if (name) { if (name) {
new_caps->name = strdup(name); new_caps->name = name;
} else { } else {
new_caps->name = NULL; new_caps->name = NULL;
} }
char *software = g_key_file_get_string(cache, ver, "software", NULL); char *software = g_key_file_get_string(cache, ver, "software", NULL);
if (software) { if (software) {
new_caps->software = strdup(software); new_caps->software = software;
} else { } else {
new_caps->software = NULL; new_caps->software = NULL;
} }
char *software_version = g_key_file_get_string(cache, ver, "software_version", NULL); char *software_version = g_key_file_get_string(cache, ver, "software_version", NULL);
if (software_version) { if (software_version) {
new_caps->software_version = strdup(software_version); new_caps->software_version = software_version;
} else { } else {
new_caps->software_version = NULL; new_caps->software_version = NULL;
} }
char *os = g_key_file_get_string(cache, ver, "os", NULL); char *os = g_key_file_get_string(cache, ver, "os", NULL);
if (os) { if (os) {
new_caps->os = strdup(os); new_caps->os = os;
} else { } else {
new_caps->os = NULL; new_caps->os = NULL;
} }
char *os_version = g_key_file_get_string(cache, ver, "os_version", NULL); char *os_version = g_key_file_get_string(cache, ver, "os_version", NULL);
if (os_version) { if (os_version) {
new_caps->os_version = strdup(os_version); new_caps->os_version = os_version;
} else { } else {
new_caps->os_version = NULL; new_caps->os_version = NULL;
} }
gsize features_len = 0; gsize features_len = 0;
gchar **features = g_key_file_get_string_list(cache, ver, "features", &features_len, NULL); 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; GSList *features_list = NULL;
int i; int i;
for (i = 0; i < features_len; i++) { for (i = 0; i < features_len; i++) {
@ -395,16 +395,16 @@ caps_create(xmpp_stanza_t *query)
GSList *features = NULL; GSList *features = NULL;
xmpp_stanza_t *softwareinfo = xmpp_stanza_get_child_by_ns(query, STANZA_NS_DATA); xmpp_stanza_t *softwareinfo = xmpp_stanza_get_child_by_ns(query, STANZA_NS_DATA);
if (softwareinfo != NULL) { if (softwareinfo) {
DataForm *form = form_create(softwareinfo); DataForm *form = form_create(softwareinfo);
FormField *formField = NULL; FormField *formField = NULL;
char *form_type = form_get_form_type_field(form); char *form_type = form_get_form_type_field(form);
if (g_strcmp0(form_type, STANZA_DATAFORM_SOFTWARE) == 0) { if (g_strcmp0(form_type, STANZA_DATAFORM_SOFTWARE) == 0) {
GSList *field = form->fields; GSList *field = form->fields;
while (field != NULL) { while (field) {
formField = field->data; formField = field->data;
if (formField->values != NULL) { if (formField->values) {
if (strcmp(formField->var, "software") == 0) { if (strcmp(formField->var, "software") == 0) {
software = strdup(formField->values->data); software = strdup(formField->values->data);
} else if (strcmp(formField->var, "software_version") == 0) { } 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); xmpp_stanza_t *child = xmpp_stanza_get_children(query);
GSList *identity_stanzas = NULL; GSList *identity_stanzas = NULL;
while (child != NULL) { while (child) {
if (g_strcmp0(xmpp_stanza_get_name(child), "feature") == 0) { if (g_strcmp0(xmpp_stanza_get_name(child), "feature") == 0) {
features = g_slist_append(features, strdup(xmpp_stanza_get_attribute(child, "var"))); 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)); Capabilities *new_caps = malloc(sizeof(struct capabilities_t));
if (category != NULL) { if (category) {
new_caps->category = strdup(category); new_caps->category = strdup(category);
} else { } else {
new_caps->category = NULL; new_caps->category = NULL;
} }
if (type != NULL) { if (type) {
new_caps->type = strdup(type); new_caps->type = strdup(type);
} else { } else {
new_caps->type = NULL; new_caps->type = NULL;
} }
if (name != NULL) { if (name) {
new_caps->name = strdup(name); new_caps->name = strdup(name);
} else { } else {
new_caps->name = NULL; new_caps->name = NULL;
} }
if (software != NULL) { if (software) {
new_caps->software = software; new_caps->software = software;
} else { } else {
new_caps->software = NULL; new_caps->software = NULL;
} }
if (software_version != NULL) { if (software_version) {
new_caps->software_version = software_version; new_caps->software_version = software_version;
} else { } else {
new_caps->software_version = NULL; new_caps->software_version = NULL;
} }
if (os != NULL) { if (os) {
new_caps->os = os; new_caps->os = os;
} else { } else {
new_caps->os = NULL; new_caps->os = NULL;
} }
if (os_version != NULL) { if (os_version) {
new_caps->os_version = os_version; new_caps->os_version = os_version;
} else { } else {
new_caps->os_version = NULL; new_caps->os_version = NULL;
} }
if (features != NULL) { if (features) {
new_caps->features = features; new_caps->features = features;
} else { } else {
new_caps->features = NULL; new_caps->features = NULL;
@ -635,7 +635,7 @@ caps_close(void)
void void
caps_destroy(Capabilities *caps) caps_destroy(Capabilities *caps)
{ {
if (caps != NULL) { if (caps) {
free(caps->category); free(caps->category);
free(caps->type); free(caps->type);
free(caps->name); free(caps->name);
@ -643,7 +643,7 @@ caps_destroy(Capabilities *caps)
free(caps->software_version); free(caps->software_version);
free(caps->os); free(caps->os);
free(caps->os_version); free(caps->os_version);
if (caps->features != NULL) { if (caps->features) {
g_slist_free_full(caps->features, free); g_slist_free_full(caps->features, free);
} }
free(caps); free(caps);

View File

@ -1,7 +1,7 @@
/* /*
* capabilities.h * 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. * This file is part of Profanity.
* *

View File

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

View File

@ -1,7 +1,7 @@
/* /*
* form.c * 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. * 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"); 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(""); GString *tag = g_string_new("");
g_string_printf(tag, "field%d", tag_num++); g_string_printf(tag, "field%d", tag_num++);
g_hash_table_insert(form->var_to_tag, strdup(field->var), strdup(tag->str)); g_hash_table_insert(form->var_to_tag, strdup(field->var), strdup(tag->str));

View File

@ -1,7 +1,7 @@
/* /*
* form.h * 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. * This file is part of Profanity.
* *

View File

@ -1,7 +1,7 @@
/* /*
* iq.c * 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. * This file is part of Profanity.
* *
@ -47,8 +47,9 @@
#include "log.h" #include "log.h"
#include "muc.h" #include "muc.h"
#include "profanity.h" #include "profanity.h"
#include "ui/ui.h"
#include "config/preferences.h" #include "config/preferences.h"
#include "server_events.h" #include "event/server_events.h"
#include "xmpp/capabilities.h" #include "xmpp/capabilities.h"
#include "xmpp/connection.h" #include "xmpp/connection.h"
#include "xmpp/stanza.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) #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, typedef struct p_room_info_data_t {
xmpp_stanza_t * const stanza, void * const userdata); char *room;
static int _ping_get_handler(xmpp_conn_t * const conn, gboolean display;
xmpp_stanza_t * const stanza, void * const userdata); } ProfRoomInfoData;
static int _version_get_handler(xmpp_conn_t * const conn,
xmpp_stanza_t * const stanza, void * const userdata); static int _error_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, static int _ping_get_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata);
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_response_handler(xmpp_conn_t * const conn, static int _disco_info_get_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata);
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, static int _room_info_response_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata);
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, static int _disco_items_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata);
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 _disco_items_get_handler(xmpp_conn_t * const conn, static int _destroy_room_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata);
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 _destroy_room_result_handler(xmpp_conn_t * const conn, static int _room_config_submit_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata);
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_config_handler(xmpp_conn_t * const conn, static int _room_affiliation_set_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata);
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_config_submit_handler(xmpp_conn_t * const conn, static int _room_role_list_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata);
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 _room_affiliation_list_result_handler(xmpp_conn_t * const conn, static int _enable_carbons_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata);
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 _room_affiliation_set_result_handler(xmpp_conn_t * const conn, static int _manual_pong_handler(xmpp_conn_t *const conn, xmpp_stanza_t * const stanza, void * const userdata);
xmpp_stanza_t * const stanza, void * const userdata); static int _ping_timed_handler(xmpp_conn_t * const conn, void * const userdata);
static int _room_role_set_result_handler(xmpp_conn_t * const conn, static int _caps_response_handler(xmpp_conn_t *const conn, xmpp_stanza_t * const stanza, void * const userdata);
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 _room_role_list_result_handler(xmpp_conn_t * const conn, static int _caps_response_handler_legacy(xmpp_conn_t *const conn, xmpp_stanza_t * const stanza, void * const userdata);
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);
void void
iq_add_handlers(void) iq_add_handlers(void)
@ -152,6 +140,34 @@ iq_room_list_request(gchar *conferencejid)
xmpp_stanza_release(iq); 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 void
iq_disco_info_request(gchar *jid) iq_disco_info_request(gchar *jid)
{ {
@ -169,14 +185,18 @@ iq_disco_info_request(gchar *jid)
} }
void 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_conn_t * const conn = connection_get_conn();
xmpp_ctx_t * const ctx = connection_get_ctx(); xmpp_ctx_t * const ctx = connection_get_ctx();
char *id = create_unique_id("room_disco_info"); char *id = create_unique_id("room_disco_info");
xmpp_stanza_t *iq = stanza_create_disco_info_iq(ctx, id, room, NULL); 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); 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); const char *id = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_ID);
char *error_msg = stanza_get_error_message(stanza); 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_debug("IQ error handler fired, id: %s, error: %s", id, error_msg);
log_error("IQ error received, id: %s, error: %s", id, error_msg); log_error("IQ error received, id: %s, error: %s", id, error_msg);
} else { } 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 *id = xmpp_stanza_get_id(stanza);
char *type = xmpp_stanza_get_type(stanza); char *type = xmpp_stanza_get_type(stanza);
if (id != NULL) { if (id) {
log_debug("IQ pong handler fired, id: %s.", id); log_debug("IQ pong handler fired, id: %s.", id);
} else { } else {
log_debug("IQ pong handler fired."); log_debug("IQ pong handler fired.");
} }
if (id != NULL && type != NULL) { if (id && type) {
// show warning if error // show warning if error
if (strcmp(type, STANZA_TYPE_ERROR) == 0) { if (strcmp(type, STANZA_TYPE_ERROR) == 0) {
char *error_msg = stanza_get_error_message(stanza); 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' // turn off autoping if error type is 'cancel'
xmpp_stanza_t *error = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_ERROR); 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); char *errtype = xmpp_stanza_get_type(error);
if (errtype != NULL) { if (errtype) {
if (strcmp(errtype, "cancel") == 0) { if (strcmp(errtype, "cancel") == 0) {
log_warning("Server ping (id=%s) error type 'cancel', disabling autoping.", id); 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); 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, _caps_response_handler_for_jid(xmpp_conn_t *const conn, xmpp_stanza_t * const stanza,
void * const userdata) void * const userdata)
{ {
char *jid = (char *)userdata;
const char *id = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_ID); 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); xmpp_stanza_t *query = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_QUERY);
char *type = xmpp_stanza_get_type(stanza); char *type = xmpp_stanza_get_type(stanza);
// ignore non result // ignore non result
if ((g_strcmp0(type, "get") == 0) || (g_strcmp0(type, "set") == 0)) { if ((g_strcmp0(type, "get") == 0) || (g_strcmp0(type, "set") == 0)) {
free(jid);
return 1; 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); const char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
if (!from) { if (!from) {
log_info("No from attribute"); log_info("No from attribute");
free(jid);
return 0; 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); char *error_message = stanza_get_error_message(stanza);
log_warning("Error received for capabilities response from %s: ", from, error_message); log_warning("Error received for capabilities response from %s: ", from, error_message);
free(error_message); free(error_message);
free(jid);
return 0; return 0;
} }
if (query == NULL) { if (query == NULL) {
log_warning("No query element found."); log_warning("No query element found.");
free(jid);
return 0; return 0;
} }
char *node = xmpp_stanza_get_attribute(query, STANZA_ATTR_NODE); char *node = xmpp_stanza_get_attribute(query, STANZA_ATTR_NODE);
if (node == NULL) { if (node == NULL) {
log_warning("No node attribute found"); log_warning("No node attribute found");
free(jid);
return 0; return 0;
} }
char *jid = (char *)userdata;
log_info("Associating capabilities with: %s", jid); log_info("Associating capabilities with: %s", jid);
Capabilities *capabilities = caps_create(query); Capabilities *capabilities = caps_create(query);
caps_add_by_jid(jid, capabilities); caps_add_by_jid(jid, capabilities);
free(jid);
return 0; 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); 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); 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); char *type = xmpp_stanza_get_type(stanza);
// ignore non result // ignore non result
if ((g_strcmp0(type, "get") == 0) || (g_strcmp0(type, "set") == 0)) { if ((g_strcmp0(type, "get") == 0) || (g_strcmp0(type, "set") == 0)) {
free(expected_node);
return 1; 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); const char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
if (!from) { if (!from) {
log_info("No from attribute"); log_info("No from attribute");
free(expected_node);
return 0; 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); char *error_message = stanza_get_error_message(stanza);
log_warning("Error received for capabilities response from %s: ", from, error_message); log_warning("Error received for capabilities response from %s: ", from, error_message);
free(error_message); free(error_message);
free(expected_node);
return 0; return 0;
} }
if (query == NULL) { if (query == NULL) {
log_warning("No query element found."); log_warning("No query element found.");
free(expected_node);
return 0; return 0;
} }
char *node = xmpp_stanza_get_attribute(query, STANZA_ATTR_NODE); char *node = xmpp_stanza_get_attribute(query, STANZA_ATTR_NODE);
if (node == NULL) { if (node == NULL) {
log_warning("No node attribute found"); log_warning("No node attribute found");
free(expected_node);
return 0; return 0;
} }
char *expected_node = (char *)userdata;
// nodes match // nodes match
if (g_strcmp0(expected_node, node) == 0) { if (g_strcmp0(expected_node, node) == 0) {
log_info("Legacy capabilities, nodes match %s", node); 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; 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 static int
_manual_pong_handler(xmpp_conn_t *const conn, xmpp_stanza_t * const stanza, _manual_pong_handler(xmpp_conn_t *const conn, xmpp_stanza_t * const stanza,
void * const userdata) void * const userdata)
@ -714,7 +776,12 @@ _manual_pong_handler(xmpp_conn_t *const conn, xmpp_stanza_t * const stanza,
// handle error responses // handle error responses
if (g_strcmp0(type, STANZA_TYPE_ERROR) == 0) { if (g_strcmp0(type, STANZA_TYPE_ERROR) == 0) {
char *error_message = stanza_get_error_message(stanza); 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); free(error_message);
g_date_time_unref(sent); g_date_time_unref(sent);
return 0; 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(sent);
g_date_time_unref(now); 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; 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); char *id = xmpp_stanza_get_id(stanza);
if (id != NULL) { if (id) {
log_debug("IQ version result handler fired, id: %s.", id); log_debug("IQ version result handler fired, id: %s.", id);
} else { } else {
log_debug("IQ version result handler fired."); 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 *version = xmpp_stanza_get_child_by_name(query, "version");
xmpp_stanza_t *os = xmpp_stanza_get_child_by_name(query, "os"); xmpp_stanza_t *os = xmpp_stanza_get_child_by_name(query, "os");
if (name != NULL) { if (name) {
name_str = xmpp_stanza_get_text(name); name_str = xmpp_stanza_get_text(name);
} }
if (version != NULL) { if (version) {
version_str = xmpp_stanza_get_text(version); version_str = xmpp_stanza_get_text(version);
} }
if (os != NULL) { if (os) {
os_str = xmpp_stanza_get_text(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); 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); 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 *to = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_TO);
const char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM); 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); log_debug("IQ ping get handler fired, id: %s.", id);
} else { } else {
log_debug("IQ ping get handler fired."); 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_FROM, to);
xmpp_stanza_set_attribute(pong, STANZA_ATTR_TYPE, STANZA_TYPE_RESULT); 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); 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 *id = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_ID);
const char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM); 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); log_debug("IQ version get handler fired, id: %s.", id);
} else { } else {
log_debug("IQ version get handler fired."); log_debug("IQ version get handler fired.");
} }
if (from != NULL) { if (from) {
xmpp_stanza_t *response = xmpp_stanza_new(ctx); xmpp_stanza_t *response = xmpp_stanza_new(ctx);
xmpp_stanza_set_name(response, STANZA_NAME_IQ); xmpp_stanza_set_name(response, STANZA_NAME_IQ);
if (id != NULL) { if (id) {
xmpp_stanza_set_id(response, id); xmpp_stanza_set_id(response, id);
} }
xmpp_stanza_set_attribute(response, STANZA_ATTR_TO, from); 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 *id = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_ID);
const char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM); 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); log_debug("IQ disco items get handler fired, id: %s.", id);
} else { } else {
log_debug("IQ disco items get handler fired."); log_debug("IQ disco items get handler fired.");
} }
if (from != NULL) { if (from) {
xmpp_stanza_t *response = xmpp_stanza_new(ctx); xmpp_stanza_t *response = xmpp_stanza_new(ctx);
xmpp_stanza_set_name(response, STANZA_NAME_IQ); xmpp_stanza_set_name(response, STANZA_NAME_IQ);
xmpp_stanza_set_id(response, xmpp_stanza_get_id(stanza)); 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); 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); log_debug("IQ disco info get handler fired, id: %s.", id);
} else { } else {
log_debug("IQ disco info get handler fired."); log_debug("IQ disco info get handler fired.");
} }
if (from != NULL) { if (from) {
xmpp_stanza_t *response = xmpp_stanza_new(ctx); xmpp_stanza_t *response = xmpp_stanza_new(ctx);
xmpp_stanza_set_name(response, STANZA_NAME_IQ); xmpp_stanza_set_name(response, STANZA_NAME_IQ);
xmpp_stanza_set_id(response, xmpp_stanza_get_id(stanza)); xmpp_stanza_set_id(response, xmpp_stanza_get_id(stanza));
xmpp_stanza_set_attribute(response, STANZA_ATTR_TO, from); xmpp_stanza_set_attribute(response, STANZA_ATTR_TO, from);
xmpp_stanza_set_type(response, STANZA_TYPE_RESULT); xmpp_stanza_set_type(response, STANZA_TYPE_RESULT);
xmpp_stanza_t *query = caps_create_query_response_stanza(ctx); 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_set_attribute(query, STANZA_ATTR_NODE, node_str);
} }
xmpp_stanza_add_child(response, query); 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); 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); log_debug("IQ destroy room result handler fired, id: %s.", id);
} else { } else {
log_debug("IQ destroy room result handler fired."); 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) { if (from == NULL) {
log_error("No from attribute for IQ destroy room result"); log_error("No from attribute for IQ destroy room result");
} else { } else {
handle_room_destroy(from); sv_ev_room_destroy(from);
} }
return 0; 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 *type = xmpp_stanza_get_type(stanza);
const char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM); 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); log_debug("IQ room config handler fired, id: %s.", id);
} else { } else {
log_debug("IQ room config handler fired."); 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 // handle error responses
if (g_strcmp0(type, STANZA_TYPE_ERROR) == 0) { if (g_strcmp0(type, STANZA_TYPE_ERROR) == 0) {
char *error_message = stanza_get_error_message(stanza); 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); free(error_message);
return 0; return 0;
} }
if (from == NULL) { if (from == NULL) {
log_warning("No from attribute for IQ config request result"); 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; return 0;
} }
xmpp_stanza_t *query = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_QUERY); xmpp_stanza_t *query = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_QUERY);
if (query == NULL) { if (query == NULL) {
log_warning("No query element found parsing room config response"); 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; return 0;
} }
xmpp_stanza_t *x = xmpp_stanza_get_child_by_ns(query, STANZA_NS_DATA); xmpp_stanza_t *x = xmpp_stanza_get_child_by_ns(query, STANZA_NS_DATA);
if (x == NULL) { if (x == NULL) {
log_warning("No x element found with %s namespace parsing room config response", STANZA_NS_DATA); 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; return 0;
} }
char *form_type = xmpp_stanza_get_attribute(x, STANZA_ATTR_TYPE); char *form_type = xmpp_stanza_get_attribute(x, STANZA_ATTR_TYPE);
if (g_strcmp0(form_type, "form") != 0) { if (g_strcmp0(form_type, "form") != 0) {
log_warning("x element not of type 'form' parsing room config response"); 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; return 0;
} }
DataForm *form = form_create(x); DataForm *form = form_create(x);
handle_room_configure(from, form); ui_handle_room_configuration(from, form);
return 0; 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); const char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
struct privilege_set_t *affiliation_set = (struct privilege_set_t *)userdata; 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); log_debug("IQ affiliation set handler fired, id: %s.", id);
} else { } else {
log_debug("IQ affiliation set handler fired."); 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 // handle error responses
if (g_strcmp0(type, STANZA_TYPE_ERROR) == 0) { if (g_strcmp0(type, STANZA_TYPE_ERROR) == 0) {
char *error_message = stanza_get_error_message(stanza); 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); 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); const char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
struct privilege_set_t *role_set = (struct privilege_set_t *)userdata; 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); log_debug("IQ role set handler fired, id: %s.", id);
} else { } else {
log_debug("IQ role set handler fired."); 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 // handle error responses
if (g_strcmp0(type, STANZA_TYPE_ERROR) == 0) { if (g_strcmp0(type, STANZA_TYPE_ERROR) == 0) {
char *error_message = stanza_get_error_message(stanza); 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); 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); const char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
char *affiliation = (char *)userdata; char *affiliation = (char *)userdata;
if (id != NULL) { if (id) {
log_debug("IQ affiliation list result handler fired, id: %s.", id); log_debug("IQ affiliation list result handler fired, id: %s.", id);
} else { } else {
log_debug("IQ affiliation list result handler fired."); 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 // handle error responses
if (g_strcmp0(type, STANZA_TYPE_ERROR) == 0) { if (g_strcmp0(type, STANZA_TYPE_ERROR) == 0) {
char *error_message = stanza_get_error_message(stanza); 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(error_message);
free(affiliation); free(affiliation);
return 0; 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); free(affiliation);
g_slist_free(jids); 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); const char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
char *role = (char *)userdata; char *role = (char *)userdata;
if (id != NULL) { if (id) {
log_debug("IQ role list result handler fired, id: %s.", id); log_debug("IQ role list result handler fired, id: %s.", id);
} else { } else {
log_debug("IQ role list result handler fired."); 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 // handle error responses
if (g_strcmp0(type, STANZA_TYPE_ERROR) == 0) { if (g_strcmp0(type, STANZA_TYPE_ERROR) == 0) {
char *error_message = stanza_get_error_message(stanza); 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(error_message);
free(role); free(role);
return 0; 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); free(role);
g_slist_free(nicks); 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 *type = xmpp_stanza_get_type(stanza);
const char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM); 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); log_debug("IQ room config submit handler fired, id: %s.", id);
} else { } else {
log_debug("IQ room config submit handler fired."); 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 // handle error responses
if (g_strcmp0(type, STANZA_TYPE_ERROR) == 0) { if (g_strcmp0(type, STANZA_TYPE_ERROR) == 0) {
char *error_message = stanza_get_error_message(stanza); 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); free(error_message);
return 0; return 0;
} }
handle_room_config_submit_result(from); ui_handle_room_config_submit_result(from);
return 0; 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); const char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
char *nick = (char *)userdata; char *nick = (char *)userdata;
if (id != NULL) { if (id) {
log_debug("IQ kick result handler fired, id: %s.", id); log_debug("IQ kick result handler fired, id: %s.", id);
} else { } else {
log_debug("IQ kick result handler fired."); 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 // handle error responses
if (g_strcmp0(type, STANZA_TYPE_ERROR) == 0) { if (g_strcmp0(type, STANZA_TYPE_ERROR) == 0) {
char *error_message = stanza_get_error_message(stanza); 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(error_message);
free(nick); free(nick);
return 0; return 0;
@ -1269,7 +1345,7 @@ _room_kick_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza
static void static void
_identity_destroy(DiscoIdentity *identity) _identity_destroy(DiscoIdentity *identity)
{ {
if (identity != NULL) { if (identity) {
free(identity->name); free(identity->name);
free(identity->type); free(identity->type);
free(identity->category); free(identity->category);
@ -1280,7 +1356,7 @@ _identity_destroy(DiscoIdentity *identity)
static void static void
_item_destroy(DiscoItem *item) _item_destroy(DiscoItem *item)
{ {
if (item != NULL) { if (item) {
free(item->jid); free(item->jid);
free(item->name); free(item->name);
free(item); free(item);
@ -1288,48 +1364,36 @@ _item_destroy(DiscoItem *item)
} }
static int 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) void * const userdata)
{ {
const char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
const char *type = xmpp_stanza_get_type(stanza); const char *type = xmpp_stanza_get_type(stanza);
ProfRoomInfoData *cb_data = (ProfRoomInfoData *)userdata;
char *room = NULL; log_info("Received diso#info response for room: %s", cb_data->room);
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");
}
}
// handle error responses // handle error responses
if (g_strcmp0(type, STANZA_TYPE_ERROR) == 0) { if (g_strcmp0(type, STANZA_TYPE_ERROR) == 0) {
char *error_message = stanza_get_error_message(stanza); if (cb_data->display) {
if (room) { char *error_message = stanza_get_error_message(stanza);
handle_room_info_error(room, error_message); ui_handle_room_info_error(cb_data->room, error_message);
} else { free(error_message);
handle_disco_info_error(from, error_message);
} }
free(error_message); free(cb_data->room);
free(cb_data);
return 0; return 0;
} }
xmpp_stanza_t *query = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_QUERY); 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); xmpp_stanza_t *child = xmpp_stanza_get_children(query);
GSList *identities = NULL; GSList *identities = NULL;
GSList *features = NULL; GSList *features = NULL;
while (child != NULL) { while (child) {
const char *stanza_name = xmpp_stanza_get_name(child); const char *stanza_name = xmpp_stanza_get_name(child);
if (g_strcmp0(stanza_name, STANZA_NAME_FEATURE) == 0) { if (g_strcmp0(stanza_name, STANZA_NAME_FEATURE) == 0) {
const char *var = xmpp_stanza_get_attribute(child, STANZA_ATTR_VAR); const char *var = xmpp_stanza_get_attribute(child, STANZA_ATTR_VAR);
if (var != NULL) { if (var) {
features = g_slist_append(features, strdup(var)); features = g_slist_append(features, strdup(var));
} }
} else if (g_strcmp0(stanza_name, STANZA_NAME_IDENTITY) == 0) { } 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 *type = xmpp_stanza_get_attribute(child, STANZA_ATTR_TYPE);
const char *category = xmpp_stanza_get_attribute(child, STANZA_ATTR_CATEGORY); 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)); DiscoIdentity *identity = malloc(sizeof(struct disco_identity_t));
if (name != NULL) { if (name) {
identity->name = strdup(name); identity->name = strdup(name);
} else { } else {
identity->name = NULL; identity->name = NULL;
} }
if (category != NULL) { if (category) {
identity->category = strdup(category); identity->category = strdup(category);
} else { } else {
identity->category = NULL; identity->category = NULL;
} }
if (type != NULL) { if (type) {
identity->type = strdup(type); identity->type = strdup(type);
} else { } else {
identity->type = NULL; 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); child = xmpp_stanza_get_next(child);
} }
if (room) { muc_set_features(cb_data->room, features);
handle_room_disco_info(room, identities, features); if (cb_data->display) {
} else { ui_show_room_disco_info(cb_data->room, identities, features);
handle_disco_info(from, identities, features);
} }
g_slist_free_full(features, free); g_slist_free_full(features, free);
g_slist_free_full(identities, (GDestroyNotify)_identity_destroy); 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 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); log_debug("Response to query: %s", id);
xmpp_stanza_t *query = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_QUERY); 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); xmpp_stanza_t *child = xmpp_stanza_get_children(query);
while (child != NULL) { while (child) {
const char *stanza_name = xmpp_stanza_get_name(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); 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)); DiscoItem *item = malloc(sizeof(struct disco_item_t));
item->jid = strdup(item_jid); item->jid = strdup(item_jid);
const char *item_name = xmpp_stanza_get_attribute(child, STANZA_ATTR_NAME); const char *item_name = xmpp_stanza_get_attribute(child, STANZA_ATTR_NAME);
if (item_name != NULL) { if (item_name) {
item->name = strdup(item_name); item->name = strdup(item_name);
} else { } else {
item->name = NULL; 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) { if (g_strcmp0(id, "confreq") == 0) {
handle_room_list(items, from); cons_show_room_list(items, from);
} else if (g_strcmp0(id, "discoitemsreq") == 0) { } 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); g_slist_free_full(items, (GDestroyNotify)_item_destroy);

View File

@ -1,7 +1,7 @@
/* /*
* iq.h * 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. * This file is part of Profanity.
* *

View File

@ -1,7 +1,7 @@
/* /*
* message.c * 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. * This file is part of Profanity.
* *
@ -42,7 +42,8 @@
#include "log.h" #include "log.h"
#include "muc.h" #include "muc.h"
#include "profanity.h" #include "profanity.h"
#include "server_events.h" #include "ui/ui.h"
#include "event/server_events.h"
#include "xmpp/connection.h" #include "xmpp/connection.h"
#include "xmpp/message.h" #include "xmpp/message.h"
#include "xmpp/roster.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) #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, static int _groupchat_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata);
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 _chat_handler(xmpp_conn_t * const conn, static int _muc_user_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata);
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 _muc_user_handler(xmpp_conn_t * const conn, static int _captcha_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata);
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 _conference_handler(xmpp_conn_t * const conn, static int _receipt_received_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata);
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);
void void
message_add_handlers(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_MUC_USER, NULL, _muc_user_handler);
HANDLE(STANZA_NS_CONFERENCE, NULL, _conference_handler); HANDLE(STANZA_NS_CONFERENCE, NULL, _conference_handler);
HANDLE(STANZA_NS_CAPTCHA, NULL, _captcha_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) message_send_chat(const char * const barejid, const char * const msg)
{ {
xmpp_stanza_t *message;
xmpp_conn_t * const conn = connection_get_conn(); xmpp_conn_t * const conn = connection_get_conn();
xmpp_ctx_t * const ctx = connection_get_ctx(); xmpp_ctx_t * const ctx = connection_get_ctx();
ChatSession *session = chat_session_get(barejid); ChatSession *session = chat_session_get(barejid);
char *state = NULL;
char *jid = NULL;
if (session) { if (session) {
char *state = NULL;
if (prefs_get_boolean(PREF_STATES) && session->send_states) { if (prefs_get_boolean(PREF_STATES) && session->send_states) {
state = STANZA_NAME_ACTIVE; state = STANZA_NAME_ACTIVE;
} }
Jid *jidp = jid_create_from_bare_and_resource(session->barejid, session->resource); 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); jid_destroy(jidp);
} else { } else {
char *state = NULL;
if (prefs_get_boolean(PREF_STATES)) { if (prefs_get_boolean(PREF_STATES)) {
state = STANZA_NAME_ACTIVE; 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_send(conn, message);
xmpp_stanza_release(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 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_conn_t * const conn = connection_get_conn();
xmpp_ctx_t * const ctx = connection_get_ctx(); 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_send(conn, message);
xmpp_stanza_release(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_conn_t * const conn = connection_get_conn();
xmpp_ctx_t * const ctx = connection_get_ctx(); 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_send(conn, message);
xmpp_stanza_release(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_conn_t * const conn = connection_get_conn();
xmpp_ctx_t * const ctx = connection_get_ctx(); 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_send(conn, stanza);
xmpp_stanza_release(stanza); xmpp_stanza_release(stanza);
@ -196,14 +262,13 @@ message_send_gone(const char * const jid)
} }
static int static int
_message_error_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, _message_error_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata)
void * const userdata)
{ {
char *id = xmpp_stanza_get_id(stanza); char *id = xmpp_stanza_get_id(stanza);
char *jid = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM); 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); xmpp_stanza_t *error_stanza = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_ERROR);
char *type = NULL; char *type = NULL;
if (error_stanza != NULL) { if (error_stanza) {
type = xmpp_stanza_get_attribute(error_stanza, STANZA_ATTR_TYPE); 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); char *err_msg = stanza_get_error_message(stanza);
GString *log_msg = g_string_new("message stanza error received"); 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=");
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, " from=");
g_string_append(log_msg, jid); g_string_append(log_msg, jid);
} }
if (type != NULL) { if (type) {
g_string_append(log_msg, " type="); g_string_append(log_msg, " 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); 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); free(err_msg);
@ -238,113 +312,120 @@ _message_error_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
} }
static int static int
_muc_user_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, _muc_user_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata)
void * const userdata)
{ {
xmpp_ctx_t *ctx = connection_get_ctx(); xmpp_ctx_t *ctx = connection_get_ctx();
xmpp_stanza_t *xns_muc_user = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_MUC_USER); 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); char *room = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
if (room == NULL) { if (!room) {
log_warning("Message received with no from attribute, ignoring"); log_warning("Message received with no from attribute, ignoring");
return 1; return 1;
} }
// XEP-0045 // XEP-0045
xmpp_stanza_t *invite = xmpp_stanza_get_child_by_name(xns_muc_user, STANZA_NAME_INVITE); xmpp_stanza_t *invite = xmpp_stanza_get_child_by_name(xns_muc_user, STANZA_NAME_INVITE);
if (invite != NULL) { if (!invite) {
char *invitor_jid = xmpp_stanza_get_attribute(invite, STANZA_ATTR_FROM); return 1;
if (invitor_jid == NULL) { }
log_warning("Chat room invite received with no from attribute");
return 1;
}
Jid *jidp = jid_create(invitor_jid); char *invitor_jid = xmpp_stanza_get_attribute(invite, STANZA_ATTR_FROM);
if (jidp == NULL) { if (!invitor_jid) {
return 1; log_warning("Chat room invite received with no from attribute");
} return 1;
char *invitor = jidp->barejid; }
char *reason = NULL; Jid *jidp = jid_create(invitor_jid);
xmpp_stanza_t *reason_st = xmpp_stanza_get_child_by_name(invite, STANZA_NAME_REASON); if (!jidp) {
if (reason_st != NULL) { return 1;
reason = xmpp_stanza_get_text(reason_st); }
} char *invitor = jidp->barejid;
handle_room_invite(INVITE_MEDIATED, invitor, room, reason); char *reason = NULL;
jid_destroy(jidp); xmpp_stanza_t *reason_st = xmpp_stanza_get_child_by_name(invite, STANZA_NAME_REASON);
if (reason != NULL) { if (reason_st) {
xmpp_free(ctx, reason); 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; return 1;
} }
static int static int
_conference_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, _conference_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata)
void * const userdata)
{ {
xmpp_stanza_t *xns_conference = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_CONFERENCE); 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"); log_warning("Message received with no from attribute, ignoring");
return 1; return 1;
} }
// XEP-0429
room = xmpp_stanza_get_attribute(xns_conference, STANZA_ATTR_JID);
if (room == NULL) {
return 1;
}
Jid *jidp = jid_create(from); Jid *jidp = jid_create(from);
if (jidp == NULL) { if (!jidp) {
return 1; 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); jid_destroy(jidp);
return 1; return 1;
} }
static int static int
_captcha_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, _captcha_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata)
void * const userdata)
{ {
xmpp_ctx_t *ctx = connection_get_ctx(); xmpp_ctx_t *ctx = connection_get_ctx();
char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM); char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
if (from == NULL) { if (!from) {
log_warning("Message received with no from attribute, ignoring"); log_warning("Message received with no from attribute, ignoring");
return 1; return 1;
} }
// XEP-0158 // XEP-0158
xmpp_stanza_t *body = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_BODY); xmpp_stanza_t *body = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_BODY);
if (body != NULL) { if (!body) {
char *message = xmpp_stanza_get_text(body); return 1;
if (message != NULL) {
handle_room_broadcast(from, message);
xmpp_free(ctx, message);
}
} }
char *message = xmpp_stanza_get_text(body);
if (!message) {
return 1;
}
sv_ev_room_broadcast(from, message);
xmpp_free(ctx, message);
return 1; return 1;
} }
static int static int
_groupchat_handler(xmpp_conn_t * const conn, _groupchat_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata)
xmpp_stanza_t * const stanza, void * const userdata)
{ {
xmpp_ctx_t *ctx = connection_get_ctx(); xmpp_ctx_t *ctx = connection_get_ctx();
char *message = NULL; char *message = NULL;
@ -353,9 +434,9 @@ _groupchat_handler(xmpp_conn_t * const conn,
// handle room subject // handle room subject
xmpp_stanza_t *subject = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_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); 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); xmpp_free(ctx, message);
jid_destroy(jid); jid_destroy(jid);
@ -363,16 +444,22 @@ _groupchat_handler(xmpp_conn_t * const conn,
} }
// handle room broadcasts // handle room broadcasts
if (jid->resourcepart == NULL) { if (!jid->resourcepart) {
xmpp_stanza_t *body = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_BODY); xmpp_stanza_t *body = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_BODY);
if (body != NULL) { if (!body) {
message = xmpp_stanza_get_text(body); jid_destroy(jid);
if (message != NULL) { return 1;
handle_room_broadcast(room_jid, message);
xmpp_free(ctx, message);
}
} }
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); jid_destroy(jid);
return 1; return 1;
} }
@ -390,32 +477,191 @@ _groupchat_handler(xmpp_conn_t * const conn,
return 1; 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); xmpp_stanza_t *body = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_BODY);
// check for and deal with message // check for and deal with message
if (body != NULL) { if (!body) {
message = xmpp_stanza_get_text(body); jid_destroy(jid);
if (message != NULL) { return 1;
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);
}
} }
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); jid_destroy(jid);
return 1; 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 static int
_chat_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, _receipt_received_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata)
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 // ignore if type not chat or absent
char *type = xmpp_stanza_get_type(stanza); 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; return 1;
} }
// check if carbon message
gboolean res = _handle_carbons(stanza);
if (res) {
return 1;
}
// ignore handled namespaces // ignore handled namespaces
xmpp_stanza_t *conf = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_CONFERENCE); 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); 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; return 1;
} }
xmpp_ctx_t *ctx = connection_get_ctx();
gchar *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM); gchar *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
Jid *jid = jid_create(from); Jid *jid = jid_create(from);
// private message from chat room use full jid (room/nick) // private message from chat room use full jid (room/nick)
if (muc_active(jid->barejid)) { if (muc_active(jid->barejid)) {
// determine if the notifications happened whilst offline _private_chat_handler(stanza, jid->fulljid);
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);
return 1; 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 * 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. * This file is part of Profanity.
* *

View File

@ -1,7 +1,7 @@
/* /*
* presence.c * 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. * This file is part of Profanity.
* *
@ -44,7 +44,8 @@
#include "log.h" #include "log.h"
#include "muc.h" #include "muc.h"
#include "profanity.h" #include "profanity.h"
#include "server_events.h" #include "ui/ui.h"
#include "event/server_events.h"
#include "xmpp/capabilities.h" #include "xmpp/capabilities.h"
#include "xmpp/connection.h" #include "xmpp/connection.h"
#include "xmpp/stanza.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_p = autocomplete_create_list(sub_requests_ac);
GSList *requests = requests_p; GSList *requests = requests_p;
while (requests != NULL) { while (requests) {
if (strcmp(requests->data, bare_jid) == 0) { if (strcmp(requests->data, bare_jid) == 0) {
result = TRUE; result = TRUE;
break; break;
@ -178,7 +179,7 @@ presence_sub_request_exists(const char * const bare_jid)
requests = g_slist_next(requests); requests = g_slist_next(requests);
} }
if (requests_p != NULL) { if (requests_p) {
g_slist_free_full(requests_p, free); g_slist_free_full(requests_p, free);
} }
@ -192,27 +193,22 @@ presence_reset_sub_request_search(void)
} }
void void
presence_update(const resource_presence_t presence_type, const char * const msg, presence_send(const resource_presence_t presence_type, const char * const msg, const int idle)
const int idle)
{ {
if (jabber_get_connection_status() != JABBER_CONNECTED) { if (jabber_get_connection_status() != JABBER_CONNECTED) {
log_warning("Error setting presence, not connected."); log_warning("Error setting presence, not connected.");
return; return;
} }
if (msg != NULL) { if (msg) {
log_debug("Updating presence: %s, \"%s\"", log_debug("Updating presence: %s, \"%s\"", string_from_resource_presence(presence_type), msg);
string_from_resource_presence(presence_type), msg);
} else { } else {
log_debug("Updating presence: %s", log_debug("Updating presence: %s", string_from_resource_presence(presence_type));
string_from_resource_presence(presence_type));
} }
xmpp_ctx_t * const ctx = connection_get_ctx(); xmpp_ctx_t * const ctx = connection_get_ctx();
xmpp_conn_t * const conn = connection_get_conn(); xmpp_conn_t * const conn = connection_get_conn();
const int pri = const int pri = accounts_get_priority_for_presence_type(jabber_get_account_name(), presence_type);
accounts_get_priority_for_presence_type(jabber_get_account_name(),
presence_type);
const char *show = stanza_get_presence_string_from_type(presence_type); const char *show = stanza_get_presence_string_from_type(presence_type);
connection_set_presence_message(msg); 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_p = muc_rooms();
GList *rooms = rooms_p; GList *rooms = rooms_p;
while (rooms != NULL) { while (rooms) {
const char *room = rooms->data; const char *room = rooms->data;
const char *nick = muc_nick(room); const char *nick = muc_nick(room);
if (nick != NULL) { if (nick) {
char *full_room_jid = create_fulljid(room, nick); char *full_room_jid = create_fulljid(room, nick);
xmpp_stanza_set_attribute(presence, STANZA_ATTR_TO, full_room_jid); 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); rooms = g_list_next(rooms);
} }
if (rooms_p != NULL) { if (rooms_p) {
g_list_free(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(); xmpp_conn_t *conn = connection_get_conn();
char *nick = muc_nick(room_jid); char *nick = muc_nick(room_jid);
if (nick != NULL) { if (nick) {
xmpp_stanza_t *presence = stanza_create_room_leave_presence(ctx, room_jid, xmpp_stanza_t *presence = stanza_create_room_leave_presence(ctx, room_jid,
nick); nick);
xmpp_send(conn, presence); 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 *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); xmpp_stanza_t *x = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_X);
char *xmlns = NULL; char *xmlns = NULL;
if (x != NULL) { if (x) {
xmlns = xmpp_stanza_get_ns(x); xmlns = xmpp_stanza_get_ns(x);
} }
char *type = NULL; char *type = NULL;
if (error_stanza != NULL) { if (error_stanza) {
type = xmpp_stanza_get_attribute(error_stanza, STANZA_ATTR_TYPE); 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; char *error_cond = NULL;
xmpp_stanza_t *reason_st = xmpp_stanza_get_child_by_ns(error_stanza, STANZA_NS_STANZAS); 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); error_cond = xmpp_stanza_get_name(reason_st);
} }
if (error_cond == NULL) { 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); 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); jid_destroy(fulljid);
return 1; 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); char *err_msg = stanza_get_error_message(stanza);
GString *log_msg = g_string_new("presence stanza error received"); 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=");
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=");
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=");
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); 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); free(err_msg);
@ -416,7 +419,7 @@ _unsubscribed_handler(xmpp_conn_t * const conn,
Jid *from_jid = jid_create(from); Jid *from_jid = jid_create(from);
log_debug("Unsubscribed presence handler fired for %s", 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); autocomplete_remove(sub_requests_ac, from_jid->barejid);
jid_destroy(from_jid); jid_destroy(from_jid);
@ -432,7 +435,7 @@ _subscribed_handler(xmpp_conn_t * const conn,
Jid *from_jid = jid_create(from); Jid *from_jid = jid_create(from);
log_debug("Subscribed presence handler fired for %s", 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); autocomplete_remove(sub_requests_ac, from_jid->barejid);
jid_destroy(from_jid); jid_destroy(from_jid);
@ -452,7 +455,7 @@ _subscribe_handler(xmpp_conn_t * const conn,
return 1; 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); autocomplete_add(sub_requests_ac, from_jid->barejid);
jid_destroy(from_jid); jid_destroy(from_jid);
@ -464,6 +467,8 @@ static int
_unavailable_handler(xmpp_conn_t * const conn, _unavailable_handler(xmpp_conn_t * const conn,
xmpp_stanza_t * const stanza, void * const userdata) xmpp_stanza_t * const stanza, void * const userdata)
{ {
ui_input_nonblocking(TRUE);
const char *jid = xmpp_conn_get_jid(conn); const char *jid = xmpp_conn_get_jid(conn);
char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM); char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
log_debug("Unavailable presence handler fired for %s", 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); char *status_str = stanza_get_status(stanza, NULL);
if (strcmp(my_jid->barejid, from_jid->barejid) !=0) { if (strcmp(my_jid->barejid, from_jid->barejid) !=0) {
if (from_jid->resourcepart != NULL) { if (from_jid->resourcepart) {
handle_contact_offline(from_jid->barejid, from_jid->resourcepart, status_str); sv_ev_contact_offline(from_jid->barejid, from_jid->resourcepart, status_str);
// hack for servers that do not send full jid with unavailable presence // hack for servers that do not send full jid with unavailable presence
} else { } else {
handle_contact_offline(from_jid->barejid, "__prof_default", status_str); sv_ev_contact_offline(from_jid->barejid, "__prof_default", status_str);
} }
} else { } else {
if (from_jid->resourcepart != NULL) { if (from_jid->resourcepart) {
connection_remove_available_resource(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) { } else if (caps->hash) {
log_info("Hash %s not supported: %s, sending service discovery request", caps->hash, jid); log_info("Hash %s not supported: %s, sending service discovery request", caps->hash, jid);
char *id = create_unique_id("caps"); char *id = create_unique_id("caps");
@ -539,6 +544,8 @@ static int
_available_handler(xmpp_conn_t * const conn, _available_handler(xmpp_conn_t * const conn,
xmpp_stanza_t * const stanza, void * const userdata) xmpp_stanza_t * const stanza, void * const userdata)
{ {
ui_input_nonblocking(TRUE);
// handler still fires if error // handler still fires if error
if (g_strcmp0(xmpp_stanza_get_type(stanza), STANZA_TYPE_ERROR) == 0) { if (g_strcmp0(xmpp_stanza_get_type(stanza), STANZA_TYPE_ERROR) == 0) {
return 1; return 1;
@ -596,7 +603,7 @@ _available_handler(xmpp_conn_t * const conn,
if (g_strcmp0(xmpp_presence->jid->barejid, my_jid->barejid) == 0) { if (g_strcmp0(xmpp_presence->jid->barejid, my_jid->barejid) == 0) {
connection_add_available_resource(resource); connection_add_available_resource(resource);
} else { } 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); 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_ctx_t *ctx = connection_get_ctx();
xmpp_conn_t *conn = connection_get_conn(); xmpp_conn_t *conn = connection_get_conn();
if (node != NULL) { if (node) {
log_debug("Node string: %s.", node); log_debug("Node string: %s.", node);
if (!caps_contains(caps_key)) { if (!caps_contains(caps_key)) {
log_debug("Capabilities not cached for '%s', sending discovery IQ.", from); 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 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)
{ {
ui_input_nonblocking(TRUE);
char *type = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_TYPE); char *type = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_TYPE);
char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM); 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 *new_jid = stanza_get_muc_destroy_alternative_room(stanza);
char *password = stanza_get_muc_destroy_alternative_password(stanza); char *password = stanza_get_muc_destroy_alternative_password(stanza);
char *reason = stanza_get_muc_destroy_reason(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(password);
free(reason); free(reason);
// kicked from room // 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 *actor = stanza_get_actor(stanza);
char *reason = stanza_get_reason(stanza); char *reason = stanza_get_reason(stanza);
handle_room_kicked(room, actor, reason); sv_ev_room_kicked(room, actor, reason);
free(reason); free(reason);
// banned from room // 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 *actor = stanza_get_actor(stanza);
char *reason = stanza_get_reason(stanza); char *reason = stanza_get_reason(stanza);
handle_room_banned(room, actor, reason); sv_ev_room_banned(room, actor, reason);
free(reason); free(reason);
// normal exit // normal exit
} else { } else {
handle_leave_room(room); sv_ev_leave_room(room);
} }
g_slist_free_full(status_codes, free); 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); gboolean config_required = stanza_muc_requires_config(stanza);
char *actor = stanza_get_actor(stanza); char *actor = stanza_get_actor(stanza);
char *reason = stanza_get_reason(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 // 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); GSList *status_codes = stanza_get_status_codes_by_ns(stanza, STANZA_NS_MUC_USER);
// kicked from room // 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 *actor = stanza_get_actor(stanza);
char *reason = stanza_get_reason(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); free(reason);
// banned from room // 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 *actor = stanza_get_actor(stanza);
char *reason = stanza_get_reason(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); free(reason);
// normal exit // normal exit
} else { } 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); 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 *actor = stanza_get_actor(stanza);
char *reason = stanza_get_reason(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 * 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. * This file is part of Profanity.
* *

View File

@ -1,7 +1,7 @@
/* /*
* roster.c * 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. * This file is part of Profanity.
* *
@ -41,7 +41,9 @@
#include "log.h" #include "log.h"
#include "profanity.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 "tools/autocomplete.h"
#include "xmpp/connection.h" #include "xmpp/connection.h"
#include "xmpp/roster.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 *groups = p_contact_groups(contact);
GSList *new_groups = NULL; GSList *new_groups = NULL;
while (groups != NULL) { while (groups) {
new_groups = g_slist_append(new_groups, strdup(groups->data)); new_groups = g_slist_append(new_groups, strdup(groups->data));
groups = g_slist_next(groups); 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); char *unique_id = create_unique_id(NULL);
GroupData *data = malloc(sizeof(GroupData)); GroupData *data = malloc(sizeof(GroupData));
data->group = strdup(group); data->group = strdup(group);
if (p_contact_name(contact) != NULL) { if (p_contact_name(contact)) {
data->name = strdup(p_contact_name(contact)); data->name = strdup(p_contact_name(contact));
} else { } else {
data->name = strdup(p_contact_barejid(contact)); 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, _group_add_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
void * const userdata) void * const userdata)
{ {
if (userdata != NULL) { if (userdata) {
GroupData *data = userdata; GroupData *data = userdata;
handle_group_add(data->name, data->group); ui_group_added(data->name, data->group);
free(data->name); free(data->name);
free(data->group); free(data->group);
free(userdata); free(userdata);
@ -176,7 +178,7 @@ roster_send_remove_from_group(const char * const group, PContact contact)
{ {
GSList *groups = p_contact_groups(contact); GSList *groups = p_contact_groups(contact);
GSList *new_groups = NULL; GSList *new_groups = NULL;
while (groups != NULL) { while (groups) {
if (strcmp(groups->data, group) != 0) { if (strcmp(groups->data, group) != 0) {
new_groups = g_slist_append(new_groups, strdup(groups->data)); 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); char *unique_id = create_unique_id(NULL);
GroupData *data = malloc(sizeof(GroupData)); GroupData *data = malloc(sizeof(GroupData));
data->group = strdup(group); data->group = strdup(group);
if (p_contact_name(contact) != NULL) { if (p_contact_name(contact)) {
data->name = strdup(p_contact_name(contact)); data->name = strdup(p_contact_name(contact));
} else { } else {
data->name = strdup(p_contact_barejid(contact)); 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, _group_remove_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
void * const userdata) void * const userdata)
{ {
if (userdata != NULL) { if (userdata) {
GroupData *data = userdata; GroupData *data = userdata;
handle_group_remove(data->name, data->group); ui_group_removed(data->name, data->group);
free(data->name); free(data->name);
free(data->group); free(data->group);
free(userdata); 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 // if from attribute exists and it is not current users barejid, ignore push
Jid *my_jid = jid_create(jabber_get_fulljid()); Jid *my_jid = jid_create(jabber_get_fulljid());
const char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM); 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); jid_destroy(my_jid);
return 1; return 1;
} }
jid_destroy(my_jid); jid_destroy(my_jid);
const char *barejid = xmpp_stanza_get_attribute(item, STANZA_ATTR_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 *name = xmpp_stanza_get_attribute(item, STANZA_ATTR_NAME);
const char *sub = xmpp_stanza_get_attribute(item, STANZA_ATTR_SUBSCRIPTION); const char *sub = xmpp_stanza_get_attribute(item, STANZA_ATTR_SUBSCRIPTION);
const char *ask = xmpp_stanza_get_attribute(item, STANZA_ATTR_ASK); 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) { if (g_strcmp0(sub, "remove") == 0) {
// remove barejid and name // remove barejid and name
if (name == NULL) { if (name == NULL) {
name = barejid; name = barejid_lower;
} }
roster_remove(name, barejid_lower);
roster_remove(name, barejid); ui_roster_remove(barejid_lower);
handle_roster_remove(barejid);
// otherwise update local roster // otherwise update local roster
} else { } else {
// check for pending out subscriptions // check for pending out subscriptions
gboolean pending_out = FALSE; gboolean pending_out = FALSE;
if ((ask != NULL) && (strcmp(ask, "subscribe") == 0)) { if (ask && (strcmp(ask, "subscribe") == 0)) {
pending_out = TRUE; pending_out = TRUE;
} }
GSList *groups = _get_groups_from_item(item); GSList *groups = _get_groups_from_item(item);
// update the local roster // update the local roster
PContact contact = roster_get_contact(barejid); PContact contact = roster_get_contact(barejid_lower);
if (contact == NULL) { 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) { if (added) {
handle_roster_add(barejid, name); ui_roster_add(barejid_lower, name);
} }
} else { } 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; return 1;
} }
static int static int
_roster_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, _roster_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata)
void * const userdata)
{ {
const char *id = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_ID); const char *id = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_ID);
if (g_strcmp0(id, "roster") != 0) {
return 1;
}
// handle initial roster response // 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 *query = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_QUERY); xmpp_stanza_t *item = xmpp_stanza_get_children(query);
xmpp_stanza_t *item = xmpp_stanza_get_children(query);
while (item != NULL) { while (item) {
const char *barejid = xmpp_stanza_get_attribute(item, STANZA_ATTR_JID); const char *barejid = xmpp_stanza_get_attribute(item, STANZA_ATTR_JID);
const char *name = xmpp_stanza_get_attribute(item, STANZA_ATTR_NAME); gchar *barejid_lower = g_utf8_strdown(barejid, -1);
const char *sub = xmpp_stanza_get_attribute(item, STANZA_ATTR_SUBSCRIPTION); 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 // do not set nickname to empty string, set to NULL instead
if (name && (strlen(name) == 0)) { if (name && (strlen(name) == 0)) name = NULL;
name = NULL;
}
gboolean pending_out = FALSE; gboolean pending_out = FALSE;
const char *ask = xmpp_stanza_get_attribute(item, STANZA_ATTR_ASK); const char *ask = xmpp_stanza_get_attribute(item, STANZA_ATTR_ASK);
if (g_strcmp0(ask, "subscribe") == 0) { if (g_strcmp0(ask, "subscribe") == 0) {
pending_out = TRUE; 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);
} }
handle_roster_received(); GSList *groups = _get_groups_from_item(item);
resource_presence_t conn_presence = accounts_get_login_presence(jabber_get_account_name()); gboolean added = roster_add(barejid_lower, name, groups, sub, pending_out);
presence_update(conn_presence, NULL, 0); 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; return 1;
} }
@ -340,10 +343,10 @@ _get_groups_from_item(xmpp_stanza_t *item)
GSList *groups = NULL; GSList *groups = NULL;
xmpp_stanza_t *group_element = xmpp_stanza_get_children(item); 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) { if (strcmp(xmpp_stanza_get_name(group_element), STANZA_NAME_GROUP) == 0) {
char *groupname = xmpp_stanza_get_text(group_element); char *groupname = xmpp_stanza_get_text(group_element);
if (groupname != NULL) { if (groupname) {
groups = g_slist_append(groups, groupname); groups = g_slist_append(groups, groupname);
} }
} }

View File

@ -1,7 +1,7 @@
/* /*
* roster.h * 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. * This file is part of Profanity.
* *

View File

@ -1,7 +1,7 @@
/* /*
* stanza.c * 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. * 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"); 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_t *nick_st = xmpp_stanza_new(ctx);
xmpp_stanza_set_name(nick_st, STANZA_NAME_NICK); xmpp_stanza_set_name(nick_st, STANZA_NAME_NICK);
xmpp_stanza_set_text(nick_st, 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 #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 * xmpp_stanza_t *
stanza_create_chat_state(xmpp_ctx_t *ctx, const char * const fulljid, const char * const state) 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 * xmpp_stanza_t *
stanza_create_message(xmpp_ctx_t *ctx, const char * const recipient, stanza_attach_state(xmpp_ctx_t *ctx, xmpp_stanza_t *stanza, const char * const state)
const char * const type, const char * const message, {
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; 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_name(msg, STANZA_NAME_MESSAGE);
xmpp_stanza_set_type(msg, type); xmpp_stanza_set_type(msg, type);
xmpp_stanza_set_attribute(msg, STANZA_ATTR_TO, recipient); xmpp_stanza_set_attribute(msg, STANZA_ATTR_TO, recipient);
char *id = create_unique_id(NULL);
xmpp_stanza_set_id(msg, id); xmpp_stanza_set_id(msg, id);
free(id);
body = xmpp_stanza_new(ctx); body = xmpp_stanza_new(ctx);
xmpp_stanza_set_name(body, STANZA_NAME_BODY); 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_add_child(msg, body);
xmpp_stanza_release(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; 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_t *iq = xmpp_stanza_new(ctx);
xmpp_stanza_set_name(iq, STANZA_NAME_IQ); xmpp_stanza_set_name(iq, STANZA_NAME_IQ);
xmpp_stanza_set_type(iq, STANZA_TYPE_SET); xmpp_stanza_set_type(iq, STANZA_TYPE_SET);
if (id != NULL) { if (id) {
xmpp_stanza_set_id(iq, 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_name(item, STANZA_NAME_ITEM);
xmpp_stanza_set_attribute(item, STANZA_ATTR_JID, jid); xmpp_stanza_set_attribute(item, STANZA_ATTR_JID, jid);
if (handle != NULL) { if (handle) {
xmpp_stanza_set_attribute(item, STANZA_ATTR_NAME, handle); xmpp_stanza_set_attribute(item, STANZA_ATTR_NAME, handle);
} else { } else {
xmpp_stanza_set_attribute(item, STANZA_ATTR_NAME, ""); xmpp_stanza_set_attribute(item, STANZA_ATTR_NAME, "");
} }
while (groups != NULL) { while (groups) {
xmpp_stanza_t *group = xmpp_stanza_new(ctx); xmpp_stanza_t *group = xmpp_stanza_new(ctx);
xmpp_stanza_t *groupname = xmpp_stanza_new(ctx); xmpp_stanza_t *groupname = xmpp_stanza_new(ctx);
xmpp_stanza_set_name(group, STANZA_NAME_GROUP); 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 * xmpp_stanza_t *
stanza_create_invite(xmpp_ctx_t *ctx, const char * const room, 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; 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_ns(x, STANZA_NS_CONFERENCE);
xmpp_stanza_set_attribute(x, STANZA_ATTR_JID, room); xmpp_stanza_set_attribute(x, STANZA_ATTR_JID, room);
if (reason != NULL) { if (reason) {
xmpp_stanza_set_attribute(x, STANZA_ATTR_REASON, 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_add_child(message, x);
xmpp_stanza_release(x); xmpp_stanza_release(x);
@ -377,6 +443,46 @@ stanza_create_invite(xmpp_ctx_t *ctx, const char * const room,
return message; 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 * xmpp_stanza_t *
stanza_create_room_join_presence(xmpp_ctx_t * const ctx, stanza_create_room_join_presence(xmpp_ctx_t * const ctx,
const char * const full_room_jid, const char * const passwd) 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); xmpp_stanza_set_ns(x, STANZA_NS_MUC);
// if a password was given // if a password was given
if (passwd != NULL) { if (passwd) {
xmpp_stanza_t *pass = xmpp_stanza_new(ctx); xmpp_stanza_t *pass = xmpp_stanza_new(ctx);
xmpp_stanza_set_name(pass, "password"); xmpp_stanza_set_name(pass, "password");
xmpp_stanza_t *text = xmpp_stanza_new(ctx); 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_t *query = xmpp_stanza_new(ctx);
xmpp_stanza_set_name(query, STANZA_NAME_QUERY); xmpp_stanza_set_name(query, STANZA_NAME_QUERY);
xmpp_stanza_set_ns(query, XMPP_NS_DISCO_INFO); xmpp_stanza_set_ns(query, XMPP_NS_DISCO_INFO);
if (node != NULL) { if (node) {
xmpp_stanza_set_attribute(query, STANZA_ATTR_NODE, 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_t *iq = xmpp_stanza_new(ctx);
xmpp_stanza_set_name(iq, STANZA_NAME_IQ); xmpp_stanza_set_name(iq, STANZA_NAME_IQ);
xmpp_stanza_set_type(iq, STANZA_TYPE_GET); xmpp_stanza_set_type(iq, STANZA_TYPE_GET);
if (target != NULL) { if (target) {
xmpp_stanza_set_attribute(iq, STANZA_ATTR_TO, target); xmpp_stanza_set_attribute(iq, STANZA_ATTR_TO, target);
} }
char *id = create_unique_id("ping"); 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 // first check for XEP-0203 delayed delivery
xmpp_stanza_t *delay = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_DELAY); 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); 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); 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; 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 // otherwise check for XEP-0091 legacy delayed delivery
// stanp format : CCYYMMDDThh:mm:ss // stanp format : CCYYMMDDThh:mm:ss
xmpp_stanza_t *x = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_X); 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); 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); 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; return TRUE;
} }
} }
@ -914,17 +1020,17 @@ stanza_get_status(xmpp_stanza_t *stanza, char *def)
xmpp_stanza_t *status = xmpp_stanza_t *status =
xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_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 // xmpp_free and free may be different functions so convert all to
// libc malloc // libc malloc
char *s1, *s2 = NULL; char *s1, *s2 = NULL;
s1 = xmpp_stanza_get_text(status); s1 = xmpp_stanza_get_text(status);
if (s1 != NULL) { if (s1) {
s2 = strdup(s1); s2 = strdup(s1);
xmpp_free(ctx, s1); xmpp_free(ctx, s1);
} }
return s2; return s2;
} else if (def != NULL) { } else if (def) {
return strdup(def); return strdup(def);
} else { } else {
return NULL; return NULL;
@ -938,17 +1044,17 @@ stanza_get_show(xmpp_stanza_t *stanza, char *def)
xmpp_stanza_t *show = xmpp_stanza_t *show =
xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_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 // xmpp_free and free may be different functions so convert all to
// libc malloc // libc malloc
char *s1, *s2 = NULL; char *s1, *s2 = NULL;
s1 = xmpp_stanza_get_text(show); s1 = xmpp_stanza_get_text(show);
if (s1 != NULL) { if (s1) {
s2 = strdup(s1); s2 = strdup(s1);
xmpp_free(ctx, s1); xmpp_free(ctx, s1);
} }
return s2; return s2;
} else if (def != NULL) { } else if (def) {
return strdup(def); return strdup(def);
} else { } else {
return NULL; return NULL;
@ -984,7 +1090,7 @@ stanza_muc_requires_config(xmpp_stanza_t * const stanza)
// muc user namespaced x element // muc user namespaced x element
xmpp_stanza_t *x = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_MUC_USER); 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 // check for item element with owner affiliation
xmpp_stanza_t *item = xmpp_stanza_get_child_by_name(x, "item"); 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 // check for status code 201
xmpp_stanza_t *x_children = xmpp_stanza_get_children(x); 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) { if (g_strcmp0(xmpp_stanza_get_name(x_children), STANZA_NAME_STATUS) == 0) {
char *code = xmpp_stanza_get_attribute(x_children, STANZA_ATTR_CODE); char *code = xmpp_stanza_get_attribute(x_children, STANZA_ATTR_CODE);
if (g_strcmp0(code, "201") == 0) { 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 // muc user namespaced x element
xmpp_stanza_t *x = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_MUC_USER); 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 // check for status child element with 303 code
xmpp_stanza_t *x_children = xmpp_stanza_get_children(x); 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) { if (g_strcmp0(xmpp_stanza_get_name(x_children), STANZA_NAME_STATUS) == 0) {
char *code = xmpp_stanza_get_attribute(x_children, STANZA_ATTR_CODE); char *code = xmpp_stanza_get_attribute(x_children, STANZA_ATTR_CODE);
if (g_strcmp0(code, "303") == 0) { 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 = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_X);
xmpp_stanza_t *x_children = xmpp_stanza_get_children(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) { if (strcmp(xmpp_stanza_get_name(x_children), STANZA_NAME_ITEM) == 0) {
char *nick = xmpp_stanza_get_attribute(x_children, STANZA_ATTR_NICK); char *nick = xmpp_stanza_get_attribute(x_children, STANZA_ATTR_NICK);
if (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); xmpp_stanza_t *text_stanza = xmpp_stanza_get_child_by_name(error_stanza, STANZA_NAME_TEXT);
// check for text // check for text
if (text_stanza != NULL) { if (text_stanza) {
gchar *err_msg = xmpp_stanza_get_text(text_stanza); gchar *err_msg = xmpp_stanza_get_text(text_stanza);
if (err_msg != NULL) { if (err_msg) {
char *result = strdup(err_msg); char *result = strdup(err_msg);
xmpp_free(ctx, err_msg); xmpp_free(ctx, err_msg);
return result; return result;
@ -1419,7 +1525,7 @@ stanza_get_error_message(xmpp_stanza_t *stanza)
int i; int i;
for (i = 0; i < ARRAY_SIZE(defined_conditions); 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]); 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)); char *result = strdup(xmpp_stanza_get_name(cond_stanza));
return result; return result;
} }
@ -1456,7 +1562,7 @@ void
stanza_attach_show(xmpp_ctx_t * const ctx, xmpp_stanza_t * const presence, stanza_attach_show(xmpp_ctx_t * const ctx, xmpp_stanza_t * const presence,
const char * const show) const char * const show)
{ {
if (show != NULL) { if (show) {
xmpp_stanza_t *show_stanza = xmpp_stanza_new(ctx); xmpp_stanza_t *show_stanza = xmpp_stanza_new(ctx);
xmpp_stanza_set_name(show_stanza, STANZA_NAME_SHOW); xmpp_stanza_set_name(show_stanza, STANZA_NAME_SHOW);
xmpp_stanza_t *text = xmpp_stanza_new(ctx); 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, stanza_attach_status(xmpp_ctx_t * const ctx, xmpp_stanza_t * const presence,
const char * const status) const char * const status)
{ {
if (status != NULL) { if (status) {
xmpp_stanza_t *status_stanza = xmpp_stanza_new(ctx); xmpp_stanza_t *status_stanza = xmpp_stanza_new(ctx);
xmpp_stanza_set_name(status_stanza, STANZA_NAME_STATUS); xmpp_stanza_set_name(status_stanza, STANZA_NAME_STATUS);
xmpp_stanza_t *text = xmpp_stanza_new(ctx); xmpp_stanza_t *text = xmpp_stanza_new(ctx);
@ -1619,9 +1725,9 @@ stanza_parse_presence(xmpp_stanza_t *stanza, int *err)
result->priority = 0; result->priority = 0;
xmpp_stanza_t *priority_stanza = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_PRIORITY); 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); char *priority_str = xmpp_stanza_get_text(priority_stanza);
if (priority_str != NULL) { if (priority_str) {
result->priority = atoi(priority_str); result->priority = atoi(priority_str);
} }
free(priority_str); free(priority_str);

View File

@ -1,7 +1,7 @@
/* /*
* stanza.h * 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. * This file is part of Profanity.
* *
@ -77,6 +77,8 @@
#define STANZA_NAME_VALUE "value" #define STANZA_NAME_VALUE "value"
#define STANZA_NAME_DESTROY "destroy" #define STANZA_NAME_DESTROY "destroy"
#define STANZA_NAME_ACTOR "actor" #define STANZA_NAME_ACTOR "actor"
#define STANZA_NAME_ENABLE "enable"
#define STANZA_NAME_DISABLE "disable"
// error conditions // error conditions
#define STANZA_NAME_BAD_REQUEST "bad-request" #define STANZA_NAME_BAD_REQUEST "bad-request"
@ -133,6 +135,7 @@
#define STANZA_ATTR_CATEGORY "category" #define STANZA_ATTR_CATEGORY "category"
#define STANZA_ATTR_REASON "reason" #define STANZA_ATTR_REASON "reason"
#define STANZA_ATTR_AUTOJOIN "autojoin" #define STANZA_ATTR_AUTOJOIN "autojoin"
#define STANZA_ATTR_PASSWORD "password"
#define STANZA_TEXT_AWAY "away" #define STANZA_TEXT_AWAY "away"
#define STANZA_TEXT_DND "dnd" #define STANZA_TEXT_DND "dnd"
@ -154,6 +157,9 @@
#define STANZA_NS_CONFERENCE "jabber:x:conference" #define STANZA_NS_CONFERENCE "jabber:x:conference"
#define STANZA_NS_CAPTCHA "urn:xmpp:captcha" #define STANZA_NS_CAPTCHA "urn:xmpp:captcha"
#define STANZA_NS_PUBSUB "http://jabber.org/protocol/pubsub" #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" #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_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, xmpp_stanza_t* stanza_create_chat_state(xmpp_ctx_t *ctx,
const char * const fulljid, const char * const state); const char * const fulljid, const char * const state);
xmpp_stanza_t* stanza_create_message(xmpp_ctx_t *ctx, xmpp_stanza_t * stanza_attach_state(xmpp_ctx_t *ctx, xmpp_stanza_t *stanza, const char * const state);
const char * const recipient, const char * const type, xmpp_stanza_t * stanza_attach_carbons_private(xmpp_ctx_t *ctx, xmpp_stanza_t *stanza);
const char * const message, const char * const state); 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, xmpp_stanza_t* stanza_create_room_join_presence(xmpp_ctx_t * const ctx,
const char * const full_room_jid, const char * const passwd); 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); const char * const to, const char * const node);
xmpp_stanza_t* stanza_create_invite(xmpp_ctx_t *ctx, const char * const room, 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); const char * const contact, const char * const reason);
gboolean stanza_contains_chat_state(xmpp_stanza_t *stanza); gboolean stanza_contains_chat_state(xmpp_stanza_t *stanza);

View File

@ -1,7 +1,7 @@
/* /*
* xmpp.h * 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. * This file is part of Profanity.
* *
@ -145,7 +145,8 @@ char* jabber_get_account_name(void);
GList * jabber_get_available_resources(void); GList * jabber_get_available_resources(void);
// message functions // 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_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(const char * const roomjid, const char * const msg);
void message_send_groupchat_subject(const char * const roomjid, const char * const subject); 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_join_room(char *room, char *nick, char * passwd);
void presence_change_room_nick(const char * const room, const char * const nick); 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_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); int idle);
gboolean presence_sub_request_exists(const char * const bare_jid); gboolean presence_sub_request_exists(const char * const bare_jid);
// iq functions // iq functions
void iq_enable_carbons();
void iq_disable_carbons();
void iq_send_software_version(const char * const fulljid); void iq_send_software_version(const char * const fulljid);
void iq_room_list_request(gchar *conferencejid); void iq_room_list_request(gchar *conferencejid);
void iq_disco_info_request(gchar *jid); 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); const char * const node, const char * const ver);
void iq_send_caps_request_legacy(const char * const to, const char * const id, void iq_send_caps_request_legacy(const char * const to, const char * const id,
const char * const node, const char * const ver); 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_list(const char * const room, char *affiliation);
void iq_room_affiliation_set(const char * const room, const char * const jid, char *affiliation, void iq_room_affiliation_set(const char * const room, const char * const jid, char *affiliation,
const char * const reason); const char * const reason);

View File

@ -85,6 +85,24 @@ void close_chat_sessions(void **state)
close_preferences(NULL); 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; static GCompareFunc cmp_func;
void void

View File

@ -6,5 +6,7 @@ void close_preferences(void **state);
void init_chat_sessions(void **state); void init_chat_sessions(void **state);
void close_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); void glist_set_cmp(GCompareFunc func);
int glist_contents_equal(const void *actual, const void *expected); 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