mirror of
https://github.com/irssi/irssi.git
synced 2026-08-23 02:22:36 +02:00
commit
4e74fa7284
83 changed files with 1080 additions and 394 deletions
26
.travis.yml
26
.travis.yml
|
|
@ -1,3 +1,4 @@
|
|||
sudo: false
|
||||
language: perl
|
||||
perl:
|
||||
- "5.20-shrplib"
|
||||
|
|
@ -7,28 +8,19 @@ env:
|
|||
- CC=clang
|
||||
- CC=gcc
|
||||
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- libperl-dev
|
||||
- elinks
|
||||
|
||||
before_install:
|
||||
- sudo apt-get update -qq
|
||||
- perl -V
|
||||
- sudo apt-get build-dep -qq irssi
|
||||
- sudo apt-get install -qq lynx
|
||||
|
||||
install: true
|
||||
|
||||
script:
|
||||
- ./autogen.sh --with-proxy --with-bot --with-perl=module
|
||||
- ./autogen.sh --with-proxy --with-bot --with-perl=module --prefix=$HOME/irssi-build
|
||||
- cat config.log
|
||||
- make
|
||||
- sudo make install
|
||||
|
||||
notifications:
|
||||
irc:
|
||||
channels:
|
||||
- "irc.freenode.net#irssi"
|
||||
template:
|
||||
- "%{repository} (%{commit}: %{author}): %{message}"
|
||||
- "Build details : %{build_url}"
|
||||
on_success: always
|
||||
on_failure: always
|
||||
use_notice: true
|
||||
skip_join: true
|
||||
- make install
|
||||
|
|
|
|||
4
INSTALL
4
INSTALL
|
|
@ -94,6 +94,10 @@ things that can go wrong:
|
|||
- If configure complains that it doesn't find some perl stuff, you're
|
||||
probably missing libperl.so or libperl.a. In debian, you'll need to do
|
||||
apt-get install libperl-dev
|
||||
- For unprivileged home directory installations, using the local::lib CPAN
|
||||
module is recommended. Read its docs, bootstrap it if needed, ensure that
|
||||
the environment variables are set before running the configure script, and
|
||||
append "--with-perl-lib=site" to the configure parameters to use it.
|
||||
|
||||
You can verify that the perl module is loaded and working with "/LOAD"
|
||||
command. It should print something like:
|
||||
|
|
|
|||
2
NEWS
2
NEWS
|
|
@ -1,4 +1,6 @@
|
|||
v0.8.18-head 2014-XX-YY The Irssi team <staff@irssi.org>
|
||||
+ Garbage Collection support has been removed. This will hardly have any
|
||||
effect for anyone given that it has been unsupported for several years.
|
||||
+ Disable SSLv3 due to the POODLE vulnerability.
|
||||
+ Try to split long lines on spaces to avoid words being splitted. Adds
|
||||
a new option: 'split_line_on_space' which defaults to on.
|
||||
|
|
|
|||
|
|
@ -3,9 +3,6 @@
|
|||
#undef HAVE_SOCKS_H
|
||||
#undef HAVE_STATIC_PERL
|
||||
#undef HAVE_GMODULE
|
||||
#undef HAVE_GC_H
|
||||
#undef HAVE_GC_GC_H
|
||||
#undef USE_GC
|
||||
|
||||
/* macros/curses checks */
|
||||
#undef HAS_CURSES
|
||||
|
|
|
|||
36
configure.ac
36
configure.ac
|
|
@ -7,6 +7,8 @@ AC_CONFIG_HEADERS([irssi-config.h])
|
|||
AC_CONFIG_MACRO_DIR([m4])
|
||||
AM_INIT_AUTOMAKE([1.9 no-define foreign])
|
||||
|
||||
AM_SILENT_RULES([yes])
|
||||
|
||||
AM_MAINTAINER_MODE
|
||||
|
||||
AC_PROG_CC
|
||||
|
|
@ -83,15 +85,6 @@ if test "x$prefix" != "xNONE"; then
|
|||
perl_prefix_note=yes
|
||||
fi
|
||||
|
||||
AC_ARG_WITH(gc,
|
||||
[ --with-gc Use garbage collector],
|
||||
if test x$withval = xno; then
|
||||
want_gc=no
|
||||
else
|
||||
want_gc=yes
|
||||
fi,
|
||||
want_gc=no)
|
||||
|
||||
AC_ARG_WITH(perl-staticlib,
|
||||
[ --with-perl-staticlib Specify that we want to link perl libraries
|
||||
statically in irssi, default is no],
|
||||
|
|
@ -270,7 +263,7 @@ for try in 1 2; do
|
|||
echo "*** trying without -lgmodule"
|
||||
glib_modules=
|
||||
fi
|
||||
AM_PATH_GLIB_2_0(2.6.0,,, $glib_modules)
|
||||
AM_PATH_GLIB_2_0(2.16.0,,, $glib_modules)
|
||||
if test "$GLIB_LIBS"; then
|
||||
if test $glib_modules = gmodule; then
|
||||
AC_DEFINE(HAVE_GMODULE)
|
||||
|
|
@ -322,28 +315,6 @@ if test "$enable_ssl" = "yes"; then
|
|||
fi
|
||||
fi
|
||||
|
||||
dnl **
|
||||
dnl ** Garbage Collector
|
||||
dnl **
|
||||
have_gc=no
|
||||
if test "x$want_gc" = xyes; then
|
||||
AC_CHECK_LIB(gc, GC_malloc, [
|
||||
AC_CHECK_HEADER(gc/gc.h, [
|
||||
AC_DEFINE(HAVE_GC_GC_H)
|
||||
AC_DEFINE(USE_GC)
|
||||
LIBS="$LIBS -lgc"
|
||||
have_gc=yes
|
||||
], [
|
||||
AC_CHECK_HEADER(gc.h, [
|
||||
AC_DEFINE(HAVE_GC_H)
|
||||
AC_DEFINE(USE_GC)
|
||||
LIBS="$LIBS -lgc"
|
||||
have_gc=yes
|
||||
])
|
||||
])
|
||||
])
|
||||
fi
|
||||
|
||||
dnl **
|
||||
dnl ** curses checks
|
||||
dnl **
|
||||
|
|
@ -782,7 +753,6 @@ if test "x$have_openssl" = "xno" -a "x$enable_ssl" = "xyes"; then
|
|||
fi
|
||||
fi
|
||||
echo "Building with 64bit DCC support .. : $offt_64bit"
|
||||
echo "Building with garbage collector .. : $have_gc"
|
||||
echo "Building with DANE support ....... : $have_dane"
|
||||
echo "Building with true color support.. : $want_truecolor"
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
docdir = $(datadir)/doc/irssi
|
||||
|
||||
man_MANS = \
|
||||
irssi.1
|
||||
|
||||
|
|
|
|||
14
docs/help/in/irssiproxy.in
Normal file
14
docs/help/in/irssiproxy.in
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
|
||||
@SYNTAX:irssiproxy@
|
||||
|
||||
%9Description:%9
|
||||
|
||||
Displays the list of clients connected to irssiproxy.
|
||||
|
||||
%9Examples:%9
|
||||
|
||||
/IRSSIPROXY
|
||||
/IRSSIPROXY STATUS
|
||||
|
||||
%9See also:%9 LOAD PROXY, SET irssiproxy
|
||||
|
||||
|
|
@ -32,6 +32,12 @@
|
|||
additional commands to the server.
|
||||
-cmdmax: Specifies the maximum number of commands to perform before
|
||||
starting the internal flood protection.
|
||||
-sasl_mechanism Specifies the mechanism to use for the SASL authentication.
|
||||
At the moment irssi only supports the 'plain' and the
|
||||
'external' mechanisms.
|
||||
-sasl_username Specifies the username to use during the SASL authentication.
|
||||
-sasl_password Specifies the password to use during the SASL authentication.
|
||||
|
||||
|
||||
The name of the network to add, edit or remove; if no parameter is given,
|
||||
the list of networks will be displayed.
|
||||
|
|
|
|||
|
|
@ -5,49 +5,49 @@
|
|||
|
||||
%9Parameters:%9
|
||||
|
||||
LOG: Modifies the logging status.
|
||||
LOGFILE: Modifies the location to the log file.
|
||||
NEW: Creates a new window.
|
||||
CLOSE: Closes a window.
|
||||
REFNUM: Go to the window with the given number.
|
||||
GOTO: Go to the window with the given nickname, channel or number.
|
||||
NEXT: Go to the next window.
|
||||
LAST: Go to the last window.
|
||||
PREVIOUS: Go to the previous window.
|
||||
LEVEL: Modifies the text levels to display in the window.
|
||||
IMMORTAL: Modifies the window mortality status.
|
||||
SERVER: Set the active server of the window.
|
||||
ITEM PREV: Go to the previous item in the window.
|
||||
ITEM NEXT: Go to the next item in the window.
|
||||
ITEM GOTO: Go to the specified nickname, channel or window item number.
|
||||
ITEM MOVE: Move the active window item to another window.
|
||||
NUMBER: Move the active window to another position.
|
||||
NAME: Give the window a name.
|
||||
HISTORY: Clears the window history buffer.
|
||||
MOVE PREV: Move the window down.
|
||||
MOVE NEXT: Move the window up.
|
||||
MOVE FIRST: Move the window to the first position.
|
||||
MOVE LAST: Move the window to the last position.
|
||||
MOVE: Move the window.
|
||||
LIST: List all the windows.
|
||||
THEME: Applies a theme to the windows.
|
||||
GROW: Increase the window size when using split windows.
|
||||
SHRINK: Decrease the window size when using split windows.
|
||||
SIZE: Modify the window size when using split windows.
|
||||
BALANCE: Balance the window locations when using split windows.
|
||||
HIDE: Hide the window when using split windows.
|
||||
SHOW: Show the window when using split windows.
|
||||
UP: Go to the window above when using split windows.
|
||||
DOWN: Go to the window below when using split windows.
|
||||
LEFT: Go to the previous window.
|
||||
RIGHT: Go to the next window.
|
||||
STICK: Make the window sticky.
|
||||
MOVE LEFT: Move the window to the previous location.
|
||||
MOVE RIGHT: Move the window to the next location.
|
||||
MOVE UP: Move the window up when using split windows.
|
||||
MOVE DOWN: Move the window down when using split windows.
|
||||
LOG: %|Turn on or off logging of the active window, optionally specifying the log file to use.
|
||||
LOGFILE: %|Sets the location of the log file to use for window logging without starting to log.
|
||||
NEW: %|Creates a new hidden or split window.
|
||||
CLOSE: %|Closes the current window, the specified one or all windows in the given range.
|
||||
REFNUM: %|Go to the window with the given number.
|
||||
GOTO: %|Go to the window with activity, with the given nickname, channel or with the specified number.
|
||||
NEXT: %|Go to the next window numerically.
|
||||
LAST: %|Go to the previously active window.
|
||||
PREVIOUS: %|Go to the previous window numerically.
|
||||
LEVEL: %|Changes the text levels to display in the window, or query the current level.
|
||||
IMMORTAL: %|Modifies or queries the window mortality status. Immortal windows have an extra protection against WINDOW CLOSE.
|
||||
SERVER: %|Change the active server of the window or the server stickyness. If the server is sticky, it cannot be cycled with next_window_item/previous_window_item
|
||||
ITEM PREV: %|Make the previous item in this window active.
|
||||
ITEM NEXT: %|Make the next item in this window active.
|
||||
ITEM GOTO: %|Change to the query with the specified nickname, channel with the given name or window item number.
|
||||
ITEM MOVE: %|Move the active window item to another window, or move the channel or query item specified by their name to the current window.
|
||||
NUMBER: %|Change the active window number to the specified number, swapping the window already in that place if required. With -sticky, protect the window number from renumbering done by windows_auto_renumber. (To re-set the sticky attribute, use WINDOW NUMBER again without -sticky.)
|
||||
NAME: %|Change or clear the window name. Window names must be unique.
|
||||
HISTORY: %|Set or clear a specific named history to use for this window. All windows with the same named history will share a history.
|
||||
MOVE PREV: %|Move the window to the place of the numerically previous window. At the first position, move the window to the end and renumber the consecutive block that it was part of.
|
||||
MOVE NEXT: %|Move the window to the place of the numerically next window. At the last position, move the window to the first position and renumber the consecutive block at first position (if any)
|
||||
MOVE FIRST: %|Move the window to the first position. Any windows inbetween are moved to their numerically next positions.
|
||||
MOVE LAST: %|Move the window to the last position. Any windows inbetween are moved to their numerically previous positions.
|
||||
MOVE: %|Move the window to the specified number or the first number that is in use when moving the window in the direction of the specified position. Any windows inbetween are shifted towards the old position of the window (unused positions remain empty)
|
||||
LIST: %|List all the windows.
|
||||
THEME: %|Applies or removes a per-window theme.
|
||||
GROW: %|Increase the size of the active split window by the specified number of lines.
|
||||
SHRINK: %|Decrease the size of the active split window by the specified number of lines.
|
||||
SIZE: %|Set the current split window size to the specified numer of lines.
|
||||
BALANCE: %|Balance the heights of all split windows.
|
||||
HIDE: %|Hides the current split window, or the split window specified by number or item name.
|
||||
SHOW: %|Show the window specified by number or item name as a new split windows. It is made sticky when autostick_split_windows is turned on.
|
||||
UP: %|Set the split window above the current one active. At the top, wraps to the bottom.
|
||||
DOWN: %|Set the split window below the current one active. At the bottom, wraps to the top.
|
||||
LEFT: %|Go to the previous window numerically that is part of the current sticky group (or not part of any sticky group).
|
||||
RIGHT: %|Go to the next window numerically that is part of the current sticky group (or not part of any sticky group).
|
||||
STICK: %|Make the currently active window sticky, or stick the window specified by number to the currently visible split window. Or turn off stickyness of the currently active window or the window specified by number.
|
||||
MOVE LEFT: %|Move the window to the numerically previous location inside the current sticky group.
|
||||
MOVE RIGHT: %|Move the window to the numerically next location inside the current sticky group.
|
||||
MOVE UP: %|Move the current window to the sticky group of the split window above. If no sticky group remains, the split window collapses.
|
||||
MOVE DOWN: %|Move the current window to the sticky group of the split window below. If no sticky group remains, the split window collapses.
|
||||
|
||||
Add the required arguments for the given command.
|
||||
%|Add the required arguments for the given command. Without arguments, the details (size, immortality, levels, server, name and sticky group) of the currently active window are displayed. If used with a number as argument, same as WINDOW REFNUM.
|
||||
|
||||
%9Description:%9
|
||||
|
||||
|
|
|
|||
|
|
@ -1185,3 +1185,11 @@ Client->{}
|
|||
connected - whether the client is connected and ready
|
||||
want_ctcp - whether the client wants to receive CTCPs
|
||||
ircnet - network tag of the network we proxy
|
||||
|
||||
|
||||
|
||||
|
||||
Bugs and Limitations
|
||||
--------------------
|
||||
* Calling die in 'script error' handler causes segfault (#101)
|
||||
* Storing and later using any Irssi object may result in use-after-free related crash
|
||||
|
|
|
|||
|
|
@ -12,6 +12,11 @@ In irssi, say:
|
|||
|
||||
/LOAD proxy
|
||||
|
||||
If you want the proxy to be loaded automatically at startup, add the
|
||||
load command to ~/.irssi/startup:
|
||||
|
||||
echo "load proxy" >> ~/.irssi/startup
|
||||
|
||||
You really should set some password for the proxy with:
|
||||
|
||||
/SET irssiproxy_password secret
|
||||
|
|
@ -24,3 +29,20 @@ something like:
|
|||
There we have 3 different irc networks answering in 3 ports. Note that
|
||||
you'll have to make the correct /IRCNET ADD and /SERVER ADD commands to
|
||||
make it work properly.
|
||||
|
||||
By default, the proxy binds to all available interfaces. To make it
|
||||
only listen on (for example) the loopback address:
|
||||
|
||||
/SET irssiproxy_bind 127.0.0.1
|
||||
|
||||
Note that bind address changes won't take effect until the proxy is
|
||||
disabled and then reenabled.
|
||||
|
||||
Once everything is set up, you can enable / disable the proxy:
|
||||
|
||||
/TOGGLE irssiproxy
|
||||
|
||||
When the proxy is configured and running, the following command will
|
||||
show all the currently connected clients:
|
||||
|
||||
/IRSSIPROXY status
|
||||
|
|
|
|||
|
|
@ -136,6 +136,10 @@ irc-cap.c
|
|||
"server cap nak "<cmd>, SERVER_REC
|
||||
"server cap end", SERVER_REC
|
||||
|
||||
sasl.c
|
||||
"server sasl failure", SERVER_REC, char *reason
|
||||
"server sasl success", SERVER_REC
|
||||
|
||||
irc.c:
|
||||
|
||||
"server event", SERVER_REC, char *data, char *sender_nick, char *sender_address
|
||||
|
|
@ -225,6 +229,7 @@ notifylist.c:
|
|||
|
||||
proxy/listen.c:
|
||||
|
||||
"proxy client connecting", CLIENT_REC
|
||||
"proxy client connected", CLIENT_REC
|
||||
"proxy client disconnected", CLIENT_REC
|
||||
"proxy client command", CLIENT_REC, char *args, char *data
|
||||
|
|
|
|||
|
|
@ -391,7 +391,7 @@ messages window.</p>
|
|||
the connection into some window. IRSSI DOES NOT. There is no required
|
||||
relationship between window and server. You can connect to 10 servers
|
||||
and manage them all in just one window, or join channel in each one of
|
||||
them to one sigle window if you really want to. That being said, here's
|
||||
them to one single window if you really want to. That being said, here's
|
||||
how you do connect to new server without closing the old connection:</p>
|
||||
|
||||
<pre>
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ if echo "${VERSION}" | grep -q -- -head; then
|
|||
# Because the git tag won't yet include the next release we modify the git
|
||||
# describe output using the version defined from configure.ac.
|
||||
version="${new_version}-$(echo "${git_version}" | sed 's/^.*-[0-9]\+-//')"
|
||||
echo "#undef PACKAGE_VERSION"
|
||||
echo "#define PACKAGE_VERSION \"${version}\""
|
||||
fi
|
||||
fi
|
||||
|
|
|
|||
17
src/common.h
17
src/common.h
|
|
@ -43,23 +43,6 @@
|
|||
# include <gmodule.h>
|
||||
#endif
|
||||
|
||||
#if !GLIB_CHECK_VERSION(2,10,0)
|
||||
#define g_slice_alloc(size) g_malloc(size)
|
||||
#define g_slice_alloc0(size) g_malloc0(size)
|
||||
#define g_slice_free1(size, mem) g_free(mem)
|
||||
#define g_slice_new(type) g_new(type, 1)
|
||||
#define g_slice_new0(type) g_new0(type, 1)
|
||||
#define g_slice_free(type, mem) g_free(mem)
|
||||
#endif
|
||||
|
||||
#if !GLIB_CHECK_VERSION(2,16,0)
|
||||
#define g_strcmp0(a, b) (!a ? -(a != b) : (!b ? (a != b) : strcmp(a, b)))
|
||||
#endif
|
||||
|
||||
#ifdef USE_GC
|
||||
# define g_free(x) G_STMT_START { (x) = NULL; } G_STMT_END
|
||||
#endif
|
||||
|
||||
#if defined (UOFF_T_INT)
|
||||
typedef unsigned int uoff_t;
|
||||
#elif defined (UOFF_T_LONG)
|
||||
|
|
|
|||
|
|
@ -156,11 +156,17 @@ static void sig_init_finished(void)
|
|||
static char *fix_path(const char *str)
|
||||
{
|
||||
char *new_str = convert_home(str);
|
||||
|
||||
if (!g_path_is_absolute(new_str)) {
|
||||
char *tmp_str = new_str;
|
||||
new_str = g_strdup_printf("%s/%s", g_get_current_dir(), tmp_str);
|
||||
char *current_dir = g_get_current_dir();
|
||||
|
||||
new_str = g_build_path(G_DIR_SEPARATOR_S, current_dir, tmp_str, NULL);
|
||||
|
||||
g_free(current_dir);
|
||||
g_free(tmp_str);
|
||||
}
|
||||
|
||||
return new_str;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
#include "log.h"
|
||||
#include "servers.h"
|
||||
#include "settings.h"
|
||||
#include "write-buffer.h"
|
||||
|
||||
static LOG_REC *awaylog;
|
||||
static int away_filepos;
|
||||
|
|
@ -62,6 +63,9 @@ static void awaylog_open(void)
|
|||
return;
|
||||
}
|
||||
|
||||
/* Flush the dirty buffers to disk before acquiring the file position */
|
||||
write_buffer_flush();
|
||||
|
||||
awaylog = log;
|
||||
away_filepos = lseek(log->handle, 0, SEEK_CUR);
|
||||
away_msgs = 0;
|
||||
|
|
@ -83,6 +87,9 @@ static void awaylog_close(void)
|
|||
|
||||
if (awaylog == log) awaylog = NULL;
|
||||
|
||||
/* Flush the dirty buffers to disk before showing the away log */
|
||||
write_buffer_flush();
|
||||
|
||||
signal_emit("awaylog show", 3, log, GINT_TO_POINTER(away_msgs),
|
||||
GINT_TO_POINTER(away_filepos));
|
||||
log_close(log);
|
||||
|
|
|
|||
|
|
@ -215,7 +215,7 @@ void gslist_free_full (GSList *list, GDestroyNotify free_func)
|
|||
{
|
||||
GSList *tmp;
|
||||
|
||||
if (!list)
|
||||
if (list == NULL)
|
||||
return;
|
||||
|
||||
for (tmp = list; tmp != NULL; tmp = tmp->next)
|
||||
|
|
|
|||
|
|
@ -571,6 +571,14 @@ int nick_match_msg(CHANNEL_REC *channel, const char *msg, const char *nick)
|
|||
}
|
||||
}
|
||||
|
||||
int nick_match_msg_everywhere(CHANNEL_REC *channel, const char *msg, const char *nick)
|
||||
{
|
||||
g_return_val_if_fail(nick != NULL, FALSE);
|
||||
g_return_val_if_fail(msg != NULL, FALSE);
|
||||
|
||||
return stristr_full(msg, nick) != NULL;
|
||||
}
|
||||
|
||||
void nicklist_init(void)
|
||||
{
|
||||
signal_add_first("channel created", (SIGNAL_FUNC) sig_channel_created);
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ int nicklist_compare(NICK_REC *p1, NICK_REC *p2, const char *nick_prefix);
|
|||
|
||||
/* Check is `msg' is meant for `nick'. */
|
||||
int nick_match_msg(CHANNEL_REC *channel, const char *msg, const char *nick);
|
||||
int nick_match_msg_everywhere(CHANNEL_REC *channel, const char *msg, const char *nick);
|
||||
|
||||
void nicklist_init(void);
|
||||
void nicklist_deinit(void);
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
static int rawlog_lines;
|
||||
static int signal_rawlog;
|
||||
static int log_file_create_mode;
|
||||
static int log_dir_create_mode;
|
||||
|
||||
RAWLOG_REC *rawlog_create(void)
|
||||
{
|
||||
|
|
@ -145,9 +146,13 @@ void rawlog_close(RAWLOG_REC *rawlog)
|
|||
|
||||
void rawlog_save(RAWLOG_REC *rawlog, const char *fname)
|
||||
{
|
||||
char *path;
|
||||
char *path, *dir;
|
||||
int f;
|
||||
|
||||
dir = g_path_get_dirname(fname);
|
||||
mkpath(dir, log_dir_create_mode);
|
||||
g_free(dir);
|
||||
|
||||
path = convert_home(fname);
|
||||
f = open(path, O_WRONLY | O_APPEND | O_CREAT, log_file_create_mode);
|
||||
g_free(path);
|
||||
|
|
@ -165,6 +170,11 @@ static void read_settings(void)
|
|||
{
|
||||
rawlog_set_size(settings_get_int("rawlog_lines"));
|
||||
log_file_create_mode = octal2dec(settings_get_int("log_create_mode"));
|
||||
log_dir_create_mode = log_file_create_mode;
|
||||
if (log_file_create_mode & 0400) log_dir_create_mode |= 0100;
|
||||
if (log_file_create_mode & 0040) log_dir_create_mode |= 0010;
|
||||
if (log_file_create_mode & 0004) log_dir_create_mode |= 0001;
|
||||
|
||||
}
|
||||
|
||||
static void cmd_rawlog(const char *data, SERVER_REC *server, void *item)
|
||||
|
|
|
|||
|
|
@ -8,6 +8,9 @@ char *address;
|
|||
int port;
|
||||
char *password;
|
||||
|
||||
int sasl_mechanism;
|
||||
char *sasl_password;
|
||||
|
||||
char *ssl_cert;
|
||||
char *ssl_pkey;
|
||||
char *ssl_pass;
|
||||
|
|
|
|||
|
|
@ -420,8 +420,8 @@ static void cmd_reconnect(const char *data, SERVER_REC *server)
|
|||
cmd_param_error(CMDERR_NOT_CONNECTED);
|
||||
rec = reconnects->data;
|
||||
} else {
|
||||
if (g_ascii_strncasecmp(data, "RECON-", 6) == 0)
|
||||
data += 6;
|
||||
if (g_ascii_strncasecmp(tag, "RECON-", 6) == 0)
|
||||
tag += 6;
|
||||
|
||||
tagnum = atoi(tag);
|
||||
rec = tagnum <= 0 ? NULL : reconnect_find_tag(tagnum);
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
(SERVER_CONNECT(conn) ? TRUE : FALSE)
|
||||
|
||||
#define server_ischannel(server, channel) \
|
||||
(server)->ischannel(server, channel)
|
||||
((server)->ischannel(server, channel))
|
||||
|
||||
/* all strings should be either NULL or dynamically allocated */
|
||||
/* address and nick are mandatory, rest are optional */
|
||||
|
|
|
|||
|
|
@ -326,8 +326,11 @@ static void autoconnect_servers(void)
|
|||
|
||||
if (autocon_server != NULL) {
|
||||
/* connect to specified server */
|
||||
str = g_strdup_printf(autocon_password == NULL ? "%s %d" : "%s %d %s",
|
||||
autocon_server, autocon_port, autocon_password);
|
||||
if (autocon_password == NULL)
|
||||
str = g_strdup_printf("%s %d", autocon_server, autocon_port);
|
||||
else
|
||||
str = g_strdup_printf("%s %d %s", autocon_server, autocon_port, autocon_password);
|
||||
|
||||
signal_emit("command connect", 1, str);
|
||||
g_free(str);
|
||||
return;
|
||||
|
|
@ -447,18 +450,7 @@ void fe_common_core_finish_init(void)
|
|||
signal_add_first("setup changed", (SIGNAL_FUNC) sig_setup_changed);
|
||||
|
||||
/* _after_ windows are created.. */
|
||||
#if GLIB_CHECK_VERSION(2,6,0)
|
||||
g_log_set_default_handler((GLogFunc) glog_func, NULL);
|
||||
#else
|
||||
g_log_set_handler(G_LOG_DOMAIN,
|
||||
(GLogLevelFlags) (G_LOG_LEVEL_CRITICAL |
|
||||
G_LOG_LEVEL_WARNING),
|
||||
(GLogFunc) glog_func, NULL);
|
||||
g_log_set_handler("GLib",
|
||||
(GLogLevelFlags) (G_LOG_LEVEL_CRITICAL |
|
||||
G_LOG_LEVEL_WARNING),
|
||||
(GLogFunc) glog_func, NULL); /* send glib errors to the same place */
|
||||
#endif
|
||||
|
||||
if (setup_changed)
|
||||
signal_emit("setup changed", 0);
|
||||
|
|
|
|||
|
|
@ -183,7 +183,9 @@ static void sig_message_public(SERVER_REC *server, const char *msg,
|
|||
nickrec = nicklist_find(chanrec, nick);
|
||||
|
||||
for_me = !settings_get_bool("hilight_nick_matches") ? FALSE :
|
||||
nick_match_msg(chanrec, msg, server->nick);
|
||||
!settings_get_bool("hilight_nick_matches_everywhere") ?
|
||||
nick_match_msg(chanrec, msg, server->nick) :
|
||||
nick_match_msg_everywhere(chanrec, msg, server->nick);
|
||||
hilight = for_me ? NULL :
|
||||
hilight_match_nick(server, target, nick, address, MSGLEVEL_PUBLIC, msg);
|
||||
color = (hilight == NULL) ? NULL : hilight_get_color(hilight);
|
||||
|
|
@ -694,6 +696,7 @@ void fe_messages_init(void)
|
|||
(GCompareFunc) g_direct_equal);
|
||||
|
||||
settings_add_bool("lookandfeel", "hilight_nick_matches", TRUE);
|
||||
settings_add_bool("lookandfeel", "hilight_nick_matches_everywhere", FALSE);
|
||||
settings_add_bool("lookandfeel", "emphasis", TRUE);
|
||||
settings_add_bool("lookandfeel", "emphasis_replace", FALSE);
|
||||
settings_add_bool("lookandfeel", "emphasis_multiword", FALSE);
|
||||
|
|
|
|||
|
|
@ -31,6 +31,8 @@
|
|||
#include "fe-windows.h"
|
||||
#include "printtext.h"
|
||||
|
||||
#define MAX_EXPAND_RECURSION 100
|
||||
|
||||
GSList *keyinfos;
|
||||
static GHashTable *keys, *default_keys;
|
||||
|
||||
|
|
@ -171,7 +173,7 @@ KEYINFO_REC *key_info_find(const char *id)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static int expand_key(const char *key, GSList **out);
|
||||
static int expand_key(const char *key, GSList **out, int *limit);
|
||||
|
||||
#define expand_out_char(out, c) \
|
||||
{ \
|
||||
|
|
@ -188,13 +190,17 @@ static int expand_key(const char *key, GSList **out);
|
|||
g_slist_free(out); out = NULL; \
|
||||
}
|
||||
|
||||
static int expand_combo(const char *start, const char *end, GSList **out)
|
||||
static int expand_combo(const char *start, const char *end, GSList **out, int *limit)
|
||||
{
|
||||
KEY_REC *rec;
|
||||
KEYINFO_REC *info;
|
||||
GSList *tmp, *tmp2, *list, *copy, *newout;
|
||||
char *str, *p;
|
||||
|
||||
if ((*limit)-- < 0) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (start == end) {
|
||||
/* single key */
|
||||
expand_out_char(*out, *start);
|
||||
|
|
@ -229,7 +235,7 @@ static int expand_combo(const char *start, const char *end, GSList **out)
|
|||
/* only one way to generate the combo, good */
|
||||
rec = list->data;
|
||||
g_slist_free(list);
|
||||
return expand_key(rec->key, out);
|
||||
return expand_key(rec->key, out, limit);
|
||||
}
|
||||
|
||||
/* multiple ways to generate the combo -
|
||||
|
|
@ -244,7 +250,11 @@ static int expand_combo(const char *start, const char *end, GSList **out)
|
|||
copy = g_slist_append(copy, g_string_new(str->str));
|
||||
}
|
||||
|
||||
if (!expand_key(rec->key, ©)) {
|
||||
if (!expand_key(rec->key, ©, limit)) {
|
||||
if (*limit < 0) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* illegal key combo, remove from list */
|
||||
expand_out_free(copy);
|
||||
} else {
|
||||
|
|
@ -254,7 +264,11 @@ static int expand_combo(const char *start, const char *end, GSList **out)
|
|||
|
||||
rec = list->data;
|
||||
g_slist_free(list);
|
||||
if (!expand_key(rec->key, out)) {
|
||||
if (!expand_key(rec->key, out, limit)) {
|
||||
if (*limit < 0) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* illegal key combo, remove from list */
|
||||
expand_out_free(*out);
|
||||
}
|
||||
|
|
@ -264,12 +278,16 @@ static int expand_combo(const char *start, const char *end, GSList **out)
|
|||
}
|
||||
|
||||
/* Expand key code - returns TRUE if successful. */
|
||||
static int expand_key(const char *key, GSList **out)
|
||||
static int expand_key(const char *key, GSList **out, int *limit)
|
||||
{
|
||||
GSList *tmp;
|
||||
const char *start;
|
||||
int last_hyphen;
|
||||
|
||||
if ((*limit)-- < 0) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* meta-^W^Gf -> ^[-^W-^G-f */
|
||||
start = NULL; last_hyphen = TRUE;
|
||||
for (; *key != '\0'; key++) {
|
||||
|
|
@ -279,7 +297,7 @@ static int expand_key(const char *key, GSList **out)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (!expand_combo(start, key-1, out))
|
||||
if (!expand_combo(start, key-1, out, limit))
|
||||
return FALSE;
|
||||
expand_out_char(*out, '-');
|
||||
start = NULL;
|
||||
|
|
@ -332,7 +350,7 @@ static int expand_key(const char *key, GSList **out)
|
|||
}
|
||||
|
||||
if (start != NULL)
|
||||
return expand_combo(start, key-1, out);
|
||||
return expand_combo(start, key-1, out, limit);
|
||||
|
||||
for (tmp = *out; tmp != NULL; tmp = tmp->next) {
|
||||
GString *str = tmp->data;
|
||||
|
|
@ -346,12 +364,13 @@ static int expand_key(const char *key, GSList **out)
|
|||
static void key_states_scan_key(const char *key, KEY_REC *rec)
|
||||
{
|
||||
GSList *tmp, *out;
|
||||
int limit = MAX_EXPAND_RECURSION;
|
||||
|
||||
if (g_strcmp0(rec->info->id, "key") == 0)
|
||||
return;
|
||||
|
||||
out = g_slist_append(NULL, g_string_new(NULL));
|
||||
if (expand_key(key, &out)) {
|
||||
if (expand_key(key, &out, &limit)) {
|
||||
for (tmp = out; tmp != NULL; tmp = tmp->next) {
|
||||
GString *str = tmp->data;
|
||||
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ real_sources = \
|
|||
fe-netsplit.c \
|
||||
fe-common-irc.c \
|
||||
fe-whois.c \
|
||||
fe-sasl.c \
|
||||
irc-completion.c \
|
||||
module-formats.c
|
||||
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ static void dcc_request(CHAT_DCC_REC *dcc)
|
|||
if (!IS_DCC_CHAT(dcc)) return;
|
||||
|
||||
printformat(dcc->server, NULL, MSGLEVEL_DCC,
|
||||
ischannel(*dcc->target) ? IRCTXT_DCC_CHAT_CHANNEL :
|
||||
server_ischannel(SERVER(dcc->server), dcc->target) ? IRCTXT_DCC_CHAT_CHANNEL :
|
||||
IRCTXT_DCC_CHAT, dcc->id, dcc->addrstr,
|
||||
dcc->port, dcc->target);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
#include "module.h"
|
||||
#include "signals.h"
|
||||
#include "levels.h"
|
||||
#include "servers.h"
|
||||
|
||||
#include "irc.h"
|
||||
#include "dcc-file.h"
|
||||
|
|
@ -40,7 +41,7 @@ static void dcc_request(GET_DCC_REC *dcc)
|
|||
sizestr = dcc_get_size_str(dcc->size);
|
||||
|
||||
printformat(dcc->server, NULL, MSGLEVEL_DCC,
|
||||
ischannel(*dcc->target) ? IRCTXT_DCC_SEND_CHANNEL :
|
||||
server_ischannel(SERVER(dcc->server), dcc->target) ? IRCTXT_DCC_SEND_CHANNEL :
|
||||
IRCTXT_DCC_SEND, dcc->nick, dcc->addrstr,
|
||||
dcc->port, dcc->arg, sizestr, dcc->target);
|
||||
|
||||
|
|
|
|||
|
|
@ -28,13 +28,11 @@
|
|||
|
||||
#include "themes.h"
|
||||
#include "fe-irc-server.h"
|
||||
#include "fe-irc-channels.h"
|
||||
|
||||
void fe_irc_modules_init(void);
|
||||
void fe_irc_modules_deinit(void);
|
||||
|
||||
void fe_irc_channels_init(void);
|
||||
void fe_irc_channels_deinit(void);
|
||||
|
||||
void fe_irc_queries_init(void);
|
||||
void fe_irc_queries_deinit(void);
|
||||
|
||||
|
|
@ -71,6 +69,9 @@ void fe_netjoin_deinit(void);
|
|||
void fe_whois_init(void);
|
||||
void fe_whois_deinit(void);
|
||||
|
||||
void fe_sasl_init(void);
|
||||
void fe_sasl_deinit(void);
|
||||
|
||||
void irc_completion_init(void);
|
||||
void irc_completion_deinit(void);
|
||||
|
||||
|
|
@ -93,6 +94,7 @@ void fe_common_irc_init(void)
|
|||
fe_netsplit_init();
|
||||
fe_netjoin_init();
|
||||
fe_whois_init();
|
||||
fe_sasl_init();
|
||||
irc_completion_init();
|
||||
|
||||
settings_check();
|
||||
|
|
@ -118,6 +120,7 @@ void fe_common_irc_deinit(void)
|
|||
fe_netsplit_deinit();
|
||||
fe_netjoin_deinit();
|
||||
fe_whois_deinit();
|
||||
fe_sasl_deinit();
|
||||
irc_completion_deinit();
|
||||
|
||||
theme_unregister();
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ static void ctcp_default_msg(IRC_SERVER_REC *server, const char *data,
|
|||
data = p+1;
|
||||
}
|
||||
|
||||
printformat(server, ischannel(*target) ? target : nick, MSGLEVEL_CTCPS,
|
||||
printformat(server, server_ischannel(SERVER(server), target) ? target : nick, MSGLEVEL_CTCPS,
|
||||
IRCTXT_CTCP_REQUESTED_UNKNOWN,
|
||||
nick, addr, cmd, data, target);
|
||||
g_free(cmd);
|
||||
|
|
@ -113,8 +113,8 @@ static void ctcp_default_reply(IRC_SERVER_REC *server, const char *data,
|
|||
ctcpdata = ptr+1;
|
||||
}
|
||||
|
||||
printformat(server, ischannel(*target) ? target : nick, MSGLEVEL_CTCPS,
|
||||
ischannel(*target) ? IRCTXT_CTCP_REPLY_CHANNEL :
|
||||
printformat(server, server_ischannel(SERVER(server), target) ? target : nick, MSGLEVEL_CTCPS,
|
||||
server_ischannel(SERVER(server), target) ? IRCTXT_CTCP_REPLY_CHANNEL :
|
||||
IRCTXT_CTCP_REPLY, ctcp, nick, ctcpdata, target);
|
||||
g_free(ctcp);
|
||||
}
|
||||
|
|
@ -137,7 +137,7 @@ static void ctcp_ping_reply(IRC_SERVER_REC *server, const char *data,
|
|||
|
||||
g_get_current_time(&tv);
|
||||
usecs = get_timeval_diff(&tv, &tv2);
|
||||
printformat(server, ischannel(*target) ? target : nick, MSGLEVEL_CTCPS,
|
||||
printformat(server, server_ischannel(SERVER(server), target) ? target : nick, MSGLEVEL_CTCPS,
|
||||
IRCTXT_CTCP_PING_REPLY, nick, usecs/1000, usecs%1000);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -400,7 +400,7 @@ static void event_target_unavailable(IRC_SERVER_REC *server, const char *data,
|
|||
g_return_if_fail(data != NULL);
|
||||
|
||||
params = event_get_params(data, 2, NULL, &target);
|
||||
if (!ischannel(*target)) {
|
||||
if (!server_ischannel(SERVER(server), target)) {
|
||||
/* nick unavailable */
|
||||
printformat(server, NULL, MSGLEVEL_CRAP,
|
||||
IRCTXT_NICK_UNAVAILABLE, target);
|
||||
|
|
@ -583,7 +583,7 @@ static void print_event_received(IRC_SERVER_REC *server, const char *data,
|
|||
return;
|
||||
ptr++;
|
||||
|
||||
if (ischannel(*data)) /* directed at channel */
|
||||
if (server_ischannel(SERVER(server), data)) /* directed at channel */
|
||||
target = g_strndup(data, (int)(ptr - data - 1));
|
||||
else if (!target_param || *ptr == ':' || (ptr2 = strchr(ptr, ' ')) == NULL)
|
||||
target = NULL;
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@
|
|||
#include "fe-queries.h"
|
||||
#include "fe-windows.h"
|
||||
#include "fe-irc-server.h"
|
||||
#include "fe-irc-channels.h"
|
||||
|
||||
static void event_privmsg(IRC_SERVER_REC *server, const char *data,
|
||||
const char *nick, const char *addr)
|
||||
|
|
@ -52,15 +53,19 @@ static void event_privmsg(IRC_SERVER_REC *server, const char *data,
|
|||
params = event_get_params(data, 2 | PARAM_FLAG_GETREST, &target, &msg);
|
||||
if (nick == NULL) nick = server->real_address;
|
||||
if (addr == NULL) addr = "";
|
||||
if (*target == '@' && ischannel(target[1])) {
|
||||
|
||||
if (fe_channel_is_opchannel(server, target)) {
|
||||
/* Hybrid 6 feature, send msg to all ops in channel */
|
||||
recoded = recode_in(SERVER(server), msg, target+1);
|
||||
const char *cleantarget = fe_channel_skip_prefix(server, target);
|
||||
recoded = recode_in(SERVER(server), msg, cleantarget);
|
||||
|
||||
/* pass the original target to the signal, with the @+ here
|
||||
* the other one is only needed for recode_in*/
|
||||
signal_emit("message irc op_public", 5,
|
||||
server, recoded, nick, addr,
|
||||
get_visible_target(server, target+1));
|
||||
server, recoded, nick, addr, target);
|
||||
} else {
|
||||
recoded = recode_in(SERVER(server), msg, ischannel(*target) ? target : nick);
|
||||
signal_emit(ischannel(*target) ?
|
||||
recoded = recode_in(SERVER(server), msg, server_ischannel(SERVER(server), target) ? target : nick);
|
||||
signal_emit(server_ischannel(SERVER(server), target) ?
|
||||
"message public" : "message private", 5,
|
||||
server, recoded, nick, addr,
|
||||
get_visible_target(server, target));
|
||||
|
|
|
|||
|
|
@ -31,6 +31,51 @@
|
|||
#include "fe-windows.h"
|
||||
#include "window-items.h"
|
||||
|
||||
int fe_channel_is_opchannel(IRC_SERVER_REC *server, const char *target)
|
||||
{
|
||||
const char *statusmsg;
|
||||
|
||||
/* Quick check */
|
||||
if (server == NULL || server->prefix[(int)(unsigned char)*target] == 0)
|
||||
return FALSE;
|
||||
|
||||
statusmsg = g_hash_table_lookup(server->isupport, "statusmsg");
|
||||
if (statusmsg == NULL)
|
||||
statusmsg = "@+";
|
||||
|
||||
return strchr(statusmsg, *target) != NULL;
|
||||
}
|
||||
|
||||
const char *fe_channel_skip_prefix(IRC_SERVER_REC *server, const char *target)
|
||||
{
|
||||
const char *statusmsg;
|
||||
|
||||
/* Quick check */
|
||||
if (server == NULL || server->prefix[(int)(unsigned char)*target] == 0)
|
||||
return target;
|
||||
|
||||
/* Exit early if target doesn't name a channel */
|
||||
if (server_ischannel(SERVER(server), target) == FALSE)
|
||||
return target;
|
||||
|
||||
statusmsg = g_hash_table_lookup(server->isupport, "statusmsg");
|
||||
|
||||
/* Hack: for bahamut 1.4 which sends neither STATUSMSG nor
|
||||
* WALLCHOPS in 005, accept @#chan and @+#chan (but not +#chan) */
|
||||
if (statusmsg == NULL && *target != '@')
|
||||
return target;
|
||||
|
||||
if (statusmsg == NULL)
|
||||
statusmsg = "@+";
|
||||
|
||||
/* Strip the leading statusmsg prefixes */
|
||||
while (strchr(statusmsg, *target) != NULL) {
|
||||
target++;
|
||||
}
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
static void sig_channel_rejoin(SERVER_REC *server, REJOIN_REC *rec)
|
||||
{
|
||||
g_return_if_fail(rec != NULL);
|
||||
|
|
@ -46,7 +91,7 @@ static void sig_event_forward(SERVER_REC *server, const char *data,
|
|||
char *params, *from, *to;
|
||||
|
||||
params = event_get_params(data, 3, NULL, &from, &to);
|
||||
if (from != NULL && to != NULL && ischannel(*from) && ischannel(*to)) {
|
||||
if (from != NULL && to != NULL && server_ischannel(server, from) && server_ischannel(server, to)) {
|
||||
channel = irc_channel_find(server, from);
|
||||
if (channel != NULL && irc_channel_find(server, to) == NULL) {
|
||||
window_bind_add(window_item_window(channel),
|
||||
|
|
|
|||
10
src/fe-common/irc/fe-irc-channels.h
Normal file
10
src/fe-common/irc/fe-irc-channels.h
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
#ifndef __FE_IRC_CHANNELS_H
|
||||
#define __FE_IRC_CHANNELS_H
|
||||
|
||||
int fe_channel_is_opchannel(IRC_SERVER_REC *server, const char *target);
|
||||
const char *fe_channel_skip_prefix(IRC_SERVER_REC *server, const char *target);
|
||||
|
||||
void fe_irc_channels_init(void);
|
||||
void fe_irc_channels_deinit(void);
|
||||
|
||||
#endif
|
||||
|
|
@ -36,32 +36,8 @@
|
|||
|
||||
#include "fe-queries.h"
|
||||
#include "window-items.h"
|
||||
|
||||
static const char *skip_target(IRC_SERVER_REC *server, const char *target)
|
||||
{
|
||||
int i = 0;
|
||||
const char *val, *chars;
|
||||
|
||||
/* Quick check */
|
||||
if (server == NULL || server->prefix[(int)(unsigned char)*target] == 0)
|
||||
return target;
|
||||
|
||||
/* Hack: for bahamut 1.4 which sends neither STATUSMSG nor
|
||||
* WALLCHOPS in 005, accept @#chan and @+#chan (but not +#chan) */
|
||||
val = g_hash_table_lookup(server->isupport, "STATUSMSG");
|
||||
if (val == NULL && *target != '@')
|
||||
return target;
|
||||
chars = val ? val : "@+";
|
||||
for(i = 0; target[i] != '\0'; i++) {
|
||||
if (strchr(chars, target[i]) == NULL)
|
||||
break;
|
||||
};
|
||||
|
||||
if(ischannel(target[i]))
|
||||
target += i;
|
||||
|
||||
return target;
|
||||
}
|
||||
#include "fe-irc-channels.h"
|
||||
#include "fe-irc-server.h"
|
||||
|
||||
static void sig_message_own_public(SERVER_REC *server, const char *msg,
|
||||
const char *target, const char *origtarget)
|
||||
|
|
@ -72,7 +48,7 @@ static void sig_message_own_public(SERVER_REC *server, const char *msg,
|
|||
if (!IS_IRC_SERVER(server))
|
||||
return;
|
||||
oldtarget = target;
|
||||
target = skip_target(IRC_SERVER(server), target);
|
||||
target = fe_channel_skip_prefix(IRC_SERVER(server), target);
|
||||
if (target != oldtarget) {
|
||||
/* Hybrid 6 / Bahamut feature, send msg to all
|
||||
ops / ops+voices in channel */
|
||||
|
|
@ -95,18 +71,28 @@ static void sig_message_irc_op_public(SERVER_REC *server, const char *msg,
|
|||
const char *nick, const char *address,
|
||||
const char *target)
|
||||
{
|
||||
char *nickmode, *optarget;
|
||||
char *nickmode, *optarget, *prefix;
|
||||
const char *cleantarget;
|
||||
|
||||
nickmode = channel_get_nickmode(channel_find(server, target),
|
||||
/* only skip here so the difference can be stored in prefix */
|
||||
cleantarget = fe_channel_skip_prefix(IRC_SERVER(server), target);
|
||||
prefix = g_strndup(target, cleantarget - target);
|
||||
|
||||
/* and clean the rest here */
|
||||
cleantarget = get_visible_target(IRC_SERVER(server), cleantarget);
|
||||
|
||||
nickmode = channel_get_nickmode(channel_find(server, cleantarget),
|
||||
nick);
|
||||
|
||||
optarget = g_strconcat("@", target, NULL);
|
||||
printformat_module("fe-common/core", server, target,
|
||||
optarget = g_strconcat(prefix, cleantarget, NULL);
|
||||
|
||||
printformat_module("fe-common/core", server, cleantarget,
|
||||
MSGLEVEL_PUBLIC,
|
||||
TXT_PUBMSG_CHANNEL,
|
||||
nick, optarget, msg, nickmode);
|
||||
g_free(nickmode);
|
||||
g_free(optarget);
|
||||
g_free(prefix);
|
||||
}
|
||||
|
||||
static void sig_message_own_wall(SERVER_REC *server, const char *msg,
|
||||
|
|
@ -117,6 +103,7 @@ static void sig_message_own_wall(SERVER_REC *server, const char *msg,
|
|||
nickmode = channel_get_nickmode(channel_find(server, target),
|
||||
server->nick);
|
||||
|
||||
/* this is always @, skip_prefix is not needed here */
|
||||
optarget = g_strconcat("@", target, NULL);
|
||||
printformat_module("fe-common/core", server, target,
|
||||
MSGLEVEL_PUBLIC | MSGLEVEL_NOHILIGHT |
|
||||
|
|
@ -135,8 +122,8 @@ static void sig_message_own_action(IRC_SERVER_REC *server, const char *msg,
|
|||
char *freemsg = NULL;
|
||||
|
||||
oldtarget = target;
|
||||
target = skip_target(IRC_SERVER(server), target);
|
||||
if (ischannel(*target))
|
||||
target = fe_channel_skip_prefix(IRC_SERVER(server), target);
|
||||
if (server_ischannel(SERVER(server), target))
|
||||
item = irc_channel_find(server, target);
|
||||
else
|
||||
item = irc_query_find(server, target);
|
||||
|
|
@ -146,7 +133,7 @@ static void sig_message_own_action(IRC_SERVER_REC *server, const char *msg,
|
|||
|
||||
printformat(server, target,
|
||||
MSGLEVEL_ACTIONS | MSGLEVEL_NOHILIGHT | MSGLEVEL_NO_ACT |
|
||||
(ischannel(*target) ? MSGLEVEL_PUBLIC : MSGLEVEL_MSGS),
|
||||
(server_ischannel(SERVER(server), target) ? MSGLEVEL_PUBLIC : MSGLEVEL_MSGS),
|
||||
item != NULL && oldtarget == target ? IRCTXT_OWN_ACTION : IRCTXT_OWN_ACTION_TARGET,
|
||||
server->nick, msg, oldtarget);
|
||||
g_free_not_null(freemsg);
|
||||
|
|
@ -163,10 +150,10 @@ static void sig_message_irc_action(IRC_SERVER_REC *server, const char *msg,
|
|||
int own = FALSE;
|
||||
|
||||
oldtarget = target;
|
||||
target = skip_target(IRC_SERVER(server), target);
|
||||
target = fe_channel_skip_prefix(IRC_SERVER(server), target);
|
||||
|
||||
level = MSGLEVEL_ACTIONS |
|
||||
(ischannel(*target) ? MSGLEVEL_PUBLIC : MSGLEVEL_MSGS);
|
||||
(server_ischannel(SERVER(server), target) ? MSGLEVEL_PUBLIC : MSGLEVEL_MSGS);
|
||||
|
||||
if (ignore_check(SERVER(server), nick, address, target, msg, level))
|
||||
return;
|
||||
|
|
@ -175,7 +162,7 @@ static void sig_message_irc_action(IRC_SERVER_REC *server, const char *msg,
|
|||
level | MSGLEVEL_NO_ACT))
|
||||
level |= MSGLEVEL_NO_ACT;
|
||||
|
||||
if (ischannel(*target)) {
|
||||
if (server_ischannel(SERVER(server), target)) {
|
||||
item = irc_channel_find(server, target);
|
||||
} else {
|
||||
own = (!g_strcmp0(nick, server->nick));
|
||||
|
|
@ -185,7 +172,7 @@ static void sig_message_irc_action(IRC_SERVER_REC *server, const char *msg,
|
|||
if (settings_get_bool("emphasis"))
|
||||
msg = freemsg = expand_emphasis(item, msg);
|
||||
|
||||
if (ischannel(*target)) {
|
||||
if (server_ischannel(SERVER(server), target)) {
|
||||
/* channel action */
|
||||
if (window_item_is_active(item) && target == oldtarget) {
|
||||
/* message to active channel in window */
|
||||
|
|
@ -219,7 +206,7 @@ static void sig_message_irc_action(IRC_SERVER_REC *server, const char *msg,
|
|||
static void sig_message_own_notice(IRC_SERVER_REC *server, const char *msg,
|
||||
const char *target)
|
||||
{
|
||||
printformat(server, skip_target(server, target), MSGLEVEL_NOTICES |
|
||||
printformat(server, fe_channel_skip_prefix(server, target), MSGLEVEL_NOTICES |
|
||||
MSGLEVEL_NOHILIGHT | MSGLEVEL_NO_ACT,
|
||||
IRCTXT_OWN_NOTICE, target, msg);
|
||||
}
|
||||
|
|
@ -232,7 +219,7 @@ static void sig_message_irc_notice(SERVER_REC *server, const char *msg,
|
|||
int level = MSGLEVEL_NOTICES;
|
||||
|
||||
oldtarget = target;
|
||||
target = skip_target(IRC_SERVER(server), target);
|
||||
target = fe_channel_skip_prefix(IRC_SERVER(server), target);
|
||||
|
||||
if (address == NULL || *address == '\0') {
|
||||
/* notice from server */
|
||||
|
|
@ -245,16 +232,16 @@ static void sig_message_irc_notice(SERVER_REC *server, const char *msg,
|
|||
}
|
||||
|
||||
if (ignore_check(server, nick, address,
|
||||
ischannel(*target) ? target : NULL,
|
||||
server_ischannel(SERVER(server), target) ? target : NULL,
|
||||
msg, level))
|
||||
return;
|
||||
|
||||
if (ignore_check(server, nick, address,
|
||||
ischannel(*target) ? target : NULL,
|
||||
server_ischannel(SERVER(server), target) ? target : NULL,
|
||||
msg, level | MSGLEVEL_NO_ACT))
|
||||
level |= MSGLEVEL_NO_ACT;
|
||||
|
||||
if (ischannel(*target)) {
|
||||
if (server_ischannel(SERVER(server), target)) {
|
||||
/* notice in some channel */
|
||||
printformat(server, target, level,
|
||||
IRCTXT_NOTICE_PUBLIC, nick, oldtarget, msg);
|
||||
|
|
@ -270,7 +257,7 @@ static void sig_message_irc_notice(SERVER_REC *server, const char *msg,
|
|||
static void sig_message_own_ctcp(IRC_SERVER_REC *server, const char *cmd,
|
||||
const char *data, const char *target)
|
||||
{
|
||||
printformat(server, skip_target(server, target), MSGLEVEL_CTCPS |
|
||||
printformat(server, fe_channel_skip_prefix(server, target), MSGLEVEL_CTCPS |
|
||||
MSGLEVEL_NOHILIGHT | MSGLEVEL_NO_ACT,
|
||||
IRCTXT_OWN_CTCP, target, cmd, data);
|
||||
}
|
||||
|
|
@ -282,8 +269,8 @@ static void sig_message_irc_ctcp(IRC_SERVER_REC *server, const char *cmd,
|
|||
const char *oldtarget;
|
||||
|
||||
oldtarget = target;
|
||||
target = skip_target(server, target);
|
||||
printformat(server, ischannel(*target) ? target : nick, MSGLEVEL_CTCPS,
|
||||
target = fe_channel_skip_prefix(server, target);
|
||||
printformat(server, server_ischannel(SERVER(server), target) ? target : nick, MSGLEVEL_CTCPS,
|
||||
IRCTXT_CTCP_REQUESTED, nick, addr, cmd, data, oldtarget);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ static void event_privmsg(SERVER_REC *server, const char *data,
|
|||
|
||||
g_return_if_fail(data != NULL);
|
||||
|
||||
if (nick == NULL || address == NULL || ischannel(*data) ||
|
||||
if (nick == NULL || address == NULL || server_ischannel(server, data) ||
|
||||
!settings_get_bool("query_track_nick_changes"))
|
||||
return;
|
||||
|
||||
|
|
|
|||
|
|
@ -56,7 +56,12 @@ static void cmd_network_list(void)
|
|||
g_string_append_printf(str, "autosendcmd: %s, ", rec->autosendcmd);
|
||||
if (rec->usermode != NULL)
|
||||
g_string_append_printf(str, "usermode: %s, ", rec->usermode);
|
||||
|
||||
if (rec->sasl_mechanism != NULL)
|
||||
g_string_append_printf(str, "sasl_mechanism: %s, ", rec->sasl_mechanism);
|
||||
if (rec->sasl_username != NULL)
|
||||
g_string_append_printf(str, "sasl_username: %s, ", rec->sasl_username);
|
||||
if (rec->sasl_password != NULL)
|
||||
g_string_append_printf(str, "sasl_password: (pass), ");
|
||||
if (rec->cmd_queue_speed > 0)
|
||||
g_string_append_printf(str, "cmdspeed: %d, ", rec->cmd_queue_speed);
|
||||
if (rec->max_cmds_at_once > 0)
|
||||
|
|
@ -84,8 +89,10 @@ static void cmd_network_list(void)
|
|||
/* SYNTAX: NETWORK ADD [-nick <nick>] [-user <user>] [-realname <name>]
|
||||
[-host <host>] [-usermode <mode>] [-autosendcmd <cmd>]
|
||||
[-querychans <count>] [-whois <count>] [-msgs <count>]
|
||||
[-kicks <count>] [-modes <count>]
|
||||
[-cmdspeed <ms>] [-cmdmax <count>] <name> */
|
||||
[-kicks <count>] [-modes <count>] [-cmdspeed <ms>]
|
||||
[-cmdmax <count>] [-sasl_mechanism <mechanism>]
|
||||
[-sasl_username <username>] [-sasl_password <password>]
|
||||
<name> */
|
||||
static void cmd_network_add(const char *data)
|
||||
{
|
||||
GHashTable *optlist;
|
||||
|
|
@ -112,6 +119,9 @@ static void cmd_network_add(const char *data)
|
|||
}
|
||||
if (g_hash_table_lookup(optlist, "usermode")) g_free_and_null(rec->usermode);
|
||||
if (g_hash_table_lookup(optlist, "autosendcmd")) g_free_and_null(rec->autosendcmd);
|
||||
if (g_hash_table_lookup(optlist, "sasl_mechanism")) g_free_and_null(rec->sasl_mechanism);
|
||||
if (g_hash_table_lookup(optlist, "sasl_username")) g_free_and_null(rec->sasl_username);
|
||||
if (g_hash_table_lookup(optlist, "sasl_password")) g_free_and_null(rec->sasl_password);
|
||||
}
|
||||
|
||||
value = g_hash_table_lookup(optlist, "kicks");
|
||||
|
|
@ -148,6 +158,14 @@ static void cmd_network_add(const char *data)
|
|||
value = g_hash_table_lookup(optlist, "autosendcmd");
|
||||
if (value != NULL && *value != '\0') rec->autosendcmd = g_strdup(value);
|
||||
|
||||
/* the validity of the parameters is checked in sig_server_setup_fill_chatnet */
|
||||
value = g_hash_table_lookup(optlist, "sasl_mechanism");
|
||||
if (value != NULL && *value != '\0') rec->sasl_mechanism = g_strdup(value);
|
||||
value = g_hash_table_lookup(optlist, "sasl_username");
|
||||
if (value != NULL && *value != '\0') rec->sasl_username = g_strdup(value);
|
||||
value = g_hash_table_lookup(optlist, "sasl_password");
|
||||
if (value != NULL && *value != '\0') rec->sasl_password = g_strdup(value);
|
||||
|
||||
ircnet_create(rec);
|
||||
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_NETWORK_ADDED, name);
|
||||
|
||||
|
|
@ -186,7 +204,8 @@ void fe_ircnet_init(void)
|
|||
command_bind("network add", NULL, (SIGNAL_FUNC) cmd_network_add);
|
||||
command_bind("network remove", NULL, (SIGNAL_FUNC) cmd_network_remove);
|
||||
|
||||
command_set_options("network add", "-kicks -msgs -modes -whois -cmdspeed -cmdmax -nick -user -realname -host -autosendcmd -querychans -usermode");
|
||||
command_set_options("network add", "-kicks -msgs -modes -whois -cmdspeed "
|
||||
"-cmdmax -nick -user -realname -host -autosendcmd -querychans -usermode -sasl_mechanism -sasl_username -sasl_password");
|
||||
}
|
||||
|
||||
void fe_ircnet_deinit(void)
|
||||
|
|
|
|||
|
|
@ -168,7 +168,7 @@ static void sig_message_mode(IRC_SERVER_REC *server, const char *channel,
|
|||
mode, MSGLEVEL_MODES))
|
||||
return;
|
||||
|
||||
if (!ischannel(*channel)) {
|
||||
if (!server_ischannel(SERVER(server), channel)) {
|
||||
/* user mode change */
|
||||
printformat(server, NULL, MSGLEVEL_MODES,
|
||||
IRCTXT_USERMODE_CHANGE, mode, channel);
|
||||
|
|
|
|||
|
|
@ -400,7 +400,7 @@ static void msg_mode(IRC_SERVER_REC *server, const char *channel,
|
|||
int show;
|
||||
|
||||
g_return_if_fail(data != NULL);
|
||||
if (!ischannel(*channel) || addr != NULL)
|
||||
if (!server_ischannel(SERVER(server), channel) || addr != NULL)
|
||||
return;
|
||||
|
||||
params = event_get_params(data, 2 | PARAM_FLAG_GETREST,
|
||||
|
|
|
|||
48
src/fe-common/irc/fe-sasl.c
Normal file
48
src/fe-common/irc/fe-sasl.c
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
fe-sasl.c : irssi
|
||||
|
||||
Copyright (C) 2015 The Lemon Man
|
||||
|
||||
This program 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "module.h"
|
||||
#include "module-formats.h"
|
||||
#include "signals.h"
|
||||
#include "levels.h"
|
||||
|
||||
#include "printtext.h"
|
||||
|
||||
static void sig_sasl_success(IRC_SERVER_REC *server)
|
||||
{
|
||||
printformat(server, NULL, MSGLEVEL_CRAP, IRCTXT_SASL_SUCCESS);
|
||||
}
|
||||
|
||||
static void sig_sasl_failure(IRC_SERVER_REC *server, const char *reason)
|
||||
{
|
||||
printformat(server, NULL, MSGLEVEL_CRAP, IRCTXT_SASL_ERROR, reason);
|
||||
}
|
||||
|
||||
void fe_sasl_init(void)
|
||||
{
|
||||
signal_add("server sasl success", (SIGNAL_FUNC) sig_sasl_success);
|
||||
signal_add("server sasl failure", (SIGNAL_FUNC) sig_sasl_failure);
|
||||
}
|
||||
|
||||
void fe_sasl_deinit(void)
|
||||
{
|
||||
signal_remove("server sasl success", (SIGNAL_FUNC) sig_sasl_success);
|
||||
signal_remove("server sasl failure", (SIGNAL_FUNC) sig_sasl_failure);
|
||||
}
|
||||
|
|
@ -44,6 +44,8 @@ FORMAT_REC fecommon_irc_formats[] = {
|
|||
{ "setupserver_header", "%#Server Port Network Settings", 0 },
|
||||
{ "setupserver_line", "%#%|$[!20]0 $[5]1 $[10]2 $3", 4, { 0, 1, 0, 0 } },
|
||||
{ "setupserver_footer", "", 0 },
|
||||
{ "sasl_success", "SASL authentication succeeded", 0 },
|
||||
{ "sasl_error", "Cannot authenticate via SASL ($0)", 1, { 0 } },
|
||||
|
||||
/* ---- */
|
||||
{ NULL, "Channels", 0 },
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@ enum {
|
|||
IRCTXT_SETUPSERVER_HEADER,
|
||||
IRCTXT_SETUPSERVER_LINE,
|
||||
IRCTXT_SETUPSERVER_FOOTER,
|
||||
IRCTXT_SASL_SUCCESS,
|
||||
IRCTXT_SASL_ERROR,
|
||||
|
||||
IRCTXT_FILL_2,
|
||||
|
||||
|
|
|
|||
|
|
@ -227,8 +227,7 @@ static void sig_gui_print_text(WINDOW_REC *window, void *fgcolor,
|
|||
term_move(root_window, next_xpos, next_ypos);
|
||||
if (flags & GUI_PRINT_FLAG_CLRTOEOL)
|
||||
term_clrtoeol(root_window);
|
||||
term_addstr(root_window, str);
|
||||
next_xpos += strlen(str); /* FIXME utf8 or big5 */
|
||||
next_xpos += term_addstr(root_window, str);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -237,7 +237,7 @@ static void paste_buffer_join_lines(GArray *buf)
|
|||
last_lf = FALSE;
|
||||
if (++line_len >= 400 && last_lf_pos != NULL) {
|
||||
memmove(last_lf_pos+1, last_lf_pos,
|
||||
dest - last_lf_pos);
|
||||
(dest - last_lf_pos) * sizeof(unichar));
|
||||
*last_lf_pos = '\n'; last_lf_pos = NULL;
|
||||
line_len = 0;
|
||||
dest++;
|
||||
|
|
|
|||
|
|
@ -286,22 +286,6 @@ static void winsock_init(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_GC
|
||||
#ifdef HAVE_GC_H
|
||||
# include <gc.h>
|
||||
#else
|
||||
# include <gc/gc.h>
|
||||
#endif
|
||||
|
||||
GMemVTable gc_mem_table = {
|
||||
GC_malloc,
|
||||
GC_realloc,
|
||||
GC_free,
|
||||
|
||||
NULL, NULL, NULL
|
||||
};
|
||||
#endif
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
static int version = 0;
|
||||
|
|
@ -312,10 +296,6 @@ int main(int argc, char **argv)
|
|||
};
|
||||
int loglev;
|
||||
|
||||
#ifdef USE_GC
|
||||
g_mem_set_vtable(&gc_mem_table);
|
||||
#endif
|
||||
|
||||
core_register_options();
|
||||
fe_common_core_register_options();
|
||||
args_register(options);
|
||||
|
|
@ -369,9 +349,6 @@ int main(int argc, char **argv)
|
|||
/* Does the same as g_main_run(main_loop), except we
|
||||
can call our dirty-checker after each iteration */
|
||||
while (!quitting) {
|
||||
#ifdef USE_GC
|
||||
GC_collect_a_little();
|
||||
#endif
|
||||
if (!dummy) term_refresh_freeze();
|
||||
g_main_iteration(TRUE);
|
||||
if (!dummy) term_refresh_thaw();
|
||||
|
|
|
|||
|
|
@ -347,10 +347,14 @@ static void item_lag(SBAR_ITEM_REC *item, int get_size_only)
|
|||
last_lag_unknown = lag_unknown;
|
||||
|
||||
if (lag_unknown) {
|
||||
// "??)" in C becomes ']'
|
||||
// See: https://en.wikipedia.org/wiki/Digraphs_and_trigraphs#C
|
||||
g_snprintf(str, sizeof(str), "%d (?""?)", lag / 100);
|
||||
} else {
|
||||
g_snprintf(str, sizeof(str),
|
||||
lag%100 == 0 ? "%d" : "%d.%02d", lag/100, lag%100);
|
||||
if (lag % 100 == 0)
|
||||
g_snprintf(str, sizeof(str), "%d", lag / 100);
|
||||
else
|
||||
g_snprintf(str, sizeof(str), "%d.%02d", lag / 100, lag % 100);
|
||||
}
|
||||
|
||||
statusbar_item_default_handler(item, get_size_only,
|
||||
|
|
|
|||
|
|
@ -522,15 +522,36 @@ void term_add_unichar(TERM_WINDOW *window, unichar chr)
|
|||
}
|
||||
}
|
||||
|
||||
void term_addstr(TERM_WINDOW *window, const char *str)
|
||||
int term_addstr(TERM_WINDOW *window, const char *str)
|
||||
{
|
||||
int len;
|
||||
int len, raw_len;
|
||||
unichar tmp;
|
||||
const char *ptr;
|
||||
|
||||
if (vcmove) term_move_real();
|
||||
len = strlen(str); /* FIXME utf8 or big5 */
|
||||
|
||||
len = 0;
|
||||
raw_len = strlen(str);
|
||||
|
||||
/* The string length depends on the terminal encoding */
|
||||
|
||||
ptr = str;
|
||||
|
||||
if (term_type == TERM_TYPE_UTF8) {
|
||||
while (*ptr != '\0') {
|
||||
tmp = g_utf8_get_char(ptr);
|
||||
len += unichar_isprint(tmp) ? mk_wcwidth(tmp) : 1;
|
||||
ptr = g_utf8_next_char(ptr);
|
||||
}
|
||||
} else
|
||||
len = raw_len;
|
||||
|
||||
term_printed_text(len);
|
||||
|
||||
fwrite(str, 1, len, window->term->out);
|
||||
/* Use strlen() here since we need the number of raw bytes */
|
||||
fwrite(str, 1, raw_len, window->term->out);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
void term_clrtoeol(TERM_WINDOW *window)
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ void term_set_color(TERM_WINDOW *window, int col);
|
|||
void term_move(TERM_WINDOW *window, int x, int y);
|
||||
void term_addch(TERM_WINDOW *window, char chr);
|
||||
void term_add_unichar(TERM_WINDOW *window, unichar chr);
|
||||
void term_addstr(TERM_WINDOW *window, const char *str);
|
||||
int term_addstr(TERM_WINDOW *window, const char *str);
|
||||
void term_clrtoeol(TERM_WINDOW *window);
|
||||
|
||||
void term_move_cursor(int x, int y);
|
||||
|
|
|
|||
|
|
@ -106,6 +106,10 @@ static TERMINFO_REC tcaps[] = {
|
|||
|
||||
/* Beep */
|
||||
{ "bel", "bl", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_bel) },
|
||||
|
||||
/* Keyboard-transmit mode */
|
||||
{ "smkx", "ks", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_smkx) },
|
||||
{ "rmkx", "ke", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_rmkx) },
|
||||
};
|
||||
|
||||
/* Move cursor (cursor_address / cup) */
|
||||
|
|
@ -498,6 +502,9 @@ static void terminfo_input_init(TERM_REC *term)
|
|||
memcpy(&term->tio, &term->old_tio, sizeof(term->tio));
|
||||
|
||||
term->tio.c_lflag &= ~(ICANON | ECHO); /* CBREAK, no ECHO */
|
||||
/* Disable the ICRNL flag to disambiguate ^J and Enter, also disable the
|
||||
* software flow control to leave ^Q and ^S ready to be bound */
|
||||
term->tio.c_iflag &= ~(ICRNL | IXON | IXOFF);
|
||||
term->tio.c_cc[VMIN] = 1; /* read() is satisfied after 1 char */
|
||||
term->tio.c_cc[VTIME] = 0; /* No timer */
|
||||
|
||||
|
|
@ -524,6 +531,10 @@ void terminfo_cont(TERM_REC *term)
|
|||
{
|
||||
if (term->TI_smcup)
|
||||
tput(tparm(term->TI_smcup));
|
||||
|
||||
if (term->TI_smkx)
|
||||
tput(tparm(term->TI_smkx));
|
||||
|
||||
terminfo_input_init(term);
|
||||
}
|
||||
|
||||
|
|
@ -538,6 +549,9 @@ void terminfo_stop(TERM_REC *term)
|
|||
if (term->TI_rmcup)
|
||||
tput(tparm(term->TI_rmcup));
|
||||
|
||||
if (term->TI_rmkx)
|
||||
tput(tparm(term->TI_rmkx));
|
||||
|
||||
/* reset input settings */
|
||||
terminfo_input_deinit(term);
|
||||
fflush(term->out);
|
||||
|
|
|
|||
|
|
@ -88,6 +88,10 @@ struct _TERM_REC {
|
|||
|
||||
/* Beep */
|
||||
char *TI_bel;
|
||||
|
||||
/* Keyboard-transmit mode */
|
||||
const char *TI_smkx;
|
||||
const char *TI_rmkx;
|
||||
};
|
||||
|
||||
extern TERM_REC *current_term;
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ libirc_core_a_SOURCES = \
|
|||
irc-servers-setup.c \
|
||||
irc-session.c \
|
||||
irc-cap.c \
|
||||
sasl.c \
|
||||
lag.c \
|
||||
massjoin.c \
|
||||
modes.c \
|
||||
|
|
@ -50,6 +51,7 @@ pkginc_irc_core_HEADERS = \
|
|||
irc-servers.h \
|
||||
irc-servers-setup.h \
|
||||
irc-cap.h \
|
||||
sasl.h \
|
||||
modes.h \
|
||||
mode-lists.h \
|
||||
module.h \
|
||||
|
|
|
|||
|
|
@ -186,7 +186,7 @@ static void command_set_ban(const char *data, IRC_SERVER_REC *server,
|
|||
|
||||
if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_OPTCHAN | PARAM_FLAG_GETREST,
|
||||
item, &channel, &nicks)) return;
|
||||
if (!ischannel(*channel)) cmd_param_error(CMDERR_NOT_JOINED);
|
||||
if (!server_ischannel(SERVER(server), channel)) cmd_param_error(CMDERR_NOT_JOINED);
|
||||
if (*nicks == '\0') {
|
||||
if (g_strcmp0(data, "*") != 0)
|
||||
cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
|
||||
|
|
|
|||
|
|
@ -149,7 +149,7 @@ static void event_target_unavailable(IRC_SERVER_REC *server, const char *data)
|
|||
g_return_if_fail(data != NULL);
|
||||
|
||||
params = event_get_params(data, 2, NULL, &channel);
|
||||
if (ischannel(*channel)) {
|
||||
if (server_ischannel(SERVER(server), channel)) {
|
||||
chanrec = irc_channel_find(server, channel);
|
||||
if (chanrec != NULL && chanrec->joined) {
|
||||
/* dalnet event - can't change nick while
|
||||
|
|
|
|||
|
|
@ -1,3 +1,22 @@
|
|||
/* irc-cap.c : irssi
|
||||
|
||||
Copyright (C) 2015 The Lemon Man
|
||||
|
||||
This program 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "module.h"
|
||||
#include "signals.h"
|
||||
#include "misc.h"
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ static void irc_channels_join(IRC_SERVER_REC *server, const char *data,
|
|||
tmp = chanlist;
|
||||
for (;; tmp++) {
|
||||
if (*tmp != NULL) {
|
||||
channel = ischannel(**tmp) ? g_strdup(*tmp) :
|
||||
channel = server_ischannel(SERVER(server), *tmp) ? g_strdup(*tmp) :
|
||||
g_strdup_printf("#%s", *tmp);
|
||||
|
||||
chanrec = irc_channel_find(server, channel);
|
||||
|
|
@ -134,7 +134,7 @@ static void irc_channels_join(IRC_SERVER_REC *server, const char *data,
|
|||
if (use_keys)
|
||||
cmdlen += outkeys->len;
|
||||
if (*tmpstr != NULL)
|
||||
cmdlen += ischannel(**tmpstr) ? strlen(*tmpstr) :
|
||||
cmdlen += server_ischannel(SERVER(server), *tmpstr) ? strlen(*tmpstr) :
|
||||
strlen(*tmpstr)+1;
|
||||
if (*tmpkey != NULL)
|
||||
cmdlen += strlen(*tmpkey);
|
||||
|
|
@ -148,9 +148,11 @@ static void irc_channels_join(IRC_SERVER_REC *server, const char *data,
|
|||
if (outchans->len > 0) {
|
||||
g_string_truncate(outchans, outchans->len - 1);
|
||||
g_string_truncate(outkeys, outkeys->len - 1);
|
||||
irc_send_cmdv(IRC_SERVER(server),
|
||||
use_keys ? "JOIN %s %s" : "JOIN %s",
|
||||
outchans->str, outkeys->str);
|
||||
|
||||
if (use_keys)
|
||||
irc_send_cmdv(IRC_SERVER(server), "JOIN %s %s", outchans->str, outkeys->str);
|
||||
else
|
||||
irc_send_cmdv(IRC_SERVER(server), "JOIN %s", outchans->str);
|
||||
}
|
||||
cmdlen = 0;
|
||||
g_string_truncate(outchans,0);
|
||||
|
|
|
|||
|
|
@ -35,10 +35,13 @@ void ircnet_create(IRC_CHATNET_REC *rec)
|
|||
|
||||
static void sig_chatnet_read(IRC_CHATNET_REC *rec, CONFIG_NODE *node)
|
||||
{
|
||||
char *value;
|
||||
|
||||
if (!IS_IRC_CHATNET(rec))
|
||||
return;
|
||||
|
||||
rec->usermode = g_strdup(config_node_get_str(node, "usermode", NULL));
|
||||
value = config_node_get_str(node, "usermode", NULL);
|
||||
rec->usermode = (value != NULL && *value != '\0') ? g_strdup(value) : NULL;
|
||||
|
||||
rec->max_cmds_at_once = config_node_get_int(node, "cmdmax", 0);
|
||||
rec->cmd_queue_speed = config_node_get_int(node, "cmdspeed", 0);
|
||||
|
|
@ -48,6 +51,10 @@ static void sig_chatnet_read(IRC_CHATNET_REC *rec, CONFIG_NODE *node)
|
|||
rec->max_msgs = config_node_get_int(node, "max_msgs", 0);
|
||||
rec->max_modes = config_node_get_int(node, "max_modes", 0);
|
||||
rec->max_whois = config_node_get_int(node, "max_whois", 0);
|
||||
|
||||
rec->sasl_mechanism = g_strdup(config_node_get_str(node, "sasl_mechanism", NULL));
|
||||
rec->sasl_username = g_strdup(config_node_get_str(node, "sasl_username", NULL));
|
||||
rec->sasl_password = g_strdup(config_node_get_str(node, "sasl_password", NULL));
|
||||
}
|
||||
|
||||
static void sig_chatnet_saved(IRC_CHATNET_REC *rec, CONFIG_NODE *node)
|
||||
|
|
@ -73,12 +80,23 @@ static void sig_chatnet_saved(IRC_CHATNET_REC *rec, CONFIG_NODE *node)
|
|||
iconfig_node_set_int(node, "max_modes", rec->max_modes);
|
||||
if (rec->max_whois > 0)
|
||||
iconfig_node_set_int(node, "max_whois", rec->max_whois);
|
||||
|
||||
if (rec->sasl_mechanism != NULL)
|
||||
iconfig_node_set_str(node, "sasl_mechanism", rec->sasl_mechanism);
|
||||
if (rec->sasl_username != NULL)
|
||||
iconfig_node_set_str(node, "sasl_username", rec->sasl_username);
|
||||
if (rec->sasl_password != NULL)
|
||||
iconfig_node_set_str(node, "sasl_password", rec->sasl_password);
|
||||
}
|
||||
|
||||
static void sig_chatnet_destroyed(IRC_CHATNET_REC *rec)
|
||||
{
|
||||
if (IS_IRC_CHATNET(rec))
|
||||
if (IS_IRC_CHATNET(rec)) {
|
||||
g_free(rec->usermode);
|
||||
g_free(rec->sasl_mechanism);
|
||||
g_free(rec->sasl_username);
|
||||
g_free(rec->sasl_password);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -19,10 +19,13 @@ struct _IRC_CHATNET_REC {
|
|||
|
||||
char *usermode;
|
||||
|
||||
char *sasl_mechanism;
|
||||
char *sasl_username;
|
||||
char *sasl_password;
|
||||
|
||||
int max_cmds_at_once;
|
||||
int cmd_queue_speed;
|
||||
int max_query_chans; /* when syncing, max. number of channels to
|
||||
put in one MODE/WHO command */
|
||||
int max_query_chans; /* when syncing, max. number of channels to put in one MODE/WHO command */
|
||||
|
||||
/* max. number of kicks/msgs/mode/whois per command */
|
||||
int max_kicks, max_msgs, max_modes, max_whois;
|
||||
|
|
|
|||
|
|
@ -170,8 +170,11 @@ static void cmd_part(const char *data, IRC_SERVER_REC *server,
|
|||
|
||||
if (*msg != '\0')
|
||||
recoded = recode_out(SERVER(server), msg, channame);
|
||||
irc_send_cmdv(server, ! recoded ? "PART %s" : "PART %s :%s",
|
||||
channame, recoded);
|
||||
|
||||
if (recoded == NULL)
|
||||
irc_send_cmdv(server, "PART %s", channame);
|
||||
else
|
||||
irc_send_cmdv(server, "PART %s :%s", channame, recoded);
|
||||
|
||||
g_free(recoded);
|
||||
cmd_params_free(free_arg);
|
||||
|
|
@ -191,7 +194,7 @@ static void cmd_kick(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *item
|
|||
return;
|
||||
|
||||
if (*channame == '\0' || *nicks == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
|
||||
if (!ischannel(*channame)) cmd_param_error(CMDERR_NOT_JOINED);
|
||||
if (!server_ischannel(SERVER(server), channame)) cmd_param_error(CMDERR_NOT_JOINED);
|
||||
|
||||
recoded = recode_out(SERVER(server), reason, channame);
|
||||
g_string_printf(tmpstr, "KICK %s %s :%s", channame, nicks, recoded);
|
||||
|
|
@ -219,8 +222,12 @@ static void cmd_topic(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *ite
|
|||
|
||||
if (*topic != '\0' || g_hash_table_lookup(optlist, "delete") != NULL)
|
||||
recoded = recode_out(SERVER(server), topic, channame);
|
||||
irc_send_cmdv(server, recoded == NULL ? "TOPIC %s" : "TOPIC %s :%s",
|
||||
channame, recoded);
|
||||
|
||||
if (recoded == NULL)
|
||||
irc_send_cmdv(server, "TOPIC %s", channame);
|
||||
else
|
||||
irc_send_cmdv(server, "TOPIC %s :%s", channame, recoded);
|
||||
|
||||
g_free(recoded);
|
||||
|
||||
cmd_params_free(free_arg);
|
||||
|
|
@ -295,8 +302,11 @@ static void cmd_who(const char *data, IRC_SERVER_REC *server,
|
|||
*channel = '\0';
|
||||
}
|
||||
|
||||
irc_send_cmdv(server, *rest == '\0' ? "WHO %s" : "WHO %s %s",
|
||||
channel, rest);
|
||||
if (rest[0] == '\0')
|
||||
irc_send_cmdv(server, "WHO %s", channel);
|
||||
else
|
||||
irc_send_cmdv(server, "WHO %s %s", channel, rest);
|
||||
|
||||
cmd_params_free(free_arg);
|
||||
}
|
||||
|
||||
|
|
@ -502,8 +512,11 @@ static void cmd_whowas(const char *data, IRC_SERVER_REC *server)
|
|||
if (free_nick) g_free(nicks_redir);
|
||||
|
||||
server->whowas_found = FALSE;
|
||||
irc_send_cmdv(server, *rest == '\0' ? "WHOWAS %s" :
|
||||
"WHOWAS %s %s", nicks, rest);
|
||||
|
||||
if (rest[0] == '\0')
|
||||
irc_send_cmdv(server, "WHOWAS %s", nicks);
|
||||
else
|
||||
irc_send_cmdv(server, "WHOWAS %s %s", nicks, rest);
|
||||
|
||||
cmd_params_free(free_arg);
|
||||
}
|
||||
|
|
@ -915,7 +928,10 @@ static void command_self(const char *data, IRC_SERVER_REC *server)
|
|||
{
|
||||
CMD_IRC_SERVER(server);
|
||||
|
||||
irc_send_cmdv(server, *data == '\0' ? "%s" : "%s %s", current_command, data);
|
||||
if (data[0] == '\0')
|
||||
irc_send_cmdv(server, "%s", current_command);
|
||||
else
|
||||
irc_send_cmdv(server, "%s %s", current_command, data);
|
||||
}
|
||||
|
||||
static void command_1self(const char *data, IRC_SERVER_REC *server)
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#include "irc-channels.h"
|
||||
#include "irc-queries.h"
|
||||
#include "irc-cap.h"
|
||||
#include "sasl.h"
|
||||
|
||||
#include "irc-servers-setup.h"
|
||||
#include "channels-setup.h"
|
||||
|
|
@ -119,6 +120,7 @@ void irc_core_init(void)
|
|||
netsplit_init();
|
||||
irc_expandos_init();
|
||||
cap_init();
|
||||
sasl_init();
|
||||
|
||||
settings_check();
|
||||
module_register("core", "irc");
|
||||
|
|
@ -128,6 +130,7 @@ void irc_core_deinit(void)
|
|||
{
|
||||
signal_emit("chat protocol deinit", 1, chat_protocol_find("IRC"));
|
||||
|
||||
sasl_deinit();
|
||||
cap_deinit();
|
||||
irc_expandos_deinit();
|
||||
netsplit_deinit();
|
||||
|
|
|
|||
|
|
@ -27,6 +27,10 @@
|
|||
#include "irc-channels.h"
|
||||
#include "nicklist.h"
|
||||
|
||||
#ifndef HOST_NAME_MAX
|
||||
#define HOST_NAME_MAX 255
|
||||
#endif
|
||||
|
||||
static char *last_join;
|
||||
|
||||
/* last person to join a channel you are on */
|
||||
|
|
@ -56,7 +60,7 @@ static char *expando_userhost(SERVER_REC *server, void *item, int *free_ret)
|
|||
{
|
||||
IRC_SERVER_REC *ircserver;
|
||||
const char *username;
|
||||
char hostname[100];
|
||||
char hostname[HOST_NAME_MAX + 1];
|
||||
|
||||
ircserver = IRC_SERVER(server);
|
||||
|
||||
|
|
@ -72,10 +76,36 @@ static char *expando_userhost(SERVER_REC *server, void *item, int *free_ret)
|
|||
username = ircserver->connrec->username;
|
||||
|
||||
if (gethostname(hostname, sizeof(hostname)) != 0 || *hostname == '\0')
|
||||
strcpy(hostname, "??");
|
||||
strcpy(hostname, "(none)");
|
||||
return g_strconcat(username, "@", hostname, NULL);;
|
||||
}
|
||||
|
||||
/* your hostname address (host) */
|
||||
static char *expando_hostname(SERVER_REC *server, void *item, int *free_ret)
|
||||
{
|
||||
IRC_SERVER_REC *ircserver;
|
||||
char hostname[HOST_NAME_MAX + 1];
|
||||
char **list;
|
||||
char *hostname_split;
|
||||
|
||||
ircserver = IRC_SERVER(server);
|
||||
|
||||
*free_ret = TRUE;
|
||||
|
||||
/* prefer the _real_ /userhost reply */
|
||||
if (ircserver != NULL && ircserver->userhost != NULL) {
|
||||
list = g_strsplit(ircserver->userhost, "@", -1);
|
||||
hostname_split = g_strdup(list[1]);
|
||||
g_strfreev(list);
|
||||
return hostname_split;
|
||||
}
|
||||
|
||||
/* haven't received userhost reply yet. guess something */
|
||||
if (gethostname(hostname, sizeof(hostname)) != 0 || *hostname == '\0')
|
||||
strcpy(hostname, "(none)");
|
||||
return g_strdup(hostname);
|
||||
}
|
||||
|
||||
/* user mode in active server */
|
||||
static char *expando_usermode(SERVER_REC *server, void *item, int *free_ret)
|
||||
{
|
||||
|
|
@ -136,6 +166,9 @@ void irc_expandos_init(void)
|
|||
expando_create("X", expando_userhost,
|
||||
"window changed", EXPANDO_ARG_NONE,
|
||||
"window server changed", EXPANDO_ARG_WINDOW, NULL);
|
||||
expando_create("x", expando_hostname,
|
||||
"window changed", EXPANDO_ARG_NONE,
|
||||
"window server changed", EXPANDO_ARG_WINDOW, NULL);
|
||||
expando_create("usermode", expando_usermode,
|
||||
"window changed", EXPANDO_ARG_NONE,
|
||||
"window server changed", EXPANDO_ARG_WINDOW,
|
||||
|
|
@ -164,6 +197,7 @@ void irc_expandos_deinit(void)
|
|||
expando_destroy("H", expando_server_numeric);
|
||||
expando_destroy("S", expando_servername);
|
||||
expando_destroy("X", expando_userhost);
|
||||
expando_destroy("x", expando_hostname);
|
||||
expando_destroy("usermode", expando_usermode);
|
||||
expando_destroy("cumode", expando_cumode);
|
||||
|
||||
|
|
|
|||
|
|
@ -394,7 +394,7 @@ static void event_target_unavailable(IRC_SERVER_REC *server, const char *data)
|
|||
g_return_if_fail(data != NULL);
|
||||
|
||||
params = event_get_params(data, 2, NULL, &channel);
|
||||
if (!ischannel(*channel)) {
|
||||
if (!server_ischannel(SERVER(server), channel)) {
|
||||
/* nick is unavailable. */
|
||||
event_nick_in_use(server, data);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ static void check_query_changes(IRC_SERVER_REC *server, const char *nick,
|
|||
{
|
||||
QUERY_REC *query;
|
||||
|
||||
if (ischannel(*target))
|
||||
if (server_ischannel(SERVER(server), target))
|
||||
return;
|
||||
|
||||
query = irc_query_find(server, nick);
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
#include "irc-chatnets.h"
|
||||
#include "irc-servers-setup.h"
|
||||
#include "irc-servers.h"
|
||||
#include "sasl.h"
|
||||
|
||||
/* Fill information to connection from server setup record */
|
||||
static void sig_server_setup_fill_reconn(IRC_SERVER_CONNECT_REC *conn,
|
||||
|
|
@ -47,12 +48,18 @@ static void sig_server_setup_fill_reconn(IRC_SERVER_CONNECT_REC *conn,
|
|||
|
||||
static void sig_server_setup_fill_connect(IRC_SERVER_CONNECT_REC *conn)
|
||||
{
|
||||
const char *value;
|
||||
|
||||
if (!IS_IRC_SERVER_CONNECT(conn))
|
||||
return;
|
||||
|
||||
conn->alternate_nick = *settings_get_str("alternate_nick") != '\0' ?
|
||||
g_strdup(settings_get_str("alternate_nick")) : NULL;
|
||||
conn->usermode = g_strdup(settings_get_str("usermode"));
|
||||
value = settings_get_str("alternate_nick");
|
||||
conn->alternate_nick = (value != NULL && *value != '\0') ?
|
||||
g_strdup(value) : NULL;
|
||||
|
||||
value = settings_get_str("usermode");
|
||||
conn->usermode = (value != NULL && *value != '\0') ?
|
||||
g_strdup(value) : NULL;
|
||||
}
|
||||
|
||||
static void sig_server_setup_fill_chatnet(IRC_SERVER_CONNECT_REC *conn,
|
||||
|
|
@ -79,6 +86,29 @@ static void sig_server_setup_fill_chatnet(IRC_SERVER_CONNECT_REC *conn,
|
|||
conn->cmd_queue_speed = ircnet->cmd_queue_speed;
|
||||
if (ircnet->max_query_chans > 0)
|
||||
conn->max_query_chans = ircnet->max_query_chans;
|
||||
|
||||
/* Validate the SASL parameters filled by sig_chatnet_read() or cmd_network_add */
|
||||
conn->sasl_mechanism = SASL_MECHANISM_NONE;
|
||||
|
||||
if (ircnet->sasl_mechanism != NULL) {
|
||||
if (!g_ascii_strcasecmp(ircnet->sasl_mechanism, "plain")) {
|
||||
/* The PLAIN method needs both the username and the password */
|
||||
if (ircnet->sasl_username != NULL && *ircnet->sasl_username &&
|
||||
ircnet->sasl_password != NULL && *ircnet->sasl_password) {
|
||||
conn->sasl_mechanism = SASL_MECHANISM_PLAIN;
|
||||
conn->sasl_username = ircnet->sasl_username;
|
||||
conn->sasl_password = ircnet->sasl_password;
|
||||
} else
|
||||
g_warning("The fields sasl_username and sasl_password are either missing or empty");
|
||||
}
|
||||
else if (!g_ascii_strcasecmp(ircnet->sasl_mechanism, "external")) {
|
||||
conn->sasl_mechanism = SASL_MECHANISM_EXTERNAL;
|
||||
conn->sasl_username = NULL;
|
||||
conn->sasl_password = NULL;
|
||||
}
|
||||
else
|
||||
g_warning("Unsupported SASL mechanism \"%s\" selected", ircnet->sasl_mechanism);
|
||||
}
|
||||
}
|
||||
|
||||
static void init_userinfo(void)
|
||||
|
|
|
|||
|
|
@ -33,6 +33,9 @@
|
|||
#include "irc-servers-setup.h"
|
||||
#include "irc-servers.h"
|
||||
#include "irc-cap.h"
|
||||
#include "sasl.h"
|
||||
|
||||
#include "channels-setup.h"
|
||||
#include "channel-rejoin.h"
|
||||
#include "servers-idle.h"
|
||||
#include "servers-reconnect.h"
|
||||
|
|
@ -72,13 +75,20 @@ static int isnickflag_func(SERVER_REC *server, char flag)
|
|||
|
||||
static int ischannel_func(SERVER_REC *server, const char *data)
|
||||
{
|
||||
if (*data == '@') {
|
||||
/* @#channel, @+#channel */
|
||||
IRC_SERVER_REC *irc_server = (IRC_SERVER_REC *) server;
|
||||
char *chantypes, *statusmsg;
|
||||
|
||||
chantypes = g_hash_table_lookup(irc_server->isupport, "chantypes");
|
||||
if (chantypes == NULL)
|
||||
chantypes = "#&!+"; /* normal, local, secure, modeless */
|
||||
statusmsg = g_hash_table_lookup(irc_server->isupport, "statusmsg");
|
||||
if (statusmsg == NULL)
|
||||
statusmsg = "@+";
|
||||
|
||||
while (strchr(statusmsg, *data) != NULL)
|
||||
data++;
|
||||
if (*data == '+' && ischannel(data[1]))
|
||||
return 1;
|
||||
}
|
||||
return ischannel(*data);
|
||||
|
||||
return strchr(chantypes, *data) != NULL;
|
||||
}
|
||||
|
||||
static char **split_line(const SERVER_REC *server, const char *line,
|
||||
|
|
@ -215,6 +225,11 @@ static void server_init(IRC_SERVER_REC *server)
|
|||
g_free(cmd);
|
||||
}
|
||||
|
||||
if (conn->sasl_mechanism != SASL_MECHANISM_NONE)
|
||||
cap_toggle(server, "sasl", TRUE);
|
||||
|
||||
cap_toggle(server, "multi-prefix", TRUE);
|
||||
|
||||
irc_send_cmd_now(server, "CAP LS");
|
||||
|
||||
if (conn->password != NULL && *conn->password != '\0') {
|
||||
|
|
@ -602,33 +617,60 @@ char *irc_server_get_channels(IRC_SERVER_REC *server)
|
|||
GString *chans, *keys;
|
||||
char *ret;
|
||||
int use_keys;
|
||||
char *rejoin_channels_mode;
|
||||
|
||||
g_return_val_if_fail(server != NULL, FALSE);
|
||||
|
||||
rejoin_channels_mode = g_strdup(settings_get_str("rejoin_channels_on_reconnect"));
|
||||
|
||||
if (rejoin_channels_mode == NULL ||
|
||||
(g_ascii_strcasecmp(rejoin_channels_mode, "on") != 0 &&
|
||||
g_ascii_strcasecmp(rejoin_channels_mode, "off") != 0 &&
|
||||
g_ascii_strcasecmp(rejoin_channels_mode, "auto") != 0)) {
|
||||
g_warning("Invalid value for 'rejoin_channels_on_reconnect', valid values are 'on', 'off', 'auto', using 'on' as default value.");
|
||||
g_free(rejoin_channels_mode);
|
||||
rejoin_channels_mode = g_strdup("on");
|
||||
}
|
||||
|
||||
chans = g_string_new(NULL);
|
||||
keys = g_string_new(NULL);
|
||||
use_keys = FALSE;
|
||||
|
||||
/* do we want to rejoin channels in the first place? */
|
||||
if(g_ascii_strcasecmp(rejoin_channels_mode, "off") == 0) {
|
||||
g_string_free(chans, TRUE);
|
||||
g_string_free(keys, TRUE);
|
||||
g_free(rejoin_channels_mode);
|
||||
return g_strdup("");
|
||||
}
|
||||
|
||||
/* get currently joined channels */
|
||||
for (tmp = server->channels; tmp != NULL; tmp = tmp->next) {
|
||||
CHANNEL_REC *channel = tmp->data;
|
||||
|
||||
CHANNEL_SETUP_REC *setup = channel_setup_find(channel->name, channel->server->connrec->chatnet);
|
||||
if ((setup != NULL && setup->autojoin && g_ascii_strcasecmp(rejoin_channels_mode, "auto") == 0) ||
|
||||
g_ascii_strcasecmp(rejoin_channels_mode, "on") == 0) {
|
||||
g_string_append_printf(chans, "%s,", channel->name);
|
||||
g_string_append_printf(keys, "%s,", channel->key == NULL ? "x" :
|
||||
channel->key);
|
||||
g_string_append_printf(keys, "%s,", channel->key == NULL ? "x" : channel->key);
|
||||
if (channel->key != NULL)
|
||||
use_keys = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* get also the channels that are in rejoin list */
|
||||
for (tmp = server->rejoin_channels; tmp != NULL; tmp = tmp->next) {
|
||||
REJOIN_REC *rec = tmp->data;
|
||||
CHANNEL_SETUP_REC *setup = channel_setup_find(rec->channel, server->tag);
|
||||
|
||||
if ((setup != NULL && setup->autojoin && g_ascii_strcasecmp(rejoin_channels_mode, "auto") == 0) ||
|
||||
g_ascii_strcasecmp(rejoin_channels_mode, "on") == 0) {
|
||||
g_string_append_printf(chans, "%s,", rec->channel);
|
||||
g_string_append_printf(keys, "%s,", rec->key == NULL ? "x" :
|
||||
rec->key);
|
||||
|
||||
if (rec->key != NULL) use_keys = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (chans->len > 0) {
|
||||
g_string_truncate(chans, chans->len-1);
|
||||
|
|
@ -639,6 +681,7 @@ char *irc_server_get_channels(IRC_SERVER_REC *server)
|
|||
ret = chans->str;
|
||||
g_string_free(chans, FALSE);
|
||||
g_string_free(keys, TRUE);
|
||||
g_free(rejoin_channels_mode);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -984,6 +1027,7 @@ void irc_server_init_isupport(IRC_SERVER_REC *server)
|
|||
|
||||
void irc_servers_init(void)
|
||||
{
|
||||
settings_add_str("servers", "rejoin_channels_on_reconnect", "on");
|
||||
settings_add_str("misc", "usermode", DEFAULT_USER_MODE);
|
||||
settings_add_str("misc", "split_line_start", "");
|
||||
settings_add_str("misc", "split_line_end", "");
|
||||
|
|
|
|||
|
|
@ -27,6 +27,10 @@ struct _IRC_SERVER_CONNECT_REC {
|
|||
char *usermode;
|
||||
char *alternate_nick;
|
||||
|
||||
int sasl_mechanism;
|
||||
char *sasl_username;
|
||||
char *sasl_password;
|
||||
|
||||
int max_cmds_at_once;
|
||||
int cmd_queue_speed;
|
||||
int max_query_chans;
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@
|
|||
#include "irc-channels.h"
|
||||
#include "irc-nicklist.h"
|
||||
|
||||
#include "sasl.h"
|
||||
|
||||
struct _isupport_data { CONFIG_REC *config; CONFIG_NODE *node; };
|
||||
|
||||
static void session_isupport_foreach(char *key, char *value, struct _isupport_data *data)
|
||||
|
|
@ -65,6 +67,10 @@ static void sig_session_save_server(IRC_SERVER_REC *server, CONFIG_REC *config,
|
|||
config_node_set_str(config, node, "away_reason", server->away_reason);
|
||||
config_node_set_bool(config, node, "emode_known", server->emode_known);
|
||||
|
||||
config_node_set_int(config, node, "sasl_mechanism", server->connrec->sasl_mechanism);
|
||||
config_node_set_str(config, node, "sasl_username", server->connrec->sasl_username);
|
||||
config_node_set_str(config, node, "sasl_password", server->connrec->sasl_password);
|
||||
|
||||
config_node_set_bool(config, node, "isupport_sent", server->isupport_sent);
|
||||
isupport = config_node_section(config, node, "isupport", NODE_TYPE_BLOCK);
|
||||
isupport_data.config = config;
|
||||
|
|
@ -90,6 +96,15 @@ static void sig_session_restore_server(IRC_SERVER_REC *server,
|
|||
server->emode_known = config_node_get_bool(node, "emode_known", FALSE);
|
||||
server->isupport_sent = config_node_get_bool(node, "isupport_sent", FALSE);
|
||||
|
||||
server->connrec->sasl_mechanism = config_node_get_int(node, "sasl_mechanism", SASL_MECHANISM_NONE);
|
||||
/* The fields below might have been filled when loading the chatnet
|
||||
* description from the config and we favor the content that's been saved
|
||||
* in the session file over that. */
|
||||
g_free(server->connrec->sasl_username);
|
||||
server->connrec->sasl_username = g_strdup(config_node_get_str(node, "sasl_username", NULL));
|
||||
g_free(server->connrec->sasl_password);
|
||||
server->connrec->sasl_password = g_strdup(config_node_get_str(node, "sasl_password", NULL));
|
||||
|
||||
if (server->isupport == NULL) {
|
||||
server->isupport = g_hash_table_new((GHashFunc) g_istr_hash,
|
||||
(GCompareFunc) g_istr_equal);
|
||||
|
|
|
|||
|
|
@ -212,8 +212,12 @@ void irc_send_cmd_split(IRC_SERVER_REC *server, const char *cmd,
|
|||
count = 0;
|
||||
if (nickstr->len > 0)
|
||||
g_string_truncate(nickstr, nickstr->len-1);
|
||||
irc_send_cmdv(server, post == NULL ? "%s %s" : "%s %s %s",
|
||||
pre, nickstr->str, post);
|
||||
|
||||
if (post == NULL)
|
||||
irc_send_cmdv(server, "%s %s", pre, nickstr->str);
|
||||
else
|
||||
irc_send_cmdv(server, "%s %s %s", pre, nickstr->str, post);
|
||||
|
||||
g_string_truncate(nickstr, 0);
|
||||
|
||||
if (*tmp == NULL || tmp[1] == NULL)
|
||||
|
|
|
|||
|
|
@ -22,12 +22,6 @@ typedef struct _REDIRECT_REC REDIRECT_REC;
|
|||
#define isnickflag(server, a) \
|
||||
(server->prefix[(int)(unsigned char) a] != '\0')
|
||||
|
||||
#define ischannel(a) \
|
||||
((a) == '#' || /* normal */ \
|
||||
(a) == '&' || /* local */ \
|
||||
(a) == '!' || /* secure */ \
|
||||
(a) == '+') /* modeless */
|
||||
|
||||
#define IS_IRC_ITEM(rec) (IS_IRC_CHANNEL(rec) || IS_IRC_QUERY(rec))
|
||||
#define IRC_PROTOCOL (chat_protocol_lookup("IRC"))
|
||||
|
||||
|
|
|
|||
|
|
@ -488,7 +488,7 @@ static void event_mode(IRC_SERVER_REC *server, const char *data,
|
|||
params = event_get_params(data, 2 | PARAM_FLAG_GETREST,
|
||||
&channel, &mode);
|
||||
|
||||
if (!ischannel(*channel)) {
|
||||
if (!server_ischannel(SERVER(server), channel)) {
|
||||
/* user mode change */
|
||||
parse_user_mode(server, mode);
|
||||
} else {
|
||||
|
|
@ -536,7 +536,7 @@ static void sig_req_usermode_change(IRC_SERVER_REC *server, const char *data,
|
|||
|
||||
params = event_get_params(data, 2 | PARAM_FLAG_GETREST,
|
||||
&target, &mode);
|
||||
if (!ischannel(*target)) {
|
||||
if (!server_ischannel(SERVER(server), target)) {
|
||||
/* we requested a user mode change, save this */
|
||||
mode = modes_join(NULL, server->wanted_usermode, mode, FALSE);
|
||||
g_free_not_null(server->wanted_usermode);
|
||||
|
|
@ -856,7 +856,7 @@ static void cmd_mode(const char *data, IRC_SERVER_REC *server,
|
|||
target = chanrec->name;
|
||||
|
||||
irc_send_cmdv(server, "MODE %s", target);
|
||||
} else if (ischannel(*target))
|
||||
} else if (server_ischannel(SERVER(server), target))
|
||||
channel_set_mode(server, target, mode);
|
||||
else {
|
||||
if (g_ascii_strcasecmp(target, server->nick) == 0) {
|
||||
|
|
|
|||
178
src/irc/core/sasl.c
Normal file
178
src/irc/core/sasl.c
Normal file
|
|
@ -0,0 +1,178 @@
|
|||
/*
|
||||
fe-sasl.c : irssi
|
||||
|
||||
Copyright (C) 2015 The Lemon Man
|
||||
|
||||
This program 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "module.h"
|
||||
#include "misc.h"
|
||||
#include "settings.h"
|
||||
|
||||
#include "irc-cap.h"
|
||||
#include "irc-servers.h"
|
||||
#include "sasl.h"
|
||||
|
||||
#define SASL_TIMEOUT (20 * 1000) // ms
|
||||
|
||||
static gboolean sasl_timeout(IRC_SERVER_REC *server)
|
||||
{
|
||||
/* The authentication timed out, we can't do much beside terminating it */
|
||||
irc_send_cmd_now(server, "AUTHENTICATE *");
|
||||
cap_finish_negotiation(server);
|
||||
|
||||
server->sasl_timeout = -1;
|
||||
|
||||
signal_emit("server sasl failure", 2, server, "The authentication timed out");
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void sasl_start(IRC_SERVER_REC *server, const char *data, const char *from)
|
||||
{
|
||||
IRC_SERVER_CONNECT_REC *conn;
|
||||
|
||||
conn = server->connrec;
|
||||
|
||||
switch (conn->sasl_mechanism) {
|
||||
case SASL_MECHANISM_PLAIN:
|
||||
irc_send_cmd_now(server, "AUTHENTICATE PLAIN");
|
||||
break;
|
||||
|
||||
case SASL_MECHANISM_EXTERNAL:
|
||||
irc_send_cmd_now(server, "AUTHENTICATE EXTERNAL");
|
||||
break;
|
||||
}
|
||||
server->sasl_timeout = g_timeout_add(SASL_TIMEOUT, (GSourceFunc) sasl_timeout, server);
|
||||
}
|
||||
|
||||
static void sasl_fail(IRC_SERVER_REC *server, const char *data, const char *from)
|
||||
{
|
||||
char *params, *error;
|
||||
|
||||
/* Stop any pending timeout, if any */
|
||||
if (server->sasl_timeout != -1) {
|
||||
g_source_remove(server->sasl_timeout);
|
||||
server->sasl_timeout = -1;
|
||||
}
|
||||
|
||||
params = event_get_params(data, 2, NULL, &error);
|
||||
|
||||
signal_emit("server sasl fail", 2, server, error);
|
||||
|
||||
/* Terminate the negotiation */
|
||||
cap_finish_negotiation(server);
|
||||
|
||||
g_free(params);
|
||||
}
|
||||
|
||||
static void sasl_already(IRC_SERVER_REC *server, const char *data, const char *from)
|
||||
{
|
||||
if (server->sasl_timeout != -1) {
|
||||
g_source_remove(server->sasl_timeout);
|
||||
server->sasl_timeout = -1;
|
||||
}
|
||||
|
||||
signal_emit("server sasl success", 1, server);
|
||||
|
||||
/* We're already authenticated, do nothing */
|
||||
cap_finish_negotiation(server);
|
||||
}
|
||||
|
||||
static void sasl_success(IRC_SERVER_REC *server, const char *data, const char *from)
|
||||
{
|
||||
if (server->sasl_timeout != -1) {
|
||||
g_source_remove(server->sasl_timeout);
|
||||
server->sasl_timeout = -1;
|
||||
}
|
||||
|
||||
signal_emit("server sasl success", 1, server);
|
||||
|
||||
/* The authentication succeeded, time to finish the CAP negotiation */
|
||||
cap_finish_negotiation(server);
|
||||
}
|
||||
|
||||
static void sasl_step(IRC_SERVER_REC *server, const char *data, const char *from)
|
||||
{
|
||||
IRC_SERVER_CONNECT_REC *conn;
|
||||
GString *req;
|
||||
char *enc_req;
|
||||
|
||||
conn = server->connrec;
|
||||
|
||||
/* Stop the timer */
|
||||
if (server->sasl_timeout != -1) {
|
||||
g_source_remove(server->sasl_timeout);
|
||||
server->sasl_timeout = -1;
|
||||
}
|
||||
|
||||
switch (conn->sasl_mechanism) {
|
||||
case SASL_MECHANISM_PLAIN:
|
||||
/* At this point we assume that conn->sasl_{username, password} are non-NULL.
|
||||
* The PLAIN mechanism expects a NULL-separated string composed by the authorization identity, the
|
||||
* authentication identity and the password.
|
||||
* The authorization identity field is explicitly set to the user provided username.
|
||||
* The whole request is then encoded in base64. */
|
||||
|
||||
req = g_string_new(NULL);
|
||||
|
||||
g_string_append(req, conn->sasl_username);
|
||||
g_string_append_c(req, '\0');
|
||||
g_string_append(req, conn->sasl_username);
|
||||
g_string_append_c(req, '\0');
|
||||
g_string_append(req, conn->sasl_password);
|
||||
|
||||
enc_req = g_base64_encode((const guchar *)req->str, req->len);
|
||||
|
||||
irc_send_cmdv(server, "AUTHENTICATE %s", enc_req);
|
||||
|
||||
g_free(enc_req);
|
||||
g_string_free(req, TRUE);
|
||||
break;
|
||||
|
||||
case SASL_MECHANISM_EXTERNAL:
|
||||
/* Empty response */
|
||||
irc_send_cmdv(server, "+");
|
||||
break;
|
||||
}
|
||||
|
||||
/* We expect a response within a reasonable time */
|
||||
server->sasl_timeout = g_timeout_add(SASL_TIMEOUT, (GSourceFunc) sasl_timeout, server);
|
||||
}
|
||||
|
||||
void sasl_init(void)
|
||||
{
|
||||
signal_add_first("server cap ack sasl", (SIGNAL_FUNC) sasl_start);
|
||||
signal_add_first("event authenticate", (SIGNAL_FUNC) sasl_step);
|
||||
signal_add_first("event 903", (SIGNAL_FUNC) sasl_success);
|
||||
signal_add_first("event 902", (SIGNAL_FUNC) sasl_fail);
|
||||
signal_add_first("event 904", (SIGNAL_FUNC) sasl_fail);
|
||||
signal_add_first("event 905", (SIGNAL_FUNC) sasl_fail);
|
||||
signal_add_first("event 906", (SIGNAL_FUNC) sasl_fail);
|
||||
signal_add_first("event 907", (SIGNAL_FUNC) sasl_already);
|
||||
}
|
||||
|
||||
void sasl_deinit(void)
|
||||
{
|
||||
signal_remove("server cap ack sasl", (SIGNAL_FUNC) sasl_start);
|
||||
signal_remove("event authenticate", (SIGNAL_FUNC) sasl_step);
|
||||
signal_remove("event 903", (SIGNAL_FUNC) sasl_success);
|
||||
signal_remove("event 902", (SIGNAL_FUNC) sasl_fail);
|
||||
signal_remove("event 904", (SIGNAL_FUNC) sasl_fail);
|
||||
signal_remove("event 905", (SIGNAL_FUNC) sasl_fail);
|
||||
signal_remove("event 906", (SIGNAL_FUNC) sasl_fail);
|
||||
signal_remove("event 907", (SIGNAL_FUNC) sasl_already);
|
||||
}
|
||||
34
src/irc/core/sasl.h
Normal file
34
src/irc/core/sasl.h
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
fe-sasl.c : irssi
|
||||
|
||||
Copyright (C) 2015 The Lemon Man
|
||||
|
||||
This program 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef __SASL_H
|
||||
#define __SASL_H
|
||||
|
||||
enum {
|
||||
SASL_MECHANISM_NONE = 0,
|
||||
SASL_MECHANISM_PLAIN,
|
||||
SASL_MECHANISM_EXTERNAL,
|
||||
SASL_MECHANISM_MAX
|
||||
};
|
||||
|
||||
void sasl_init(void);
|
||||
void sasl_deinit(void);
|
||||
|
||||
#endif
|
||||
|
|
@ -433,9 +433,11 @@ static void redirect_abort(IRC_SERVER_REC *server, REDIRECT_REC *rec)
|
|||
|
||||
if (rec->aborted || !rec->destroyed) {
|
||||
/* emit the failure signal */
|
||||
str = g_strdup_printf(rec->failure_signal != NULL ?
|
||||
"FAILED %s: %s" : "FAILED %s",
|
||||
rec->cmd->name, rec->failure_signal);
|
||||
if (rec->failure_signal != NULL)
|
||||
str = g_strdup_printf("FAILED %s: %s", rec->cmd->name, rec->failure_signal);
|
||||
else
|
||||
str = g_strdup_printf("FAILED %s", rec->cmd->name);
|
||||
|
||||
rawlog_redirect(server->rawlog, str);
|
||||
g_free(str);
|
||||
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ static void sig_dcc_request(GET_DCC_REC *dcc, const char *nickaddr)
|
|||
|
||||
/* Unless specifically said in dcc_autoget_masks, don't do autogets
|
||||
sent to channels. */
|
||||
if (*masks == '\0' && dcc->target != NULL && ischannel(*dcc->target))
|
||||
if (*masks == '\0' && dcc->target != NULL && server_ischannel(SERVER(dcc->server), dcc->target))
|
||||
return;
|
||||
|
||||
/* don't autoget files beginning with a dot, if download dir is
|
||||
|
|
|
|||
|
|
@ -226,6 +226,8 @@ void sig_dccget_connected(GET_DCC_REC *dcc)
|
|||
else
|
||||
ret = fchmod(temphandle, dcc_file_create_mode);
|
||||
|
||||
close(temphandle);
|
||||
|
||||
if (ret != -1) {
|
||||
ret = link(tempfname, dcc->file);
|
||||
|
||||
|
|
@ -249,7 +251,6 @@ void sig_dccget_connected(GET_DCC_REC *dcc)
|
|||
|
||||
/* close/remove the temp file */
|
||||
ret_errno = errno;
|
||||
close(temphandle);
|
||||
unlink(tempfname);
|
||||
g_free(tempfname);
|
||||
|
||||
|
|
|
|||
|
|
@ -250,7 +250,7 @@ static void flood_privmsg(IRC_SERVER_REC *server, const char *data,
|
|||
|
||||
params = event_get_params(data, 2, &target, &text);
|
||||
|
||||
level = ischannel(*target) ? MSGLEVEL_PUBLIC : MSGLEVEL_MSGS;
|
||||
level = server_ischannel(SERVER(server), target) ? MSGLEVEL_PUBLIC : MSGLEVEL_MSGS;
|
||||
if (addr != NULL && !ignore_check(SERVER(server), nick, addr, target, text, level))
|
||||
flood_newmsg(server, level, nick, addr, target);
|
||||
|
||||
|
|
@ -287,7 +287,7 @@ static void flood_ctcp(IRC_SERVER_REC *server, const char *data,
|
|||
return;
|
||||
|
||||
level = g_ascii_strncasecmp(data, "ACTION ", 7) != 0 ? MSGLEVEL_CTCPS :
|
||||
(ischannel(*target) ? MSGLEVEL_PUBLIC : MSGLEVEL_MSGS);
|
||||
(server_ischannel(SERVER(server), target) ? MSGLEVEL_PUBLIC : MSGLEVEL_MSGS);
|
||||
if (!ignore_check(SERVER(server), nick, addr, target, data, level))
|
||||
flood_newmsg(server, level, nick, addr, target);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -169,7 +169,7 @@ static void dump_join(IRC_CHANNEL_REC *channel, CLIENT_REC *client)
|
|||
NICK_REC *nick = tmp->data;
|
||||
|
||||
if (str->len >= 500) {
|
||||
g_string_append_c(str, '\r\n');
|
||||
g_string_append(str, "\r\n");
|
||||
proxy_outdata(client, "%s", str->str);
|
||||
create_names_start(str, channel, client);
|
||||
first = TRUE;
|
||||
|
|
@ -186,7 +186,7 @@ static void dump_join(IRC_CHANNEL_REC *channel, CLIENT_REC *client)
|
|||
}
|
||||
g_slist_free(nicks);
|
||||
|
||||
g_string_append_c(str, '\r\n');
|
||||
g_string_append(str, "\r\n");
|
||||
proxy_outdata(client, "%s", str->str);
|
||||
g_string_free(str, TRUE);
|
||||
|
||||
|
|
|
|||
|
|
@ -37,6 +37,8 @@ GSList *proxy_clients;
|
|||
static GString *next_line;
|
||||
static int ignore_next;
|
||||
|
||||
static int enabled = FALSE;
|
||||
|
||||
static void remove_client(CLIENT_REC *rec)
|
||||
{
|
||||
g_return_if_fail(rec != NULL);
|
||||
|
|
@ -45,8 +47,8 @@ static void remove_client(CLIENT_REC *rec)
|
|||
rec->listen->clients = g_slist_remove(rec->listen->clients, rec);
|
||||
|
||||
signal_emit("proxy client disconnected", 1, rec);
|
||||
printtext(NULL, NULL, MSGLEVEL_CLIENTNOTICE,
|
||||
"Proxy: Client disconnected from %s", rec->host);
|
||||
printtext(rec->server, NULL, MSGLEVEL_CLIENTNOTICE,
|
||||
"Proxy: Client %s:%d disconnected", rec->host, rec->port);
|
||||
|
||||
g_free(rec->proxy_address);
|
||||
net_sendbuffer_destroy(rec->handle, TRUE);
|
||||
|
|
@ -126,6 +128,10 @@ static void handle_client_connect_cmd(CLIENT_REC *client,
|
|||
/* client didn't send us PASS, kill it */
|
||||
remove_client(client);
|
||||
} else {
|
||||
signal_emit("proxy client connected", 1, client);
|
||||
printtext(client->server, NULL, MSGLEVEL_CLIENTNOTICE,
|
||||
"Proxy: Client %s:%d connected",
|
||||
client->host, client->port);
|
||||
client->connected = TRUE;
|
||||
proxy_dump_data(client);
|
||||
}
|
||||
|
|
@ -262,7 +268,7 @@ static void handle_client_cmd(CLIENT_REC *client, char *cmd, char *args,
|
|||
|
||||
ignore_next = TRUE;
|
||||
if (*msg != '\001' || msg[strlen(msg)-1] != '\001') {
|
||||
signal_emit(ischannel(*target) ?
|
||||
signal_emit(server_ischannel(SERVER(client->server), target) ?
|
||||
"message own_public" : "message own_private", 4,
|
||||
client->server, msg, target, target);
|
||||
} else if (strncmp(msg+1, "ACTION ", 7) == 0) {
|
||||
|
|
@ -347,6 +353,7 @@ static void sig_listen(LISTEN_REC *listen)
|
|||
rec->listen = listen;
|
||||
rec->handle = sendbuf;
|
||||
rec->host = g_strdup(host);
|
||||
rec->port = port;
|
||||
if (g_strcmp0(listen->ircnet, "*") == 0) {
|
||||
rec->proxy_address = g_strdup("irc.proxy");
|
||||
rec->server = servers == NULL ? NULL : IRC_SERVER(servers->data);
|
||||
|
|
@ -361,9 +368,10 @@ static void sig_listen(LISTEN_REC *listen)
|
|||
proxy_clients = g_slist_prepend(proxy_clients, rec);
|
||||
rec->listen->clients = g_slist_prepend(rec->listen->clients, rec);
|
||||
|
||||
signal_emit("proxy client connected", 1, rec);
|
||||
printtext(NULL, NULL, MSGLEVEL_CLIENTNOTICE,
|
||||
"Proxy: Client connected from %s", rec->host);
|
||||
signal_emit("proxy client connecting", 1, rec);
|
||||
printtext(rec->server, NULL, MSGLEVEL_CLIENTNOTICE,
|
||||
"Proxy: New client %s:%d on port %d (%s)",
|
||||
rec->host, rec->port, listen->port, listen->ircnet);
|
||||
}
|
||||
|
||||
static void sig_incoming(IRC_SERVER_REC *server, const char *line)
|
||||
|
|
@ -634,7 +642,8 @@ static void remove_listen(LISTEN_REC *rec)
|
|||
static void read_settings(void)
|
||||
{
|
||||
LISTEN_REC *rec;
|
||||
GSList *remove_listens;
|
||||
GSList *remove_listens = NULL;
|
||||
GSList *add_listens = NULL;
|
||||
char **ports, **tmp, *ircnet, *port;
|
||||
int portnum;
|
||||
|
||||
|
|
@ -653,17 +662,30 @@ static void read_settings(void)
|
|||
continue;
|
||||
|
||||
rec = find_listen(ircnet, portnum);
|
||||
if (rec == NULL)
|
||||
add_listen(ircnet, portnum);
|
||||
else
|
||||
if (rec == NULL) {
|
||||
rec = g_new0(LISTEN_REC, 1);
|
||||
rec->ircnet = ircnet; /* borrow */
|
||||
rec->port = portnum;
|
||||
add_listens = g_slist_prepend(add_listens, rec);
|
||||
} else {
|
||||
/* remove from the list of listens to remove == keep it */
|
||||
remove_listens = g_slist_remove(remove_listens, rec);
|
||||
}
|
||||
g_strfreev(ports);
|
||||
}
|
||||
|
||||
while (remove_listens != NULL) {
|
||||
remove_listen(remove_listens->data);
|
||||
remove_listens = g_slist_remove(remove_listens, remove_listens->data);
|
||||
}
|
||||
|
||||
while (add_listens != NULL) {
|
||||
rec = add_listens->data;
|
||||
add_listen(rec->ircnet, rec->port);
|
||||
g_free(rec);
|
||||
add_listens = g_slist_remove(add_listens, add_listens->data);
|
||||
}
|
||||
|
||||
g_strfreev(ports);
|
||||
}
|
||||
|
||||
static void sig_dump(CLIENT_REC *client, const char *data)
|
||||
|
|
@ -676,6 +698,11 @@ static void sig_dump(CLIENT_REC *client, const char *data)
|
|||
|
||||
void proxy_listen_init(void)
|
||||
{
|
||||
if (enabled) {
|
||||
return;
|
||||
}
|
||||
enabled = TRUE;
|
||||
|
||||
next_line = g_string_new(NULL);
|
||||
|
||||
proxy_clients = NULL;
|
||||
|
|
@ -697,6 +724,11 @@ void proxy_listen_init(void)
|
|||
|
||||
void proxy_listen_deinit(void)
|
||||
{
|
||||
if (!enabled) {
|
||||
return;
|
||||
}
|
||||
enabled = FALSE;
|
||||
|
||||
while (proxy_listens != NULL)
|
||||
remove_listen(proxy_listens->data);
|
||||
g_string_free(next_line, TRUE);
|
||||
|
|
|
|||
|
|
@ -23,11 +23,60 @@
|
|||
#include "settings.h"
|
||||
#include "levels.h"
|
||||
|
||||
#include "fe-common/core/printtext.h"
|
||||
|
||||
/* SYNTAX: IRSSIPROXY STATUS */
|
||||
static void cmd_irssiproxy_status(const char *data, IRC_SERVER_REC *server)
|
||||
{
|
||||
if (!settings_get_bool("irssiproxy")) {
|
||||
printtext(server, NULL, MSGLEVEL_CLIENTNOTICE,
|
||||
"Proxy is currently disabled");
|
||||
return;
|
||||
}
|
||||
|
||||
GSList *tmp;
|
||||
|
||||
printtext(server, NULL, MSGLEVEL_CLIENTNOTICE,
|
||||
"Proxy: Currently connected clients: %d",
|
||||
g_slist_length(proxy_clients));
|
||||
|
||||
for (tmp = proxy_clients; tmp != NULL; tmp = tmp->next) {
|
||||
CLIENT_REC *rec = tmp->data;
|
||||
|
||||
printtext(server, NULL, MSGLEVEL_CLIENTNOTICE,
|
||||
" %s:%d connect%s to %d (%s)",
|
||||
rec->host, rec->port,
|
||||
rec->connected ? "ed" : "ing",
|
||||
rec->listen->port, rec->listen->ircnet);
|
||||
}
|
||||
}
|
||||
|
||||
/* SYNTAX: IRSSIPROXY */
|
||||
static void cmd_irssiproxy(const char *data, IRC_SERVER_REC *server, void *item)
|
||||
{
|
||||
if (*data == '\0') {
|
||||
cmd_irssiproxy_status(data, server);
|
||||
return;
|
||||
}
|
||||
|
||||
command_runsub("irssiproxy", data, server, item);
|
||||
}
|
||||
|
||||
static void irc_proxy_setup_changed(void)
|
||||
{
|
||||
if (settings_get_bool("irssiproxy")) {
|
||||
proxy_listen_init();
|
||||
} else {
|
||||
proxy_listen_deinit();
|
||||
}
|
||||
}
|
||||
|
||||
void irc_proxy_init(void)
|
||||
{
|
||||
settings_add_str("irssiproxy", "irssiproxy_ports", "");
|
||||
settings_add_str("irssiproxy", "irssiproxy_password", "");
|
||||
settings_add_str("irssiproxy", "irssiproxy_bind", "");
|
||||
settings_add_bool("irssiproxy", "irssiproxy", TRUE);
|
||||
|
||||
if (*settings_get_str("irssiproxy_password") == '\0') {
|
||||
/* no password - bad idea! */
|
||||
|
|
@ -43,7 +92,14 @@ void irc_proxy_init(void)
|
|||
"... to set them.");
|
||||
}
|
||||
|
||||
command_bind("irssiproxy", NULL, (SIGNAL_FUNC) cmd_irssiproxy);
|
||||
command_bind("irssiproxy status", NULL, (SIGNAL_FUNC) cmd_irssiproxy_status);
|
||||
|
||||
signal_add_first("setup changed", (SIGNAL_FUNC) irc_proxy_setup_changed);
|
||||
|
||||
if (settings_get_bool("irssiproxy")) {
|
||||
proxy_listen_init();
|
||||
}
|
||||
settings_check();
|
||||
module_register("proxy", "irc");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ typedef struct {
|
|||
|
||||
typedef struct {
|
||||
char *nick, *host;
|
||||
int port;
|
||||
NET_SENDBUF_REC *handle;
|
||||
int recv_tag;
|
||||
char *proxy_address;
|
||||
|
|
|
|||
|
|
@ -149,6 +149,7 @@ static void perl_client_fill_hash(HV *hv, CLIENT_REC *client)
|
|||
{
|
||||
(void) hv_store(hv, "nick", 4, new_pv(client->nick), 0);
|
||||
(void) hv_store(hv, "host", 4, new_pv(client->host), 0);
|
||||
(void) hv_store(hv, "port", 4, newSViv(client->port), 0);
|
||||
(void) hv_store(hv, "proxy_address", 13, new_pv(client->proxy_address), 0);
|
||||
(void) hv_store(hv, "server", 6, iobject_bless(client->server), 0);
|
||||
(void) hv_store(hv, "pass_sent", 9, newSViv(client->pass_sent), 0);
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
# Remember to include the asterisk ('*').
|
||||
$SRC_PATH='src';
|
||||
|
||||
@files = `find src -name '*.c'`;
|
||||
@files = sort `find src -name '*.c'`;
|
||||
|
||||
foreach $file (@files) {
|
||||
open (FILE, "$file");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue