Compare commits
111 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 312d0783cf | |||
| 8564297e2a | |||
| c015835d3a | |||
| 1d14abd875 | |||
| 74bed4bc02 | |||
| 8f229f41e1 | |||
| b4d6decc06 | |||
| 04f87b7587 | |||
| b7dd384048 | |||
| e101afab38 | |||
| 37e9165548 | |||
| 25bb7a978d | |||
| 7d531a9bbf | |||
| 1c009f394a | |||
| 649ea0baf7 | |||
| de942e40ac | |||
| 5d3c2bea95 | |||
| 620418fa3b | |||
| 28e4bc1399 | |||
| a0becea2fc | |||
| 6a72c7382b | |||
| 86d7b7aed5 | |||
| 07201b7bdc | |||
| 2ae916fc1a | |||
| 2ba8908024 | |||
| 4a287a724e | |||
| 87e1236b30 | |||
| 0044672b85 | |||
| e921a619b0 | |||
| 25282cfe23 | |||
| 8187bedcb6 | |||
| 79140c3abc | |||
| 4d11be0b85 | |||
| b746c014aa | |||
| f69edd6606 | |||
| 385de6f4fe | |||
| 0fdffa0e50 | |||
| 36c59ff375 | |||
| 71f3532e04 | |||
| d135728424 | |||
| 2185af0b7d | |||
| f22764ec56 | |||
| 02c7c6dcd6 | |||
| 364eb009ca | |||
| d4cbc576e2 | |||
| 9bb9c9868c | |||
| cd8e3d6d41 | |||
| fa965a85e4 | |||
| 59a4c356dd | |||
| c912726f49 | |||
| fbfe0ba18a | |||
| 5ee210a5b7 | |||
| 5d55d7f6de | |||
| b952fc1f6d | |||
| 89065e4d34 | |||
| bc4b8ee19f | |||
| 281ef2e93e | |||
| 9b22d72fd1 | |||
| f11635ed7f | |||
| a1e47ca4c9 | |||
| 6c7a2ce3c8 | |||
| 153d8c55d9 | |||
| d14bc2df53 | |||
| d8299a1231 | |||
| 465c2e4082 | |||
| 2a97c01215 | |||
| 152ba0847d | |||
| fe88e30bf5 | |||
| a8a852d4b3 | |||
| e41f503202 | |||
| 762aaffecf | |||
| 99ac971b66 | |||
| e75e840346 | |||
| 3d59a94554 | |||
| f42ecedd42 | |||
| 63a7980329 | |||
| bc54bf520d | |||
| 11aaf1b325 | |||
| 5ca07656a1 | |||
| f20c6fb28e | |||
| 1613e75a48 | |||
| abd892cbd7 | |||
| 4ae95be9db | |||
| 328bf9af1e | |||
| ce83f8244c | |||
| 8a8ff11887 | |||
| 131aee6f08 | |||
| 07f6d0b350 | |||
| 1cc8656368 | |||
| 4c81112840 | |||
| 5dda5661ae | |||
| 628facf286 | |||
| 7225b68f74 | |||
| e188de5501 | |||
| cdf6544c94 | |||
| a28528d260 | |||
| 27f185e8aa | |||
| d207c90577 | |||
| 2afc9f99c3 | |||
| 4ab247ead0 | |||
| 1dd464f35c | |||
| 955b3728a3 | |||
| aa77bc41d0 | |||
| 5b208547c4 | |||
| c8890953b3 | |||
| cfc78ffdf0 | |||
| 637a3d2bf7 | |||
| a912b3f28c | |||
| 27cd8b3a63 | |||
| 2bde385dc7 | |||
| 74c9759932 |
@@ -1,3 +1,5 @@
|
|||||||
|
sudo: required
|
||||||
|
dist: trusty
|
||||||
language: c
|
language: c
|
||||||
notifications:
|
notifications:
|
||||||
irc:
|
irc:
|
||||||
@@ -25,15 +27,18 @@ compiler:
|
|||||||
before_install:
|
before_install:
|
||||||
# We need this PPA for a recent version of libedit
|
# We need this PPA for a recent version of libedit
|
||||||
- sudo add-apt-repository ppa:ondrej/php5-5.6 -y
|
- sudo add-apt-repository ppa:ondrej/php5-5.6 -y
|
||||||
|
# We need this PPA for Lua 5.3
|
||||||
|
- sudo add-apt-repository ppa:vbernat/haproxy-1.6 -y
|
||||||
- sudo apt-get update -qq
|
- sudo apt-get update -qq
|
||||||
install:
|
install:
|
||||||
- sudo apt-get install -y help2man libedit-dev expect
|
- sudo apt-get install -y libncursesw5-dev libreadline-dev libedit-dev
|
||||||
|
liblua5.3-dev help2man expect
|
||||||
before_script:
|
before_script:
|
||||||
- mkdir build
|
- mkdir build
|
||||||
- cd build
|
- cd build
|
||||||
script:
|
script:
|
||||||
- cmake .. -DCMAKE_INSTALL_PREFIX=/usr
|
- cmake .. -DCMAKE_INSTALL_PREFIX=/usr
|
||||||
-DWANT_READLINE=$readline -DWANT_LIBEDIT=$libedit
|
-DWANT_READLINE=$readline -DWANT_LIBEDIT=$libedit
|
||||||
- make
|
- make all test
|
||||||
- cpack -G DEB
|
- cpack -G DEB
|
||||||
- ../test
|
- ../test
|
||||||
|
|||||||
100
CMakeLists.txt
100
CMakeLists.txt
@@ -1,5 +1,5 @@
|
|||||||
project (uirc3 C)
|
project (uirc3 C)
|
||||||
cmake_minimum_required (VERSION 2.8.5)
|
cmake_minimum_required (VERSION 2.8.11)
|
||||||
|
|
||||||
# Options
|
# Options
|
||||||
option (WANT_READLINE "Use GNU Readline for the UI (better)" ON)
|
option (WANT_READLINE "Use GNU Readline for the UI (better)" ON)
|
||||||
@@ -14,7 +14,7 @@ endif ("${CMAKE_C_COMPILER_ID}" MATCHES "GNU" OR CMAKE_COMPILER_IS_GNUC)
|
|||||||
# Version
|
# Version
|
||||||
set (project_VERSION_MAJOR "0")
|
set (project_VERSION_MAJOR "0")
|
||||||
set (project_VERSION_MINOR "9")
|
set (project_VERSION_MINOR "9")
|
||||||
set (project_VERSION_PATCH "0")
|
set (project_VERSION_PATCH "2")
|
||||||
|
|
||||||
set (project_VERSION "${project_VERSION_MAJOR}")
|
set (project_VERSION "${project_VERSION_MAJOR}")
|
||||||
set (project_VERSION "${project_VERSION}.${project_VERSION_MINOR}")
|
set (project_VERSION "${project_VERSION}.${project_VERSION_MINOR}")
|
||||||
@@ -27,18 +27,40 @@ pkg_check_modules (libssl REQUIRED libssl libcrypto)
|
|||||||
pkg_check_modules (ncursesw ncursesw)
|
pkg_check_modules (ncursesw ncursesw)
|
||||||
|
|
||||||
if ("${CMAKE_SYSTEM_NAME}" MATCHES "BSD")
|
if ("${CMAKE_SYSTEM_NAME}" MATCHES "BSD")
|
||||||
# iconv() doesn't have to be present in libc
|
include_directories(/usr/local/include)
|
||||||
# FIXME: detect if we need the library independently on the platform
|
link_directories(/usr/local/lib)
|
||||||
list (APPEND project_libraries iconv)
|
# Need this for SIGWINCH in FreeBSD and OpenBSD respectively;
|
||||||
# Need this for SIGWINCH; our POSIX version macros make it undefined
|
# our POSIX version macros make it undefined
|
||||||
add_definitions (-D__BSD_VISIBLE=1)
|
add_definitions (-D__BSD_VISIBLE=1 -D_BSD_SOURCE=1)
|
||||||
endif ("${CMAKE_SYSTEM_NAME}" MATCHES "BSD")
|
endif ("${CMAKE_SYSTEM_NAME}" MATCHES "BSD")
|
||||||
|
|
||||||
|
list (APPEND project_libraries ${libssl_LIBRARIES})
|
||||||
|
include_directories (${libssl_INCLUDE_DIRS})
|
||||||
|
link_directories (${libssl_LIBRARY_DIRS})
|
||||||
|
|
||||||
|
# FIXME: other Lua versions may be acceptable, don't know yet
|
||||||
|
pkg_search_module (lua lua53 lua5.3 lua-5.3 lua>=5.3)
|
||||||
|
option (WITH_LUA "Enable experimental support for Lua plugins" ${lua_FOUND})
|
||||||
|
|
||||||
|
if (WITH_LUA)
|
||||||
|
if (NOT lua_FOUND)
|
||||||
|
message (FATAL_ERROR "Lua library not found")
|
||||||
|
endif (NOT lua_FOUND)
|
||||||
|
|
||||||
|
list (APPEND project_libraries ${lua_LIBRARIES})
|
||||||
|
include_directories (${lua_INCLUDE_DIRS})
|
||||||
|
link_directories (${lua_LIBRARY_DIRS})
|
||||||
|
endif (WITH_LUA)
|
||||||
|
|
||||||
# -lpthread is only there for debugging (gdb & errno)
|
# -lpthread is only there for debugging (gdb & errno)
|
||||||
# -lrt is only for glibc < 2.17
|
# -lrt is only for glibc < 2.17
|
||||||
list (APPEND project_libraries ${libssl_LIBRARIES} rt pthread)
|
# -liconv may or may not be a part of libc
|
||||||
include_directories (${libssl_INCLUDE_DIRS})
|
foreach (extra iconv rt pthread)
|
||||||
link_directories (${libssl_LIBRARY_DIRS})
|
find_library (extra_lib_${extra} ${extra})
|
||||||
|
if (extra_lib_${extra})
|
||||||
|
list (APPEND project_libraries ${extra})
|
||||||
|
endif (extra_lib_${extra})
|
||||||
|
endforeach (extra)
|
||||||
|
|
||||||
if (ncursesw_FOUND)
|
if (ncursesw_FOUND)
|
||||||
list (APPEND project_libraries ${ncursesw_LIBRARIES})
|
list (APPEND project_libraries ${ncursesw_LIBRARIES})
|
||||||
@@ -53,7 +75,13 @@ endif (ncursesw_FOUND)
|
|||||||
if ((WANT_READLINE AND WANT_LIBEDIT) OR (NOT WANT_READLINE AND NOT WANT_LIBEDIT))
|
if ((WANT_READLINE AND WANT_LIBEDIT) OR (NOT WANT_READLINE AND NOT WANT_LIBEDIT))
|
||||||
message (SEND_ERROR "You have to choose either GNU Readline or libedit")
|
message (SEND_ERROR "You have to choose either GNU Readline or libedit")
|
||||||
elseif (WANT_READLINE)
|
elseif (WANT_READLINE)
|
||||||
|
# OpenBSD's default readline is too old
|
||||||
|
if ("${CMAKE_SYSTEM_NAME}" MATCHES "OpenBSD")
|
||||||
|
include_directories (/usr/local/include/ereadline)
|
||||||
|
list (APPEND project_libraries ereadline)
|
||||||
|
else ("${CMAKE_SYSTEM_NAME}" MATCHES "OpenBSD")
|
||||||
list (APPEND project_libraries readline)
|
list (APPEND project_libraries readline)
|
||||||
|
endif ("${CMAKE_SYSTEM_NAME}" MATCHES "OpenBSD")
|
||||||
elseif (WANT_LIBEDIT)
|
elseif (WANT_LIBEDIT)
|
||||||
pkg_check_modules (libedit REQUIRED libedit)
|
pkg_check_modules (libedit REQUIRED libedit)
|
||||||
list (APPEND project_libraries ${libedit_LIBRARIES})
|
list (APPEND project_libraries ${libedit_LIBRARIES})
|
||||||
@@ -61,16 +89,13 @@ elseif (WANT_LIBEDIT)
|
|||||||
endif ((WANT_READLINE AND WANT_LIBEDIT) OR (NOT WANT_READLINE AND NOT WANT_LIBEDIT))
|
endif ((WANT_READLINE AND WANT_LIBEDIT) OR (NOT WANT_READLINE AND NOT WANT_LIBEDIT))
|
||||||
|
|
||||||
# Generate a configuration file
|
# Generate a configuration file
|
||||||
if (WANT_READLINE)
|
set (HAVE_READLINE "${WANT_READLINE}")
|
||||||
set (HAVE_READLINE 1)
|
set (HAVE_EDITLINE "${WANT_LIBEDIT}")
|
||||||
endif (WANT_READLINE)
|
set (HAVE_LUA "${WITH_LUA}")
|
||||||
|
|
||||||
if (WANT_LIBEDIT)
|
|
||||||
set (HAVE_EDITLINE 1)
|
|
||||||
endif (WANT_LIBEDIT)
|
|
||||||
|
|
||||||
include (GNUInstallDirs)
|
include (GNUInstallDirs)
|
||||||
set (plugin_dir ${CMAKE_INSTALL_LIBDIR}/${PROJECT_NAME})
|
# ZyklonB is currently an odd duck but degesch follows normal XDG rules
|
||||||
|
set (zyklonb_plugin_dir ${CMAKE_INSTALL_LIBDIR}/zyklonb/plugins)
|
||||||
configure_file (${PROJECT_SOURCE_DIR}/config.h.in ${PROJECT_BINARY_DIR}/config.h)
|
configure_file (${PROJECT_SOURCE_DIR}/config.h.in ${PROJECT_BINARY_DIR}/config.h)
|
||||||
include_directories (${PROJECT_SOURCE_DIR} ${PROJECT_BINARY_DIR})
|
include_directories (${PROJECT_SOURCE_DIR} ${PROJECT_BINARY_DIR})
|
||||||
|
|
||||||
@@ -97,13 +122,44 @@ target_link_libraries (degesch ${project_libraries})
|
|||||||
add_executable (kike kike.c kike-replies.c ${common_sources} ${common_headers})
|
add_executable (kike kike.c kike-replies.c ${common_sources} ${common_headers})
|
||||||
target_link_libraries (kike ${project_libraries})
|
target_link_libraries (kike ${project_libraries})
|
||||||
|
|
||||||
|
# Tests
|
||||||
|
function (make_tests_for target_name)
|
||||||
|
get_target_property (sources ${target_name} SOURCES)
|
||||||
|
get_target_property (libraries ${target_name} LINK_LIBRARIES)
|
||||||
|
|
||||||
|
set (test test-${target_name})
|
||||||
|
add_executable (${test} ${sources})
|
||||||
|
target_link_libraries (${test} ${libraries})
|
||||||
|
add_test (NAME ${test} COMMAND ${test})
|
||||||
|
set_target_properties (${test} PROPERTIES COMPILE_DEFINITIONS TESTING)
|
||||||
|
endfunction (make_tests_for)
|
||||||
|
|
||||||
|
include (CTest)
|
||||||
|
if (BUILD_TESTING)
|
||||||
|
make_tests_for (degesch)
|
||||||
|
endif (BUILD_TESTING)
|
||||||
|
|
||||||
|
# Various clang-based diagnostics, loads of fake positives and spam
|
||||||
|
file (GLOB clang_tidy_sources *.c)
|
||||||
|
set (clang_tidy_checks misc-* readability-*
|
||||||
|
-readability-braces-around-statements
|
||||||
|
-readability-named-parameter)
|
||||||
|
string (REPLACE ";" "," clang_tidy_checks "${clang_tidy_checks}")
|
||||||
|
|
||||||
|
set (CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||||
|
add_custom_target (clang-tidy
|
||||||
|
COMMAND clang-tidy -p ${PROJECT_BINARY_DIR} -checks=${clang_tidy_checks}
|
||||||
|
${clang_tidy_sources} 1>&2
|
||||||
|
USES_TERMINAL
|
||||||
|
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR})
|
||||||
|
|
||||||
# Installation
|
# Installation
|
||||||
install (TARGETS zyklonb degesch kike DESTINATION ${CMAKE_INSTALL_BINDIR})
|
install (TARGETS zyklonb degesch kike DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||||
install (FILES LICENSE DESTINATION ${CMAKE_INSTALL_DOCDIR})
|
install (FILES LICENSE DESTINATION ${CMAKE_INSTALL_DOCDIR})
|
||||||
|
install (DIRECTORY plugins/zyklonb/
|
||||||
foreach (plugin coin eval script youtube ${plugins})
|
DESTINATION ${zyklonb_plugin_dir} USE_SOURCE_PERMISSIONS)
|
||||||
install (FILES plugins/${plugin} DESTINATION ${plugin_dir})
|
install (DIRECTORY plugins/degesch/
|
||||||
endforeach (plugin)
|
DESTINATION ${CMAKE_INSTALL_DATADIR}/degesch/plugins)
|
||||||
|
|
||||||
# Generate documentation from program help
|
# Generate documentation from program help
|
||||||
find_program (HELP2MAN_EXECUTABLE help2man)
|
find_program (HELP2MAN_EXECUTABLE help2man)
|
||||||
|
|||||||
57
NEWS
Normal file
57
NEWS
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
0.9.2 (2015-12-31)
|
||||||
|
|
||||||
|
* degesch: added rudimentary support for Lua scripting
|
||||||
|
|
||||||
|
* degesch: added detection of pasting, so that it doesn't trigger other
|
||||||
|
keyboard shortcuts, such as for autocomplete
|
||||||
|
|
||||||
|
* degesch: added auto-away capability
|
||||||
|
|
||||||
|
* degesch: added an /oper command
|
||||||
|
|
||||||
|
* degesch: libedit backend works again
|
||||||
|
|
||||||
|
* degesch: added capability to edit the input line using VISUAL/EDITOR
|
||||||
|
|
||||||
|
* degesch: added Meta-Tab to switch to the last used buffer
|
||||||
|
|
||||||
|
* degesch: correctly respond to stopping and resuming (SIGTSTP)
|
||||||
|
|
||||||
|
* degesch: fixed decoding of text formatting
|
||||||
|
|
||||||
|
* degesch: unseen PMs now show up as highlights
|
||||||
|
|
||||||
|
* degesch: various bugfixes
|
||||||
|
|
||||||
|
|
||||||
|
0.9.1 (2015-09-25)
|
||||||
|
|
||||||
|
* All "ssl" options have been renamed to "tls"
|
||||||
|
|
||||||
|
* The project now builds on OpenBSD
|
||||||
|
|
||||||
|
* Pulled in kqueue support
|
||||||
|
|
||||||
|
* degesch: added backlog/scrollback functionality using less(1)
|
||||||
|
|
||||||
|
* degesch: made showing the entire set of channel mode user prefixes optional
|
||||||
|
|
||||||
|
* degesch: nicknames in /names are now ordered
|
||||||
|
|
||||||
|
* degesch: nicknames now use the 256-color terminal palette if available
|
||||||
|
|
||||||
|
* degesch: now we skip entries in the "addresses" list that can't be resolved
|
||||||
|
to an address, along with displaying a more helpful message
|
||||||
|
|
||||||
|
* degesch: joins, parts, nick changes and quits don't count as new buffer
|
||||||
|
activity anymore
|
||||||
|
|
||||||
|
* degesch: added Meta-H to open the full log file
|
||||||
|
|
||||||
|
* degesch: various bugfixes and little improvements
|
||||||
|
|
||||||
|
|
||||||
|
0.9.0 (2015-07-23)
|
||||||
|
|
||||||
|
* Initial release
|
||||||
|
|
||||||
@@ -1,43 +1,54 @@
|
|||||||
uirc3
|
uirc3
|
||||||
=====
|
=====
|
||||||
|
:compact-option:
|
||||||
|
|
||||||
The unethical IRC trinity. This project consists of an experimental IRC client,
|
The unethical IRC trinity. This project consists of an experimental IRC client,
|
||||||
daemon, and bot. It's all you're ever going to need for chatting.
|
daemon, and bot. It's all you're ever going to need for chatting, as long as
|
||||||
|
you can make do with minimalist software.
|
||||||
|
|
||||||
All of them have these potentially interesting properties:
|
All of them have these potentially interesting properties:
|
||||||
|
|
||||||
- full IPv6 support
|
- full IPv6 support
|
||||||
- TLS support, including client certificates
|
- TLS support, including client certificates
|
||||||
- minimal dependencies
|
- minimal dependencies
|
||||||
- very compact and easy to hack on
|
- compact and arguably easy to hack on
|
||||||
- permissive license
|
- permissive license
|
||||||
|
|
||||||
degesch
|
degesch
|
||||||
-------
|
-------
|
||||||
The IRC client. It is largely defined by being built on top of GNU Readline.
|
The IRC client. It is largely defined by being built on top of GNU Readline
|
||||||
Its interface should however feel familiar for weechat or irssi users.
|
that has been hacked to death. Its interface should feel somewhat familiar for
|
||||||
|
weechat or irssi users.
|
||||||
|
|
||||||
This is the youngest and largest application within the project. It has most of
|
This is the largest application within the project. It has most of the stuff
|
||||||
the stuff you'd expect of an IRC client, such as being able to set up multiple
|
you'd expect of an IRC client, such as being able to set up multiple servers,
|
||||||
servers, powerful configuration system, integrated help, mIRC text formatting,
|
a powerful configuration system, integrated help, text formatting, CTCP queries,
|
||||||
CTCP queries, automatic splitting of overlong messages, autocomplete, logging
|
automatic splitting of overlong messages, autocomplete, logging to file,
|
||||||
to file, and command aliases.
|
auto-away, command aliases and rudimentary support for Lua scripting.
|
||||||
|
|
||||||
kike
|
kike
|
||||||
----
|
----
|
||||||
The IRC daemon. It is designed to be used as a regular user application rather
|
The IRC daemon. It is designed to be used as a regular user application rather
|
||||||
than a system-wide daemon. If all you want is a decent, minimal IRCd for
|
than a system-wide daemon. If all you want is a decent, minimal IRCd for
|
||||||
a small network of respectful users (or bots), or testing, this one will do it.
|
testing purposes or a small network of respectful users (or bots), this one will
|
||||||
|
do it just fine.
|
||||||
|
|
||||||
Notable features:
|
Notable features:
|
||||||
- TLS autodetection (why doesn't everyone have this?)
|
|
||||||
- IRCop authentication through TLS client certificates
|
- TLS autodetection (why doesn't everyone have this?), using secure defaults
|
||||||
- epoll support on Linux; it should be able to handle quite a number of users
|
- IRCop authentication via TLS client certificates
|
||||||
|
- epoll/kqueue support; this means that it should be able to handle quite
|
||||||
|
a number of concurrent user connections
|
||||||
- partial IRCv3 support
|
- partial IRCv3 support
|
||||||
|
|
||||||
Not supported:
|
Not supported:
|
||||||
|
|
||||||
- server linking (which also means no services); I consider existing protocols
|
- server linking (which also means no services); I consider existing protocols
|
||||||
for this purpose ugly and tricky to implement correctly
|
for this purpose ugly and tricky to implement correctly; I've also found no
|
||||||
- online changes to configuration; the config system from degesch could be used
|
use for this feature yet
|
||||||
- limits of almost any kind, just connections and mode +l
|
- online changes to configuration; the configuration system from degesch could
|
||||||
|
be used to implement this feature if needed
|
||||||
|
- limits of almost any kind, just connections and mode `+l`
|
||||||
|
|
||||||
ZyklonB
|
ZyklonB
|
||||||
-------
|
-------
|
||||||
@@ -45,64 +56,66 @@ The IRC bot. It builds upon the concept of my other VitaminA IRC bot. The main
|
|||||||
characteristic of these two bots is that they run plugins as coprocesses, which
|
characteristic of these two bots is that they run plugins as coprocesses, which
|
||||||
allows for enhanced reliability and programming language freedom.
|
allows for enhanced reliability and programming language freedom.
|
||||||
|
|
||||||
While originally intended to be a simple C99 rewrite of the original bot, which
|
While originally intended to be a simple rewrite of the original AWK bot in C,
|
||||||
was written in the GNU dialect of AWK, it fairly quickly became a playground
|
it fairly quickly became a playground, and it eventually got me into writing
|
||||||
where I added everything that seemed nice, and it eventually got me into writing
|
the rest of the package.
|
||||||
the rest of this package.
|
|
||||||
|
|
||||||
Notable features:
|
It survives crashes, server disconnects and timeouts, and also has native SOCKS
|
||||||
- resilient against crashes, server disconnects and timeouts
|
support (even though socksify can add that easily to any program).
|
||||||
- SOCKS support (even though socksify can add that easily to any program)
|
|
||||||
|
|
||||||
Building
|
Building
|
||||||
--------
|
--------
|
||||||
Build dependencies: CMake, pkg-config, help2man, awk, sh, liberty (included)
|
Build dependencies: CMake, pkg-config, help2man, awk, sh, liberty (included) +
|
||||||
Runtime dependencies: openssl, curses (degesch),
|
Runtime dependencies: openssl, curses (degesch),
|
||||||
readline or libedit >= 2013-07-12 (degesch)
|
readline >= 6.0 or libedit >= 2013-07-12 (degesch),
|
||||||
|
lua >= 5.3 (degesch, optional)
|
||||||
|
|
||||||
$ git clone https://github.com/pjanouch/uirc3.git
|
$ git clone --recursive https://github.com/pjanouch/uirc3.git
|
||||||
$ git submodule init
|
$ mkdir uirc3/build
|
||||||
$ git submodule update
|
$ cd uirc3/build
|
||||||
$ mkdir build
|
|
||||||
$ cd build
|
|
||||||
$ cmake .. -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Debug \
|
$ cmake .. -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Debug \
|
||||||
-DWANT_READLINE=ON -DWANT_LIBEDIT=OFF
|
-DWANT_READLINE=ON -DWANT_LIBEDIT=OFF -DWANT_LUA=ON
|
||||||
$ make
|
$ make
|
||||||
|
|
||||||
To install the application, you can do either the usual:
|
To install the application, you can do either the usual:
|
||||||
|
|
||||||
# make install
|
# make install
|
||||||
|
|
||||||
Or you can try telling CMake to make a package for you. For Debian it is:
|
Or you can try telling CMake to make a package for you. For Debian it is:
|
||||||
|
|
||||||
$ cpack -G DEB
|
$ cpack -G DEB
|
||||||
# dpkg -i uirc3-*.deb
|
# dpkg -i uirc3-*.deb
|
||||||
|
|
||||||
Note that for versions of CMake before 2.8.9, you need to prefix cpack with
|
Note that for versions of CMake before 2.8.9, you need to prefix `cpack` with
|
||||||
`fakeroot' or file ownership will end up wrong.
|
`fakeroot` or file ownership will end up wrong.
|
||||||
|
|
||||||
Running
|
Running
|
||||||
-------
|
-------
|
||||||
`degesch' has in-program configuration. Just run it and read the instructions.
|
'degesch' has in-program configuration. Just run it and read the instructions.
|
||||||
|
|
||||||
For the rest you might want to generate a configuration file:
|
For the rest you might want to generate a configuration file:
|
||||||
|
|
||||||
$ zyklonb --write-default-config
|
$ zyklonb --write-default-config
|
||||||
$ kike --write-default-config
|
$ kike --write-default-config
|
||||||
|
|
||||||
After making any necessary edits to the file (there are comments to aid you in
|
After making any necessary edits to the file (there are comments to aid you in
|
||||||
doing that), simply run the appropriate program with no arguments:
|
doing that), simply run the appropriate program with no arguments:
|
||||||
|
|
||||||
$ zyklonb
|
$ zyklonb
|
||||||
$ kike
|
$ kike
|
||||||
|
|
||||||
`ZyklonB' stays running in the foreground, therefore I recommend launching it
|
'ZyklonB' stays running in the foreground, therefore I recommend launching it
|
||||||
inside a Screen or tmux session.
|
inside a Screen or tmux session.
|
||||||
|
|
||||||
`kike', on the other hand, immediately forks into the background. Use the PID
|
'kike', on the other hand, immediately forks into the background. Use the PID
|
||||||
file or something like `killall' if you want to terminate it. You can run it
|
file or something like `killall` if you want to terminate it. You can run it
|
||||||
as a `forking' type systemd user service.
|
as a `forking` type systemd user service.
|
||||||
|
|
||||||
Client Certificates
|
Client Certificates
|
||||||
-------------------
|
-------------------
|
||||||
`kike' uses SHA1 fingerprints of TLS client certificates to authenticate users.
|
'kike' uses SHA1 fingerprints of TLS client certificates to authenticate users.
|
||||||
To get the fingerprint from a certificate file in the required form, use:
|
To get the fingerprint from a certificate file in the required form, use:
|
||||||
|
|
||||||
$ openssl x509 -in public.pem -outform DER | sha1sum
|
$ openssl x509 -in public.pem -outform DER | sha1sum
|
||||||
|
|
||||||
Contributing and Support
|
Contributing and Support
|
||||||
@@ -118,7 +131,7 @@ And no, I'm not going to change the names.
|
|||||||
|
|
||||||
License
|
License
|
||||||
-------
|
-------
|
||||||
`uirc3' is written by Přemysl Janouch <p.janouch@gmail.com>.
|
'uirc3' is written by Přemysl Janouch <p.janouch@gmail.com>.
|
||||||
|
|
||||||
You may use the software under the terms of the ISC license, the text of which
|
You may use the software under the terms of the ISC license, the text of which
|
||||||
is included within the package, or, at your option, you may relicense the work
|
is included within the package, or, at your option, you may relicense the work
|
||||||
@@ -2,9 +2,10 @@
|
|||||||
#define CONFIG_H
|
#define CONFIG_H
|
||||||
|
|
||||||
#define PROGRAM_VERSION "${project_VERSION}"
|
#define PROGRAM_VERSION "${project_VERSION}"
|
||||||
#define PLUGIN_DIR "${CMAKE_INSTALL_PREFIX}/${plugin_dir}"
|
#define ZYKLONB_PLUGIN_DIR "${CMAKE_INSTALL_PREFIX}/${zyklonb_plugin_dir}"
|
||||||
|
|
||||||
#cmakedefine HAVE_READLINE
|
#cmakedefine HAVE_READLINE
|
||||||
#cmakedefine HAVE_EDITLINE
|
#cmakedefine HAVE_EDITLINE
|
||||||
|
#cmakedefine HAVE_LUA
|
||||||
|
|
||||||
#endif // ! CONFIG_H
|
#endif // ! CONFIG_H
|
||||||
|
|||||||
61
kike.c
61
kike.c
@@ -34,7 +34,7 @@ enum { PIPE_READ, PIPE_WRITE };
|
|||||||
// Just get rid of the crappiest ciphers available by default
|
// Just get rid of the crappiest ciphers available by default
|
||||||
#define DEFAULT_CIPHERS "DEFAULT:!MEDIUM:!LOW"
|
#define DEFAULT_CIPHERS "DEFAULT:!MEDIUM:!LOW"
|
||||||
|
|
||||||
static struct config_item g_config_table[] =
|
static struct simple_config_item g_config_table[] =
|
||||||
{
|
{
|
||||||
{ "pid_file", NULL, "Path or name of the PID file" },
|
{ "pid_file", NULL, "Path or name of the PID file" },
|
||||||
{ "server_name", NULL, "Server name" },
|
{ "server_name", NULL, "Server name" },
|
||||||
@@ -44,9 +44,9 @@ static struct config_item g_config_table[] =
|
|||||||
|
|
||||||
{ "bind_host", NULL, "Address of the IRC server" },
|
{ "bind_host", NULL, "Address of the IRC server" },
|
||||||
{ "bind_port", "6667", "Port of the IRC server" },
|
{ "bind_port", "6667", "Port of the IRC server" },
|
||||||
{ "ssl_cert", NULL, "Server TLS certificate (PEM)" },
|
{ "tls_cert", NULL, "Server TLS certificate (PEM)" },
|
||||||
{ "ssl_key", NULL, "Server TLS private key (PEM)" },
|
{ "tls_key", NULL, "Server TLS private key (PEM)" },
|
||||||
{ "ssl_ciphers", DEFAULT_CIPHERS, "OpenSSL cipher list" },
|
{ "tls_ciphers", DEFAULT_CIPHERS, "OpenSSL cipher list" },
|
||||||
|
|
||||||
{ "operators", NULL, "IRCop TLS cert. fingerprints" },
|
{ "operators", NULL, "IRCop TLS cert. fingerprints" },
|
||||||
|
|
||||||
@@ -666,7 +666,7 @@ server_context_init (struct server_context *self)
|
|||||||
|
|
||||||
str_map_init (&self->config);
|
str_map_init (&self->config);
|
||||||
self->config.free = free;
|
self->config.free = free;
|
||||||
load_config_defaults (&self->config, g_config_table);
|
simple_config_load_defaults (&self->config, g_config_table);
|
||||||
|
|
||||||
str_vector_init (&self->motd);
|
str_vector_init (&self->motd);
|
||||||
self->catalog = (nl_catd) -1;
|
self->catalog = (nl_catd) -1;
|
||||||
@@ -1784,7 +1784,7 @@ mode_processor_do_user (struct mode_processor *self, int mode)
|
|||||||
target, self->channel->name);
|
target, self->channel->name);
|
||||||
else if (irc_modify_mode (&target_user->modes, mode, self->adding))
|
else if (irc_modify_mode (&target_user->modes, mode, self->adding))
|
||||||
{
|
{
|
||||||
str_append_c (self->output, self->mode_char); \
|
str_append_c (self->output, self->mode_char);
|
||||||
str_vector_add (self->output_params, client->nickname);
|
str_vector_add (self->output_params, client->nickname);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3106,7 +3106,7 @@ irc_try_read (struct client *c)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
irc_try_read_ssl (struct client *c)
|
irc_try_read_tls (struct client *c)
|
||||||
{
|
{
|
||||||
if (c->ssl_tx_want_rx)
|
if (c->ssl_tx_want_rx)
|
||||||
return true;
|
return true;
|
||||||
@@ -3174,7 +3174,7 @@ irc_try_write (struct client *c)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
irc_try_write_ssl (struct client *c)
|
irc_try_write_tls (struct client *c)
|
||||||
{
|
{
|
||||||
if (c->ssl_rx_want_tx)
|
if (c->ssl_rx_want_tx)
|
||||||
return true;
|
return true;
|
||||||
@@ -3212,7 +3212,7 @@ irc_try_write_ssl (struct client *c)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
irc_autodetect_ssl (struct client *c)
|
irc_autodetect_tls (struct client *c)
|
||||||
{
|
{
|
||||||
// Trivial SSL/TLS autodetection. The first block of data returned by
|
// Trivial SSL/TLS autodetection. The first block of data returned by
|
||||||
// recv() must be at least three bytes long for this to work reliably,
|
// recv() must be at least three bytes long for this to work reliably,
|
||||||
@@ -3251,7 +3251,7 @@ start:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
client_initialize_ssl (struct client *c)
|
client_initialize_tls (struct client *c)
|
||||||
{
|
{
|
||||||
const char *error_info = NULL;
|
const char *error_info = NULL;
|
||||||
if (!c->ctx->ssl_ctx)
|
if (!c->ctx->ssl_ctx)
|
||||||
@@ -3288,7 +3288,7 @@ on_client_ready (const struct pollfd *pfd, void *user_data)
|
|||||||
if (!c->initialized)
|
if (!c->initialized)
|
||||||
{
|
{
|
||||||
hard_assert (pfd->events == POLLIN);
|
hard_assert (pfd->events == POLLIN);
|
||||||
if (irc_autodetect_ssl (c) && !client_initialize_ssl (c))
|
if (irc_autodetect_tls (c) && !client_initialize_tls (c))
|
||||||
{
|
{
|
||||||
client_kill (c, NULL);
|
client_kill (c, NULL);
|
||||||
return;
|
return;
|
||||||
@@ -3301,7 +3301,7 @@ on_client_ready (const struct pollfd *pfd, void *user_data)
|
|||||||
{
|
{
|
||||||
// Reads may want to write, writes may want to read, poll() may
|
// Reads may want to write, writes may want to read, poll() may
|
||||||
// return unexpected things in `revents'... let's try both
|
// return unexpected things in `revents'... let's try both
|
||||||
if (!irc_try_read_ssl (c) || !irc_try_write_ssl (c))
|
if (!irc_try_read_tls (c) || !irc_try_write_tls (c))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (!irc_try_read (c) || !irc_try_write (c))
|
else if (!irc_try_read (c) || !irc_try_write (c))
|
||||||
@@ -3421,6 +3421,13 @@ irc_try_fetch_client (struct server_context *ctx, int listen_fd)
|
|||||||
c->ping_timer.dispatcher = on_client_ping_timer;
|
c->ping_timer.dispatcher = on_client_ping_timer;
|
||||||
c->ping_timer.user_data = c;
|
c->ping_timer.user_data = c;
|
||||||
|
|
||||||
|
// A little bit questionable once the traffic gets high enough (IMO),
|
||||||
|
// but it reduces silly latencies that we don't need because we already
|
||||||
|
// do buffer our output
|
||||||
|
int yes = 1;
|
||||||
|
soft_assert (setsockopt (fd, IPPROTO_TCP, TCP_NODELAY,
|
||||||
|
&yes, sizeof yes) != -1);
|
||||||
|
|
||||||
set_blocking (fd, false);
|
set_blocking (fd, false);
|
||||||
client_update_poller (c, NULL);
|
client_update_poller (c, NULL);
|
||||||
client_set_kill_timer (c);
|
client_set_kill_timer (c);
|
||||||
@@ -3510,7 +3517,7 @@ irc_initialize_ssl_ctx (struct server_context *ctx,
|
|||||||
SSL_CTX_set_options (ctx->ssl_ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
|
SSL_CTX_set_options (ctx->ssl_ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
|
||||||
|
|
||||||
// XXX: perhaps we should read the files ourselves for better messages
|
// XXX: perhaps we should read the files ourselves for better messages
|
||||||
const char *ciphers = str_map_find (&ctx->config, "ssl_ciphers");
|
const char *ciphers = str_map_find (&ctx->config, "tls_ciphers");
|
||||||
if (!SSL_CTX_set_cipher_list (ctx->ssl_ctx, ciphers))
|
if (!SSL_CTX_set_cipher_list (ctx->ssl_ctx, ciphers))
|
||||||
error_set (e, "failed to select any cipher from the cipher list");
|
error_set (e, "failed to select any cipher from the cipher list");
|
||||||
else if (!SSL_CTX_use_certificate_chain_file (ctx->ssl_ctx, cert_path))
|
else if (!SSL_CTX_use_certificate_chain_file (ctx->ssl_ctx, cert_path))
|
||||||
@@ -3531,33 +3538,33 @@ irc_initialize_ssl_ctx (struct server_context *ctx,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
irc_initialize_ssl (struct server_context *ctx, struct error **e)
|
irc_initialize_tls (struct server_context *ctx, struct error **e)
|
||||||
{
|
{
|
||||||
const char *ssl_cert = str_map_find (&ctx->config, "ssl_cert");
|
const char *tls_cert = str_map_find (&ctx->config, "tls_cert");
|
||||||
const char *ssl_key = str_map_find (&ctx->config, "ssl_key");
|
const char *tls_key = str_map_find (&ctx->config, "tls_key");
|
||||||
|
|
||||||
// Only try to enable SSL support if the user configures it; it is not
|
// Only try to enable SSL support if the user configures it; it is not
|
||||||
// a failure if no one has requested it.
|
// a failure if no one has requested it.
|
||||||
if (!ssl_cert && !ssl_key)
|
if (!tls_cert && !tls_key)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (!ssl_cert)
|
if (!tls_cert)
|
||||||
error_set (e, "no TLS certificate set");
|
error_set (e, "no TLS certificate set");
|
||||||
else if (!ssl_key)
|
else if (!tls_key)
|
||||||
error_set (e, "no TLS private key set");
|
error_set (e, "no TLS private key set");
|
||||||
if (!ssl_cert || !ssl_key)
|
if (!tls_cert || !tls_key)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
bool result = false;
|
bool result = false;
|
||||||
|
|
||||||
char *cert_path = resolve_filename
|
char *cert_path = resolve_filename
|
||||||
(ssl_cert, resolve_relative_config_filename);
|
(tls_cert, resolve_relative_config_filename);
|
||||||
char *key_path = resolve_filename
|
char *key_path = resolve_filename
|
||||||
(ssl_key, resolve_relative_config_filename);
|
(tls_key, resolve_relative_config_filename);
|
||||||
if (!cert_path)
|
if (!cert_path)
|
||||||
error_set (e, "%s: %s", "cannot open file", ssl_cert);
|
error_set (e, "%s: %s", "cannot open file", tls_cert);
|
||||||
else if (!key_path)
|
else if (!key_path)
|
||||||
error_set (e, "%s: %s", "cannot open file", ssl_key);
|
error_set (e, "%s: %s", "cannot open file", tls_key);
|
||||||
else
|
else
|
||||||
result = irc_initialize_ssl_ctx (ctx, cert_path, key_path, e);
|
result = irc_initialize_ssl_ctx (ctx, cert_path, key_path, e);
|
||||||
|
|
||||||
@@ -3982,7 +3989,7 @@ main (int argc, char *argv[])
|
|||||||
printf (PROGRAM_NAME " " PROGRAM_VERSION "\n");
|
printf (PROGRAM_NAME " " PROGRAM_VERSION "\n");
|
||||||
exit (EXIT_SUCCESS);
|
exit (EXIT_SUCCESS);
|
||||||
case 'w':
|
case 'w':
|
||||||
call_write_default_config (optarg, g_config_table);
|
call_simple_config_write_default (optarg, g_config_table);
|
||||||
exit (EXIT_SUCCESS);
|
exit (EXIT_SUCCESS);
|
||||||
default:
|
default:
|
||||||
print_error ("wrong options");
|
print_error ("wrong options");
|
||||||
@@ -4007,7 +4014,7 @@ main (int argc, char *argv[])
|
|||||||
irc_register_cap_handlers (&ctx);
|
irc_register_cap_handlers (&ctx);
|
||||||
|
|
||||||
struct error *e = NULL;
|
struct error *e = NULL;
|
||||||
if (!read_config_file (&ctx.config, &e))
|
if (!simple_config_update_from_file (&ctx.config, &e))
|
||||||
{
|
{
|
||||||
print_error ("error loading configuration: %s", e->message);
|
print_error ("error loading configuration: %s", e->message);
|
||||||
error_free (e);
|
error_free (e);
|
||||||
@@ -4019,7 +4026,7 @@ main (int argc, char *argv[])
|
|||||||
ctx.signal_event.user_data = &ctx;
|
ctx.signal_event.user_data = &ctx;
|
||||||
poller_fd_set (&ctx.signal_event, POLLIN);
|
poller_fd_set (&ctx.signal_event, POLLIN);
|
||||||
|
|
||||||
if (!irc_initialize_ssl (&ctx, &e)
|
if (!irc_initialize_tls (&ctx, &e)
|
||||||
|| !irc_initialize_server_name (&ctx, &e)
|
|| !irc_initialize_server_name (&ctx, &e)
|
||||||
|| !irc_initialize_motd (&ctx, &e)
|
|| !irc_initialize_motd (&ctx, &e)
|
||||||
|| !irc_initialize_catalog (&ctx, &e)
|
|| !irc_initialize_catalog (&ctx, &e)
|
||||||
|
|||||||
2
liberty
2
liberty
Submodule liberty updated: 02708608a9...f6d74544f8
33
plugins/degesch/ping-timeout.lua
Normal file
33
plugins/degesch/ping-timeout.lua
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
--
|
||||||
|
-- ping-timeout.lua: ping timeout readability enhancement plugin
|
||||||
|
--
|
||||||
|
-- Copyright (c) 2015, Přemysl Janouch <p.janouch@gmail.com>
|
||||||
|
--
|
||||||
|
-- Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
-- purpose with or without fee is hereby granted, provided that the above
|
||||||
|
-- copyright notice and this permission notice appear in all copies.
|
||||||
|
--
|
||||||
|
-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
-- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
-- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||||
|
-- SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
-- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||||
|
-- OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||||
|
-- CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
--
|
||||||
|
|
||||||
|
degesch.hook_irc (function (hook, server, line)
|
||||||
|
local start, timeout =
|
||||||
|
line:match ("^(:[^ ]* QUIT :Ping timeout:) (%d+) seconds$")
|
||||||
|
if not start then
|
||||||
|
return line
|
||||||
|
end
|
||||||
|
|
||||||
|
local minutes = timeout // 60
|
||||||
|
if minutes == 0 then
|
||||||
|
return line
|
||||||
|
end
|
||||||
|
|
||||||
|
local seconds = timeout % 60
|
||||||
|
return ("%s %d minutes, %d seconds"):format (start, minutes, seconds)
|
||||||
|
end)
|
||||||
63
plugins/degesch/utm-filter.lua
Normal file
63
plugins/degesch/utm-filter.lua
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
--
|
||||||
|
-- utm-filter.lua: filter out Google Analytics bullshit from URLs
|
||||||
|
--
|
||||||
|
-- Copyright (c) 2015, Přemysl Janouch <p.janouch@gmail.com>
|
||||||
|
--
|
||||||
|
-- Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
-- purpose with or without fee is hereby granted, provided that the above
|
||||||
|
-- copyright notice and this permission notice appear in all copies.
|
||||||
|
--
|
||||||
|
-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
-- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
-- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||||
|
-- SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
-- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||||
|
-- OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||||
|
-- CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
--
|
||||||
|
|
||||||
|
-- A list of useless URL parameters that don't affect page function
|
||||||
|
local banned = {
|
||||||
|
gclid = 1,
|
||||||
|
|
||||||
|
utm_source = 1,
|
||||||
|
utm_medium = 1,
|
||||||
|
utm_term = 1,
|
||||||
|
utm_content = 1,
|
||||||
|
utm_campaign = 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Go through a parameter list and throw out any banned elements
|
||||||
|
local do_args = function (args)
|
||||||
|
local filtered = {}
|
||||||
|
for part in args:gmatch ("[^&]+") do
|
||||||
|
if not banned[part:match ("^[^=]*")] then
|
||||||
|
table.insert (filtered, part)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return table.concat (filtered, "&")
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Filter parameters in both the query and the fragment part of an URL
|
||||||
|
local do_single_url = function (url)
|
||||||
|
return url:gsub ('^([^?#]*)%?([^#]*)', function (start, query)
|
||||||
|
local clean = do_args (query)
|
||||||
|
return #clean > 0 and start .. "?" .. clean or start
|
||||||
|
end, 1):gsub ('^([^#]*)#(.*)', function (start, fragment)
|
||||||
|
local clean = do_args (fragment)
|
||||||
|
return #clean > 0 and start .. "#" .. clean or start
|
||||||
|
end, 1)
|
||||||
|
end
|
||||||
|
|
||||||
|
local do_text = function (text)
|
||||||
|
return text:gsub ('%f[%g]https?://%g+', do_single_url)
|
||||||
|
end
|
||||||
|
|
||||||
|
degesch.hook_irc (function (hook, server, line)
|
||||||
|
local start, message = line:match ("^(.* :)(.*)$")
|
||||||
|
return message and start .. do_text (message) or line
|
||||||
|
end)
|
||||||
|
|
||||||
|
degesch.hook_input (function (hook, buffer, input)
|
||||||
|
return do_text (input)
|
||||||
|
end)
|
||||||
45
zyklonb.c
45
zyklonb.c
@@ -19,12 +19,13 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#define PROGRAM_NAME "ZyklonB"
|
#define PROGRAM_NAME "ZyklonB"
|
||||||
|
#define PLUGIN_DIR ZYKLONB_PLUGIN_DIR
|
||||||
|
|
||||||
#include "common.c"
|
#include "common.c"
|
||||||
|
|
||||||
// --- Configuration (application-specific) ------------------------------------
|
// --- Configuration (application-specific) ------------------------------------
|
||||||
|
|
||||||
static struct config_item g_config_table[] =
|
static struct simple_config_item g_config_table[] =
|
||||||
{
|
{
|
||||||
{ "nickname", "ZyklonB", "IRC nickname" },
|
{ "nickname", "ZyklonB", "IRC nickname" },
|
||||||
{ "username", "bot", "IRC user name" },
|
{ "username", "bot", "IRC user name" },
|
||||||
@@ -32,11 +33,11 @@ static struct config_item g_config_table[] =
|
|||||||
|
|
||||||
{ "irc_host", NULL, "Address of the IRC server" },
|
{ "irc_host", NULL, "Address of the IRC server" },
|
||||||
{ "irc_port", "6667", "Port of the IRC server" },
|
{ "irc_port", "6667", "Port of the IRC server" },
|
||||||
{ "ssl", "off", "Whether to use SSL" },
|
{ "tls", "off", "Whether to use TLS" },
|
||||||
{ "ssl_cert", NULL, "Client SSL certificate (PEM)" },
|
{ "tls_cert", NULL, "Client TLS certificate (PEM)" },
|
||||||
{ "ssl_verify", "on", "Whether to verify certificates" },
|
{ "tls_verify", "on", "Whether to verify certificates" },
|
||||||
{ "ssl_ca_file", NULL, "OpenSSL CA bundle file" },
|
{ "tls_ca_file", NULL, "OpenSSL CA bundle file" },
|
||||||
{ "ssl_ca_path", NULL, "OpenSSL CA bundle path" },
|
{ "tls_ca_path", NULL, "OpenSSL CA bundle path" },
|
||||||
{ "autojoin", NULL, "Channels to join on start" },
|
{ "autojoin", NULL, "Channels to join on start" },
|
||||||
{ "reconnect", "on", "Whether to reconnect on error" },
|
{ "reconnect", "on", "Whether to reconnect on error" },
|
||||||
{ "reconnect_delay", "5", "Time between reconnecting" },
|
{ "reconnect_delay", "5", "Time between reconnecting" },
|
||||||
@@ -153,7 +154,7 @@ bot_context_init (struct bot_context *self)
|
|||||||
{
|
{
|
||||||
str_map_init (&self->config);
|
str_map_init (&self->config);
|
||||||
self->config.free = free;
|
self->config.free = free;
|
||||||
load_config_defaults (&self->config, g_config_table);
|
simple_config_load_defaults (&self->config, g_config_table);
|
||||||
self->admin_re = NULL;
|
self->admin_re = NULL;
|
||||||
|
|
||||||
self->irc_fd = -1;
|
self->irc_fd = -1;
|
||||||
@@ -320,7 +321,7 @@ irc_initialize_ssl_ctx (struct bot_context *ctx, struct error **e)
|
|||||||
SSL_CTX_set_options (ctx->ssl_ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
|
SSL_CTX_set_options (ctx->ssl_ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
|
||||||
|
|
||||||
bool verify;
|
bool verify;
|
||||||
if (!irc_get_boolean_from_config (ctx, "ssl_verify", &verify, e))
|
if (!irc_get_boolean_from_config (ctx, "tls_verify", &verify, e))
|
||||||
return false;
|
return false;
|
||||||
SSL_CTX_set_verify (ctx->ssl_ctx,
|
SSL_CTX_set_verify (ctx->ssl_ctx,
|
||||||
verify ? SSL_VERIFY_PEER : SSL_VERIFY_NONE, NULL);
|
verify ? SSL_VERIFY_PEER : SSL_VERIFY_NONE, NULL);
|
||||||
@@ -363,7 +364,7 @@ ca_error:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
irc_initialize_ssl (struct bot_context *ctx, struct error **e)
|
irc_initialize_tls (struct bot_context *ctx, struct error **e)
|
||||||
{
|
{
|
||||||
const char *error_info = NULL;
|
const char *error_info = NULL;
|
||||||
ctx->ssl_ctx = SSL_CTX_new (SSLv23_client_method ());
|
ctx->ssl_ctx = SSL_CTX_new (SSLv23_client_method ());
|
||||||
@@ -376,17 +377,17 @@ irc_initialize_ssl (struct bot_context *ctx, struct error **e)
|
|||||||
if (!ctx->ssl)
|
if (!ctx->ssl)
|
||||||
goto error_ssl_2;
|
goto error_ssl_2;
|
||||||
|
|
||||||
const char *ssl_cert = str_map_find (&ctx->config, "ssl_cert");
|
const char *tls_cert = str_map_find (&ctx->config, "tls_cert");
|
||||||
if (ssl_cert)
|
if (tls_cert)
|
||||||
{
|
{
|
||||||
char *path = resolve_filename
|
char *path = resolve_filename
|
||||||
(ssl_cert, resolve_relative_config_filename);
|
(tls_cert, resolve_relative_config_filename);
|
||||||
if (!path)
|
if (!path)
|
||||||
print_error ("%s: %s", "cannot open file", ssl_cert);
|
print_error ("%s: %s", "cannot open file", tls_cert);
|
||||||
// XXX: perhaps we should read the file ourselves for better messages
|
// XXX: perhaps we should read the file ourselves for better messages
|
||||||
else if (!SSL_use_certificate_file (ctx->ssl, path, SSL_FILETYPE_PEM)
|
else if (!SSL_use_certificate_file (ctx->ssl, path, SSL_FILETYPE_PEM)
|
||||||
|| !SSL_use_PrivateKey_file (ctx->ssl, path, SSL_FILETYPE_PEM))
|
|| !SSL_use_PrivateKey_file (ctx->ssl, path, SSL_FILETYPE_PEM))
|
||||||
print_error ("%s: %s", "setting the SSL client certificate failed",
|
print_error ("%s: %s", "setting the TLS client certificate failed",
|
||||||
ERR_error_string (ERR_get_error (), NULL));
|
ERR_error_string (ERR_get_error (), NULL));
|
||||||
free (path);
|
free (path);
|
||||||
}
|
}
|
||||||
@@ -418,7 +419,7 @@ error_ssl_1:
|
|||||||
// multiple errors on the OpenSSL stack.
|
// multiple errors on the OpenSSL stack.
|
||||||
if (!error_info)
|
if (!error_info)
|
||||||
error_info = ERR_error_string (ERR_get_error (), NULL);
|
error_info = ERR_error_string (ERR_get_error (), NULL);
|
||||||
error_set (e, "%s: %s", "could not initialize SSL", error_info);
|
error_set (e, "%s: %s", "could not initialize TLS", error_info);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1444,7 +1445,7 @@ enum irc_read_result
|
|||||||
};
|
};
|
||||||
|
|
||||||
static enum irc_read_result
|
static enum irc_read_result
|
||||||
irc_fill_read_buffer_ssl (struct bot_context *ctx, struct str *buf)
|
irc_fill_read_buffer_tls (struct bot_context *ctx, struct str *buf)
|
||||||
{
|
{
|
||||||
int n_read;
|
int n_read;
|
||||||
start:
|
start:
|
||||||
@@ -1608,7 +1609,7 @@ on_irc_readable (const struct pollfd *fd, struct bot_context *ctx)
|
|||||||
struct str *buf = &ctx->read_buffer;
|
struct str *buf = &ctx->read_buffer;
|
||||||
enum irc_read_result (*fill_buffer)(struct bot_context *, struct str *)
|
enum irc_read_result (*fill_buffer)(struct bot_context *, struct str *)
|
||||||
= ctx->ssl
|
= ctx->ssl
|
||||||
? irc_fill_read_buffer_ssl
|
? irc_fill_read_buffer_tls
|
||||||
: irc_fill_read_buffer;
|
: irc_fill_read_buffer;
|
||||||
bool disconnected = false;
|
bool disconnected = false;
|
||||||
while (true)
|
while (true)
|
||||||
@@ -1754,8 +1755,8 @@ irc_connect (struct bot_context *ctx, struct error **e)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool use_ssl;
|
bool use_tls;
|
||||||
if (!irc_get_boolean_from_config (ctx, "ssl", &use_ssl, e))
|
if (!irc_get_boolean_from_config (ctx, "tls", &use_tls, e))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
bool connected = socks_host
|
bool connected = socks_host
|
||||||
@@ -1765,7 +1766,7 @@ irc_connect (struct bot_context *ctx, struct error **e)
|
|||||||
if (!connected)
|
if (!connected)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (use_ssl && !irc_initialize_ssl (ctx, e))
|
if (use_tls && !irc_initialize_tls (ctx, e))
|
||||||
{
|
{
|
||||||
xclose (ctx->irc_fd);
|
xclose (ctx->irc_fd);
|
||||||
ctx->irc_fd = -1;
|
ctx->irc_fd = -1;
|
||||||
@@ -1965,7 +1966,7 @@ main (int argc, char *argv[])
|
|||||||
printf (PROGRAM_NAME " " PROGRAM_VERSION "\n");
|
printf (PROGRAM_NAME " " PROGRAM_VERSION "\n");
|
||||||
exit (EXIT_SUCCESS);
|
exit (EXIT_SUCCESS);
|
||||||
case 'w':
|
case 'w':
|
||||||
call_write_default_config (optarg, g_config_table);
|
call_simple_config_write_default (optarg, g_config_table);
|
||||||
exit (EXIT_SUCCESS);
|
exit (EXIT_SUCCESS);
|
||||||
default:
|
default:
|
||||||
print_error ("wrong options");
|
print_error ("wrong options");
|
||||||
@@ -1988,7 +1989,7 @@ main (int argc, char *argv[])
|
|||||||
bot_context_init (&ctx);
|
bot_context_init (&ctx);
|
||||||
|
|
||||||
struct error *e = NULL;
|
struct error *e = NULL;
|
||||||
if (!read_config_file (&ctx.config, &e)
|
if (!simple_config_update_from_file (&ctx.config, &e)
|
||||||
|| !setup_recovery_handler (&ctx, &e))
|
|| !setup_recovery_handler (&ctx, &e))
|
||||||
{
|
{
|
||||||
print_error ("%s", e->message);
|
print_error ("%s", e->message);
|
||||||
|
|||||||
Reference in New Issue
Block a user