1
0
mirror of https://github.com/irssi/irssi.git synced 2024-12-04 14:46:39 -05:00

Merge pull request #1372 from dwfreed/rebrand-1.3.2

Merge Nei's changes
This commit is contained in:
Tom Wesley 2022-04-25 18:09:44 +01:00 committed by GitHub
commit 7d673653a1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
82 changed files with 1139 additions and 441 deletions

View File

@ -18,7 +18,7 @@ jobs:
steps: steps:
- name: prepare required software - name: prepare required software
run: | run: |
sudo apt install $apt_build_deps $apt_build_deps_autotools sudo apt update && sudo apt install $apt_build_deps $apt_build_deps_autotools
- uses: actions/checkout@main - uses: actions/checkout@main
- name: make dist - name: make dist
run: | run: |
@ -38,18 +38,18 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
os: [ubuntu-16.04, ubuntu-latest] os: [ubuntu-18.04, ubuntu-latest]
builder: [meson, configure] builder: [meson, configure]
compiler: [clang, gcc] compiler: [clang, gcc]
flags: [regular] flags: [regular]
include: include:
- os: ubuntu-16.04 - os: ubuntu-18.04
builder: meson builder: meson
meson_ver: ==0.49.2 meson_ver: ==0.49.2
setuptools_ver: <51 setuptools_ver: <51
- os: ubuntu-latest - os: ubuntu-latest
builder: meson builder: meson
meson_ver: <0.59.0 meson_ver: <0.60.0
- os: ubuntu-latest - os: ubuntu-latest
builder: meson builder: meson
flags: meson-latest FAILURE-OK flags: meson-latest FAILURE-OK
@ -64,7 +64,7 @@ jobs:
meson_ver: ${{ matrix.meson_ver }} meson_ver: ${{ matrix.meson_ver }}
setuptools_ver: ${{ matrix.setuptools_ver }} setuptools_ver: ${{ matrix.setuptools_ver }}
run: | run: |
sudo apt install $apt_build_deps $apt_build_deps_${{ matrix.builder }} sudo apt update && sudo apt install $apt_build_deps $apt_build_deps_${{ matrix.builder }}
eval "$get_pip_build_deps_${{ matrix.builder }}" eval "$get_pip_build_deps_${{ matrix.builder }}"
curl -SLf https://github.com/irssi-import/actions-irssi/raw/master/check-irssi/render.pl -o ~/render.pl && chmod +x ~/render.pl curl -SLf https://github.com/irssi-import/actions-irssi/raw/master/check-irssi/render.pl -o ~/render.pl && chmod +x ~/render.pl
- name: unpack archive - name: unpack archive
@ -118,5 +118,5 @@ jobs:
echo load perl >> irssi-test/startup echo load perl >> irssi-test/startup
echo load proxy >> irssi-test/startup echo load proxy >> irssi-test/startup
echo ^quit >> irssi-test/startup echo ^quit >> irssi-test/startup
irssi-build/bin/irssi --home irssi-test | ~/render.pl irssi-build/bin/irssi --home irssi-test | perl -Mutf8 -C ~/render.pl
cat irc.log.* cat irc.log.*

View File

@ -19,13 +19,23 @@ jobs:
matrix: matrix:
sanitizer: [address, undefined, memory] sanitizer: [address, undefined, memory]
steps: steps:
- uses: actions/checkout@main
with:
path: irssi
- name: Docker build build_fuzzers container
run: |
# google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master
docker build -t build_fuzzers:actions -f "/home/runner/work/_actions/google/oss-fuzz/master/infra/build_fuzzers.Dockerfile" "/home/runner/work/_actions/google/oss-fuzz/master/infra"
- name: Build Fuzzers (${{ matrix.sanitizer }}) - name: Build Fuzzers (${{ matrix.sanitizer }})
id: build id: build
uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master env:
with: OSS_FUZZ_PROJECT_NAME: 'irssi'
oss-fuzz-project-name: 'irssi' DRY_RUN: false
dry-run: false SANITIZER: ${{ matrix.sanitizer }}
sanitizer: ${{ matrix.sanitizer }} PROJECT_SRC_PATH: /github/workspace/irssi
REPOSITORY: 'irssi'
run: |
docker run --workdir /github/workspace --rm -e OSS_FUZZ_PROJECT_NAME -e DRY_RUN -e SANITIZER -e PROJECT_SRC_PATH -e REPOSITORY -e WORKSPACE=/github/workspace -e CI=true -v "/var/run/docker.sock":"/var/run/docker.sock" -v "$GITHUB_WORKSPACE":"/github/workspace" build_fuzzers:actions
- name: Run Fuzzers (${{ matrix.sanitizer }}) - name: Run Fuzzers (${{ matrix.sanitizer }})
uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master
with: with:

290
NEWS
View File

@ -1,4 +1,290 @@
v1.3-head 2021-xx-xx The Irssi team <staff@irssi.org> v1.3.2 2022-xx-xx The Irssi team <staff@irssi.org>
- CHANTYPES take precedence over (missing) STATUSMSG in /join
(#1358, an#54)
- Fix crash in Perl's $view->set_bookmark (freebsd#254237,
an#56)
- Minor help fixes (an#51, an#52)
- Fix regression where own channel status was forgotten after
/UPGRADE (#1357, an#53)
* /SET resolve_reverse_lookup setting was removed (#1034,
#1135)
* Irssi will try to connect on IPv4 if IPv6 connection failed
(#1146). By Shivaram Lingamneni
* The display system now renders formats on the fly (#1079,
#1188, #1191, #1192, #1204, #1205, #1209, #1349, #1355,
an#13, an#14, an#28, an#29, an#36, an#37, an#49)
This major change will break scripts that try to modify
printed text during "print text" signal (#1189). They need
to be ported to modify the text during "print format"
instead. It also breaks the usage of using /FORMAT to add
different colours to a line. Such usage needs to be ported
to using $expando variables instead. Affected scripts
include format_identify.pl, friends_peder.pl, nickcolor.pl,
nm.pl, people.pl
The "gui print text finished" and "gui print text after
finished" signals gained a TEXT_DEST_REC *parameter in the
process.
A new "gui render line text" signal is available to change
the rendering of a line
* made the $Z expando (time) dynamic (#1087, #1207, #1208)
This change breaks the usage of /SET timestamp_format to
supply a custom displayed time stamp. Affected scripts
include binary_time.pl
* /HILIGHT -priority now affects which hilight rule gets
applied (#1228, #1232)
* The NAMES list is now hidden by default if there are more
than 18 users on the channel (an#7)
To revert to the previous behaviour
/SET show_names_on_join_limit -1
* -tls_verify is now enabled by default (#1170, an#18, #1309,
an#23, #1343, #1351)
This may cause an ugly display of notls_verify in the output
of /SERVER LIST, even on plain-text connection, on old
configs. Kindly remove the "tls_verify = "no";" entries from
your config file manually.
* Irssi will now attempt STARTTLS if advertised (#1170, #1312,
an#19)
Use -disallow_starttls if you absolutely do not want this
In order to check for a STARTTLS advertisement, Irssi will
now wait for a response (even an error) to CAP LS 302. If
your bouncer/server does not want to communicate before
receiving USER/PASS at all, use -nocap to disable the CAP
check.
* Channel sync requests (WHO, MODE) are now sent "later" than
user commands. This should improve responsiveness to user
commands in the autojoin phase (an#26, an#32, an#33)
* Irssi is now using full paths in #include directives and
consequently does not add all directories to the include
path anymore (#1040)
* The Build System was ported to Meson (#1064, #1065, #1068,
#1071, #1072, #1073, #1074, #1075, #1084, #1085, #1118, #1166,
#1223, #1224, #1245, #1313, #1314, an#31)
* Scriptassist was changed to use a YAML database (#1163)
It will tell you when you need to update your setting
* /BIND shows all partial matches (#1155)
* Cleanup of unused functions (#1017, #1132, #1145, #1182,
#1246, #1264)
Functions removed:
NET_CALLBACK
NET_HOST_CALLBACK
RESOLVED_NAME_REC
net_gethostbyaddr_nonblock
net_connect_nonblock
[ SIMPLE_THREAD_REC, simple_init, simple_readpipe ]
hash_save_key
Functions deprecated:
dec2octal
g_timeval_cmp
get_timeval_diff
Function names corrected:
g_input -> i_input
g_istr -> i_istr
g_io_channel -> i_io_channel
g_hash_free_value -> i_hash_free_value
remove g_free_true
gslist -> i_slist
glog_func -> i_log_func
glist -> i_list
If multi-version compatibility is desired, module authors
can find an example of backwards compatible code in
cdidier/irssi-xmpp#55
+ Add MSGLEVEL_HIDDEN to Perl (#1044)
+ Add $view->set_hidden_level and $view->remove_lines_by_level
to Perl (#1026)
+ Add a /SET scrollback_max_age setting (#1022). By Heikki
Orsila
+ Add /SET actlist_prefer_window_name (#1025)
+ Add -window option to /CAT (#1023, #1159)
+ Add an option to list specific sections with
/SET -section lookandfeel
(#1048)
+ Add support for IRCv3 CAP LS 302 (#1091)
+ Add a new "print noformat" signal that goes together with
"print format" (#1088, #1192)
+ Add support for IRCv3 extended-join. /SET show_extended_join
to enable (#1097, #1107, #1124)
There are two new /FORMATs, join_extended and
join_extended_account, that theme writers need to take into
account if desired.
+ Add support for IRCv3 setname (#1093, #1104, #1254, GL#33)
+ Add support for IRCv3 account-notify (#1100, #1098, GL#33,
#1105, #1131). Credit to oss-fuzz
/SET show_account_notify to enable
+ Add support for IRCv3 invite-notify (#1094)
+ Add support for receiving IRCv3 message-tags (#576, #1090)
+ Add support for sending IRCv3 message-tags (#1092, an#34)
+ Enable the znc.in/self-message CAP by default (#1123)
+ Add support for IRCv3 away-notify. /SET away_notify_public
to enable (#1099, GL#33, #1105)
+ Add support for IRCv3 chghost (#1096, GL#33, #1105)
For servers with broken chghost implementation that fill the
status window with host changed messages, one may add "quote
cap req -chghost" to the -autosendcmd or, if the host change
messages are entirely undesired, "/format -delete
host_changed"
+ Add support for IRCv3 server-time. /SET show_server_time to
enable (#1108)
+ Add support for logging IRCv3 server-time.
/SET log_server_time to disable (#1318, an#16)
+ Add IRCv3 features to signals.txt (#1111)
In particular, "message join" now takes 2 additional
arguments, script and module authors must beware of this
change.
+ Show the unignore time in /IGNORE output (#1158, #1161)
+ Add /SET quit_on_hup to make the behaviour of SIGHUP
configurable (#828, #1169). By Pinguin1234
+ Support numeric 489 as ERR_SECUREONLYCHAN (#1193, #1196). By
Michael Hansen
+ Improve support for building Irssi in Termux-Android with
Meson (#1199)
+ Add usermode key to Irssi::Irc::Chatnet in Perl (#1288). By
Jessica Sophie Porter
+ Add format_string_expand and format_string_unexpand
functions to Perl (#1286)
+ Add ...->format_create_dest(...)->printformat("format",
args...) and ...->printformat_module("module", "format",
args...) methods to Perl (#1284)
You can avoid any CORE::GLOBAL::caller hacks using the
printformat_module method, especially sind that hack was not
safe during signal emissions
+ Add tracking of user accounts in the channel nicklist using
WHOX on join (#1250)
+ Add auto-loading of the Perl and otr module from /SET
autoload_modules (#1295)
+ Add /IGNORE ... NOHILIGHT to ignore some hilights (#1260)
+ Do not beep on hidden lines with /SET beep_msg_level
... -HIDDEN (#1259)
+ Added /CS, /MS, /NS, and /OS aliases to the default config
(#1316). By Mathis Beer
+ Allow -tls_ca{file,path} '' to unset an argument (#730,
#1060, an#30)
+ Add a "server outgoing modify" signal to intercept outgoing
messages (#1148, #1151, an#15, an#43). Original by
JustAnotherArchivist
- remove some hard-coded 510 byte assumptions (#1086)
- Several fixes for error checks in SSL (#944, #1037, #943,
#1036). Reported by Chi Li
- Wrong variable tested in mask_match (#902, #1035)
- Fix bug where irssi-proxy with `?'-port would not reconnect
(#1041)
- Allow shrinking of /SET rawlog_lines (#957, #1020). By
Marcus "Teschi" Prinz
- Fix /WINDOW BALANCE warning (#1054)
- fix overflow when first command history entry expires
(#1070)
- begin modularising IRC module (#1067, #1112, #1113)
- fix some memory leaks in /DCC RESUME and settings_add
(#1077). By Zero King
- fix cut-off text with theme_indent module and /SET
indent_always OFF (#1078)
- fix the cap_queue order (#1095)
- add reference counted strings (#1089)
- Fix irc_op_public messages not triggering hilights (#354,
#891, #1129). By Dan Collins
- Fix /IGNORE not setting the right level in irc_op_public
messages (#1280). Credit to oss-fuzz
- Fix GTimeVal deprecation (#1141, #1144, #1145, #1350, an#44)
If multi-version compatibility is desired, module authors
can find an example of backwards compatible code in
cdidier/irssi-xmpp#53
- Fix /IGNORE ... MODES NO_ACT not working (#1164)
- Deprecated -ssl* options are hidden from tab completion
(#1171)
- Make /SET actlist_sort a choice type (#1198)
- Fix crash from self-unloading script (#1206). By Thomas
Stagner
- Fix crash during Perl signal emission (#1233, #1234)
- Fix a case where empty lines or comments inside channels or
servers in the config would confuse Irssi (#1062, #1242,
#1243)
- Fix reported freezing in DCC GET on slow disks (#159, #1271)
- Fix message-tags parsing (#1274, #1275). Credit to oss-fuzz
- Fail redirects when receiving numeric 263 (RPL_TRYAGAIN) in
response to /WHO (#1283)
- Some updates to .gitignore (#1302). By Rene Kita
- Fix build on operating systems with X/Open Curses, version 2
(#1305, #1308). By Nia Alarie (Regression introduced with
#1290, alternative fix for Irssi 1.2.3 no-term.h.patch)
- Fix otr module not using g_strndup, e.g. on Solaris 10
(#1315). By Claes Nästén
- Fix cursor getting stuck for auto completions that changes
case (#1176, #1322, an#8). By ffrogman
- Restore operation of tag/* in /SET activity_hide_targets
(#1337, an#11) nb. the ::all syntax was working in Irssi 1.1
and 1.2 (and continues to work)
- Fix /SERVER ADD -matrix -network my_matrix_network
(an#12). By Andrej Kacian
- Fix /SERVER ADD creating duplicated entries in the config
file (#1317, an#22, an#41)
- Fix critical when SASL user is set and SASL password is
empty (#1325, an#21)
- Misc fixes (#1106, #1141, #1272, #1297, an#35)
- Fuzz fixes (#1116, #1117, #1119, #1125, #1126, an#20)
- Build system fixes (#1101, #1102, #1069, #1140, #1181, #1253)
- Sync docs and scripts (an#39)
- Text and Help updates
- add -tls_* options to manual (#1029, #1030). By Jacob
V. Rasmussen
- missing targets in /MSG (#1032)
- wrong parameter in /ECHO (#1024)
- Spelling in OTR (#1047). By David Gall
- Clarify statusbar priority (#1049). By Marius Gedminas
- Document get_irssi_dir in Perl (#1051, #1052). By Alex
Shafer
- typo in /HILIGHT help (#1081). By DFrostByte
- improved clarity of your_nick_owned (#1138). By Mike Quin
- Update some URLs to https (#1163)
- Add documentation for escaping some characters (#1329,
#1330, an#9). By Guntbert Reiter
- Fix some typos (#1336, an#10). By Francis Mteo
- Document $abiversion and parse_special (an#38). By bw1
- Infrastructure updates:
- Support for Github Actions (#1039, #1103, #1160, #1212,
#1231, #1252, #1261, an#40)
- Run clang-format on pull requests (#1172, #1173, #1184,
#1230, #1247, #1287)
- Run abidiff on pull requests (#1179, #1195)
- Test CI-Fuzz (#1279, #1304, an#17)
v1.2.3 2021-04-11 The Irssi team <staff@irssi.org> v1.2.3 2021-04-11 The Irssi team <staff@irssi.org>
- Fix the compilation of utf8proc (#1021) - Fix the compilation of utf8proc (#1021)
@ -40,7 +326,7 @@ v1.2.3 2021-04-11 The Irssi team <staff@irssi.org>
v1.2.2 2019-08-29 The Irssi team <staff@irssi.org> v1.2.2 2019-08-29 The Irssi team <staff@irssi.org>
- Fix a use after free issue when receiving IRCv3 CAP - Fix a use after free issue when receiving IRCv3 CAP
information from the server (GL#34) information from the server (GL#34, GL!35)
- Fix a crash during startup when windows weren't fully - Fix a crash during startup when windows weren't fully
initialised yet (#1114, bdo#935813) initialised yet (#1114, bdo#935813)

View File

@ -1,11 +1,10 @@
# [Irssi](https://irssi.org/) # [Irssi](https://irssi.org)
![Build Status](https://github.com/irssi/irssi/workflows/Check%20Irssi/badge.svg?branch=master) ![Build Status](https://github.com/irssi/irssi/workflows/Check%20Irssi/badge.svg?branch=master)
Irssi is a modular chat client that is most commonly known for its Irssi is a modular text mode chat client. It comes with IRC support
text mode user interface, but 80% of the code isn't text mode built in, and there are third party
specific. Irssi comes with IRC support built in, and there are [ICB](https://github.com/jperkin/irssi-icb),
third party [ICB](https://github.com/jperkin/irssi-icb),
[SILC](http://www.silcnet.org/), [SILC](http://www.silcnet.org/),
[XMPP](http://cybione.org/~irssi-xmpp/) (Jabber), [XMPP](http://cybione.org/~irssi-xmpp/) (Jabber),
[PSYC](http://about.psyc.eu/Irssyc) and [PSYC](http://about.psyc.eu/Irssyc) and
@ -34,8 +33,8 @@ ninja -C Build && sudo ninja -C Build install
``` ```
tar xJf irssi-*.tar.xz tar xJf irssi-*.tar.xz
cd irssi-* cd irssi-*
./configure meson Build
make && sudo make install ninja -C Build && sudo ninja -C Build install
``` ```
### Requirements ### Requirements

View File

@ -1,4 +1,4 @@
AC_INIT(irssi, 1.3-head) AC_INIT(irssi, 1.3.2)
AC_CONFIG_SRCDIR([src]) AC_CONFIG_SRCDIR([src])
AC_CONFIG_AUX_DIR(build-aux) AC_CONFIG_AUX_DIR(build-aux)
AC_PREREQ(2.50) AC_PREREQ(2.50)

View File

@ -2,7 +2,7 @@
<h1>Frequently Asked Questions</h1> <h1>Frequently Asked Questions</h1>
<h3 id="q-why-doesnt-irssi-display-colors-even-when-ircii-etc-displays-them">Q: Why doesnt irssi display colors even when ircii etc. displays them?</h3> <h3 id="q-why-doesnt-irssi-display-colors-even-when-ircii-etc-displays-them">Q: Why doesnt irssi display colors even when ircii etc. displays them?</h3>
<p>A: They force ANSI colors even if terminal doesnt support them. By default, irssi uses colors only if terminfo/termcap so says. The correct way to fix this would be to change your TERM environment to a value where colors work, like xterm-color or color_xterm (eg. <code>TERM=xterm-color irssi</code>). If this doesnt help, then use the evil way of <code>/SET term_force_colors ON</code>.</p> <p>A: They force ANSI colors even if terminal doesnt support them. By default, irssi uses colors only if terminfo/termcap so says. The correct way to fix this would be to change your TERM environment to a value where colors work, like xterm-256color or color_xterm (eg. <code>TERM=xterm-256color irssi</code>). If this doesnt help, then use the evil way of <code>/SET term_force_colors ON</code>.</p>
<h3 id="q-how-do-i-easily-write-text-to-channel-that-starts-with--character">Q: How do I easily write text to channel that starts with / character?</h3> <h3 id="q-how-do-i-easily-write-text-to-channel-that-starts-with--character">Q: How do I easily write text to channel that starts with / character?</h3>
@ -54,7 +54,7 @@
<h3 id="q-will-there-be-detach-like-feature">Q: Will there be /DETACH-like feature?</h3> <h3 id="q-will-there-be-detach-like-feature">Q: Will there be /DETACH-like feature?</h3>
<p>A: <a href="https://tmux.github.io/">tmux</a>, <a href="https://www.gnu.org/software/screen/screen.html">screen</a> and <a href="http://dtach.sf.net/">dtach</a> can be used to do it just fine.</p> <p>A: <a href="https://tmux.github.io/">tmux</a>, <a href="https://www.gnu.org/software/screen/screen.html">screen</a> and <a href="https://sourceforge.net/projects/dtach/">dtach</a> can be used to do it just fine.</p>
<h3 id="q-how-do-i-run-scripts-automatically-at-startup">Q: How do I run scripts automatically at startup?</h3> <h3 id="q-how-do-i-run-scripts-automatically-at-startup">Q: How do I run scripts automatically at startup?</h3>

View File

@ -4,8 +4,8 @@ Q: Why doesnt irssi display colors even when ircii etc. displays them?
A: They force ANSI colors even if terminal doesnt support them. By default, A: They force ANSI colors even if terminal doesnt support them. By default,
irssi uses colors only if terminfo/termcap so says. The correct way to fix this irssi uses colors only if terminfo/termcap so says. The correct way to fix this
would be to change your TERM environment to a value where colors work, like would be to change your TERM environment to a value where colors work, like
xterm-color or color_xterm (eg. TERM=xterm-color irssi). If this doesnt help, xterm-256color or color_xterm (eg. TERM=xterm-256color irssi). If this doesnt
then use the evil way of /SET term_force_colors ON. help, then use the evil way of /SET term_force_colors ON.
Q: How do I easily write text to channel that starts with / character? Q: How do I easily write text to channel that starts with / character?
A: / /text A: / /text
@ -119,6 +119,6 @@ A: Check [6]here
[1] https://github.com/irssi-import/xirssi [1] https://github.com/irssi-import/xirssi
[2] https://tmux.github.io/ [2] https://tmux.github.io/
[3] https://www.gnu.org/software/screen/screen.html [3] https://www.gnu.org/software/screen/screen.html
[4] http://dtach.sf.net/ [4] https://sourceforge.net/projects/dtach/
[5] https://dgl.cx/irssi/hack-whois-in-current-window.pl [5] https://dgl.cx/irssi/hack-whois-in-current-window.pl
[6] https://irssi.org/assets/irssi.wav [6] https://irssi.org/assets/irssi.wav

View File

@ -15,7 +15,7 @@
%9Examples:%9 %9Examples:%9
/ADMIN /ADMIN
/ADMIN irc.example.com /ADMIN irc.libera.chat
/ADMIN mike /ADMIN mike
%9See also:%9 INFO %9See also:%9 INFO

View File

@ -33,12 +33,12 @@
/CHANNEL /CHANNEL
/CHANNEL LIST /CHANNEL LIST
/CHANNEL ADD -auto #irssi ExampleNet /CHANNEL ADD -auto #irssi liberachat
/CHANNEL ADD -auto #basementcat Quakenet secret_lair /CHANNEL ADD -auto #basementcat Quakenet secret_lair
/CHANNEL ADD -auto -bots '*!@*.irssi.org *!bot@irssi.org' -botcmd 'msg $0 op WzerTrzq' #hideout ExampleNet /CHANNEL ADD -auto -bots '*!@*.irssi.org *!bot@irssi.org' -botcmd 'msg $0 op WzerTrzq' #hideout liberachat
/CHANNEL ADD -auto -bots 'Q!TheQBot@CServe.quakenet.org' -botcmd '^MSG Q op #irssi' #irssi Quakenet /CHANNEL ADD -auto -bots 'Q!TheQBot@CServe.quakenet.org' -botcmd '^MSG Q op #irssi' #irssi Quakenet
/CHANNEL MODIFY -noauto #irssi ExampleNet /CHANNEL MODIFY -noauto #irssi liberachat
/CHANNEL REMOVE #hideout ExampleNet /CHANNEL REMOVE #hideout liberachat
%9Special Example:%9 %9Special Example:%9

View File

@ -34,9 +34,9 @@
%9Examples:%9 %9Examples:%9
/CONNECT ExampleNet /CONNECT liberachat
/CONNECT -6 ExampleNet /CONNECT -6 liberachat
/CONNECT -4 -! -host staff.irssi.org -network ExampleNet irc.example.com /CONNECT -4 -! -host staff.irssi.org -network liberachat irc.libera.chat
/CONNECT irc.irssi.org 6667 WzerT8zq mike /CONNECT irc.irssi.org 6667 WzerT8zq mike
%9See also:%9 DISCONNECT, RMRECONNS, SERVER %9See also:%9 DISCONNECT, RMRECONNS, SERVER

View File

@ -18,7 +18,7 @@
%9Examples:%9 %9Examples:%9
/DISCONNECT ExampleNet I'm off for today, take care! /DISCONNECT liberachat I'm off for today, take care!
/DISCONNECT * Vacation time :D /DISCONNECT * Vacation time :D
/DISCONNECT /DISCONNECT

View File

@ -11,11 +11,17 @@
Evaluates the given commands and executes them; you can use internal Evaluates the given commands and executes them; you can use internal
variables and separate multiple commands by using the ';' character. variables and separate multiple commands by using the ';' character.
If the command contains a string with '$', '\' or ';' those characters
need to be escaped:
'$' -> '$$'
'\' -> '\\' (or even '\\\\', depending on where they are used)
';' -> '\;'
%9Examples:%9 %9Examples:%9
/EVAL echo I am connected to ${S} on ${chatnet} as ${N} /EVAL echo I am connected to ${S} on ${chatnet} as ${N}
/EVAL echo My user privileges are +${usermode}; echo Let's party! /EVAL echo My user privileges are +${usermode}; echo Let's party!
to print '1;2$3\4': /EVAL echo 1\;2$$3\\4
%9References:%9 %9References:%9

View File

@ -15,7 +15,7 @@
%9Examples:%9 %9Examples:%9
/INFO /INFO
/INFO irc.example.com /INFO irc.libera.chat
%9See also:%9 ADMIN %9See also:%9 ADMIN

View File

@ -20,7 +20,7 @@
/JOIN #irssi /JOIN #irssi
/JOIN #basementcat secret_lair /JOIN #basementcat secret_lair
/JOIN -invite /JOIN -invite
/JOIN -ExampleNet #github,#example,#irssi /JOIN -liberachat #github,#libera,#irssi
%9See also:%9 KICK, PART %9See also:%9 KICK, PART

View File

@ -23,7 +23,7 @@
%9Examples:%9 %9Examples:%9
/KNOCK #irssi /KNOCK #irssi
/KNOCK #example /KNOCK #libera
/KNOCK #github /KNOCK #github
%9See also:%9 INVITE, JOIN %9See also:%9 INVITE, JOIN

View File

@ -33,10 +33,10 @@
%9Examples:%9 %9Examples:%9
/LOG OPEN -targets mike ~/irclogs/mike.log MSGS /LOG OPEN -targets mike ~/irclogs/mike.log MSGS
/LOG OPEN -targets #irssi ~/irclogs/ExampleNet/irssi-%%Y-%%m-%%d /LOG OPEN -targets #irssi ~/irclogs/liberachat/irssi-%%Y-%%m-%%d
/LOG CLOSE ~/irclogs/ExampleNet/irssi-%%Y-%%m-%%d /LOG CLOSE ~/irclogs/liberachat/irssi-%%Y-%%m-%%d
/LOG STOP ~/irclogs/ExampleNet/irssi-%%Y-%%m-%%d /LOG STOP ~/irclogs/liberachat/irssi-%%Y-%%m-%%d
/LOG START ~/irclogs/ExampleNet/irssi-%%Y-%%m-%%d /LOG START ~/irclogs/liberachat/irssi-%%Y-%%m-%%d
/SET autolog ON /SET autolog ON

View File

@ -15,7 +15,7 @@
%9Examples:%9 %9Examples:%9
/MOTD /MOTD
/MOTD irc.example.com /MOTD irc.libera.chat
/MOTD bob /MOTD bob
%9See also:%9 ADMIN, INFO, LINKS, MAP %9See also:%9 ADMIN, INFO, LINKS, MAP

View File

@ -21,7 +21,7 @@
%9Examples:%9 %9Examples:%9
/NAMES -ops /NAMES -ops
/NAMES -voices #irssi,#example /NAMES -voices #irssi,#libera
%9See also:%9 JOIN, PART, WHO, WHOIS %9See also:%9 JOIN, PART, WHO, WHOIS

View File

@ -15,7 +15,7 @@
%9Examples:%9 %9Examples:%9
/NCTCP #irssi VERSION King of the Jungle v1.0 /NCTCP #irssi VERSION King of the Jungle v1.0
/NCTCP bob,#example USERINFO I am bob :p /NCTCP bob,#libera USERINFO I am bob :p
%9See also:%9 CTCP %9See also:%9 CTCP

View File

@ -19,6 +19,7 @@
-autosendcmd: Specifies the commands, separated by the ';' character, -autosendcmd: Specifies the commands, separated by the ';' character,
and enclosed within two "'" characters, to perform after and enclosed within two "'" characters, to perform after
connecting. connecting.
(Some characters need to be escaped - see /help eval)
-querychans: Specifies the maximum number of channels to put in one MODE -querychans: Specifies the maximum number of channels to put in one MODE
or WHO command when synchronizing. or WHO command when synchronizing.
-whois: Specifies the maximum number of nicknames in one WHOIS -whois: Specifies the maximum number of nicknames in one WHOIS
@ -59,11 +60,11 @@
%9Examples:%9 %9Examples:%9
/NETWORK ADD -usermode +giw EFnet /NETWORK ADD -usermode +giw EFnet
/NETWORK ADD -usermode +iw -nick mike -realname 'The one and only mike!' -host staff.irssi.org ExampleNet /NETWORK ADD -usermode +iw -nick mike -realname 'The one and only mike!' -host staff.irssi.org liberachat
/NETWORK ADD -autosendcmd '^MSG NickServ identify WzerT8zq' ExampleNet /NETWORK ADD -autosendcmd '^MSG NickServ identify WzerT8zq' liberachat
/NETWORK ADD -autosendcmd '^MSG Q@CServe.quakenet.org AUTH mike WzerT8zq; WAIT 2000; OPER mike WzerT8zq; WAIT 2000; MODE mike +kXP' Quakenet /NETWORK ADD -autosendcmd '^MSG Q@CServe.quakenet.org AUTH mike WzerT8zq; WAIT 2000; OPER mike WzerT8zq; WAIT 2000; MODE mike +kXP' Quakenet
/NETWORK MODIFY -usermode +gi EFnet /NETWORK MODIFY -usermode +gi EFnet
/NETWORK REMOVE ExampleNet /NETWORK REMOVE liberachat
%9See also:%9 CHANNEL, CONNECT, SERVER %9See also:%9 CHANNEL, CONNECT, SERVER

View File

@ -51,7 +51,7 @@ GENKEY <name>
This process is done in a background worker and can take an arbitrary This process is done in a background worker and can take an arbitrary
amount of time. The completion is checked when another irssi event is amount of time. The completion is checked when another irssi event is
catched. caught.
HELP HELP
Print this help. Print this help.

View File

@ -14,7 +14,7 @@
%9Examples:%9 %9Examples:%9
/PART #irssi /PART #irssi
/PART #example,#irssi /PART #libera,#irssi
%9See also:%9 JOIN, KICK %9See also:%9 JOIN, KICK

View File

@ -17,8 +17,8 @@
%9Examples:%9 %9Examples:%9
/QUERY mike /QUERY mike
/QUERY -ExampleNet bob /QUERY -liberachat bob
/QUERY -ExampleNet -window sarah /QUERY -liberachat -window sarah
%9See also:%9 MSG, UNQUERY, WINDOW %9See also:%9 MSG, UNQUERY, WINDOW

View File

@ -22,7 +22,7 @@
%9Examples:%9 %9Examples:%9
/RECODE /RECODE
/RECODE ADD ExampleNet/mike utf-8 /RECODE ADD liberachat/mike utf-8
/RECODE ADD #korea euc-kr /RECODE ADD #korea euc-kr
/RECODE REMOVE #korea /RECODE REMOVE #korea

View File

@ -15,7 +15,7 @@
%9Examples:%9 %9Examples:%9
/RECONNECT /RECONNECT
/RECONNECT ExampleNet /RECONNECT liberachat
/RECONNECT EFnet BRB :) /RECONNECT EFnet BRB :)
%9See also:%9 CONNECT, DISCONNECT, NETWORK, RMRECONNS, SERVER %9See also:%9 CONNECT, DISCONNECT, NETWORK, RMRECONNS, SERVER

View File

@ -5,7 +5,7 @@
%9Parameters:%9 %9Parameters:%9
LIST: Displays the list of servers you are connected to. LIST: Displays the list of servers you have configured.
CONNECT: Connects to the given server. CONNECT: Connects to the given server.
ADD: Adds a server to your configuration. ADD: Adds a server to your configuration.
MODIFY: Modifies a server in your configuration. MODIFY: Modifies a server in your configuration.
@ -51,25 +51,24 @@
When using the ADD parameter on a server that already exists, the When using the ADD parameter on a server that already exists, the
configuration will be merged with each other. configuration will be merged with each other.
When using the command without any of the given parameters, it will When using the CONNECT parameter, it will connect to the specified
connect to the specified server; the server in the active window will be server; the server in the active window will be disconnected
disconnected unless you prepend the server with the '+' character; the same unless you prepend the server with the '+' character.
method is applicable to the CONNECT parameter.
Specify '-' as password to remove a server password Specify '-' as password to remove a server password
%9Examples:%9 %9Examples:%9
/SERVER /SERVER
/SERVER CONNECT irc.example.com /SERVER CONNECT irc.libera.chat
/SERVER CONNECT +irc.example.com /SERVER CONNECT +irc.libera.chat
/SERVER ADD -network ExampleNet -noautosendcmd irc.example.com /SERVER ADD -network liberachat -noautosendcmd irc.libera.chat
/SERVER ADD -! -auto -host staff.irssi.org -4 -network ExampleNet -noproxy irc.example.com 6667 /SERVER ADD -! -auto -host staff.irssi.org -4 -network liberachat -noproxy irc.libera.chat 6667
/SERVER MODIFY -network ExampleNet -noauto irc.example.com /SERVER MODIFY -network liberachat -noauto irc.libera.chat
/SERVER MODIFY -network ExampleNet irc.example.com 6697 - /SERVER MODIFY -network liberachat irc.libera.chat 6697 -
/SERVER REMOVE irc.example.com 6667 ExampleNet /SERVER REMOVE irc.libera.chat 6667 liberachat
/SERVER PURGE /SERVER PURGE
/SERVER PURGE irc.example.com /SERVER PURGE irc.libera.chat
%9See also:%9 CHANNEL, CONNECT, DISCONNECT, NETWORK, RECONNECT, RMRECONNS %9See also:%9 CHANNEL, CONNECT, DISCONNECT, NETWORK, RECONNECT, RMRECONNS

View File

@ -33,12 +33,12 @@
THEME: %|Applies or removes a per-window theme. THEME: %|Applies or removes a per-window theme.
GROW: %|Increase the size of the active split window by the specified number of lines. 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. 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. SIZE: %|Set the current split window size to the specified number of lines.
BALANCE: %|Balance the heights of all split windows. BALANCE: %|Balance the heights of all split windows.
HIDE: %|Hides the current split window, or the split window specified by number or item name. 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. 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 left or above the current one active. At the top, wraps to the bottom. UP: %|Set the split window left or above the current one active. At the top, wraps to the bottom.
DOWN: %|Set the split window right or below the current one active. At the bottom, wraps teft. DOWN: %|Set the split window right or below the current one active. At the bottom, wraps left.
LEFT: %|Go to the previous window numerically that is part of the current sticky group (or not part of any sticky group). 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). 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. 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.

View File

@ -349,7 +349,7 @@
after connecting to the network. This is useful for automatically after connecting to the network. This is useful for automatically
identifying yourself to NickServ, for example identifying yourself to NickServ, for example
/NETWORK ADD -autosendcmd "/^msg NickServ identify secret" ExampleNet /NETWORK ADD -autosendcmd "/^msg NickServ identify secret" liberachat
/NETWORK REMOVE <name> /NETWORK REMOVE <name>

View File

@ -24,7 +24,7 @@ You really should set some password for the proxy with:
Then you'll need to configure the ports/ircnets the proxy listens in, Then you'll need to configure the ports/ircnets the proxy listens in,
something like: something like:
/SET irssiproxy_ports IRCnet=2777 EFNet=2778 ExampleNet=2779 /SET irssiproxy_ports IRCnet=2777 EFNet=2778 liberachat=2779
There we have 3 different irc networks answering in 3 ports. Note that 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 you'll have to make the correct /IRCNET ADD and /SERVER ADD commands to

View File

@ -151,6 +151,7 @@ irc.c:
"whois default event", SERVER_REC, char *args, char *sender_nick, char *sender_address "whois default event", SERVER_REC, char *args, char *sender_nick, char *sender_address
"server incoming", SERVER_REC, char *data "server incoming", SERVER_REC, char *data
"server outgoing modify", SERVER_REC, GString *data, int crlf
(for perl parser..) (for perl parser..)
"redir "<cmd>, SERVER_REC, char *args, char *sender_nick, char *sender_address "redir "<cmd>, SERVER_REC, char *args, char *sender_nick, char *sender_address
@ -358,6 +359,9 @@ gui-printtext.c:
textbuffer-view.c textbuffer-view.c
"gui textbuffer line removed", TEXTBUFFER_VIEW_REC *view, LINE_REC *line, LINE_REC *prev_line "gui textbuffer line removed", TEXTBUFFER_VIEW_REC *view, LINE_REC *line, LINE_REC *prev_line
textbuffer-formats.c
"gui render line text", TEXT_DEST_REC, GString *str, LINE_INFO_META_REC
Perl Perl
---- ----

View File

@ -68,7 +68,7 @@
<p>And to connect to one of those networks and join a channel:</p> <p>And to connect to one of those networks and join a channel:</p>
<div><div><pre><code>/CONNECT ExampleNet <div><div><pre><code>/CONNECT liberachat
/JOIN #irssi /JOIN #irssi
</code></pre></div></div> </code></pre></div></div>
@ -94,7 +94,7 @@
<p>If you have irssi 0.8.18 or higher and the irc network supports it, you can use SASL instead of nickserv, which is more reliable:</p> <p>If you have irssi 0.8.18 or higher and the irc network supports it, you can use SASL instead of nickserv, which is more reliable:</p>
<div><div><pre><code>/NETWORK ADD -sasl_username yourname -sasl_password yourpassword -sasl_mechanism PLAIN ExampleNet <div><div><pre><code>/NETWORK ADD -sasl_username yourname -sasl_password yourpassword -sasl_mechanism PLAIN liberachat
</code></pre></div></div> </code></pre></div></div>
<p>These commands have many more options, see their help for details:</p> <p>These commands have many more options, see their help for details:</p>
@ -226,7 +226,7 @@ Ctrl-P, Ctrl-N - Jump to previous / next window
<p>And finally channels:</p> <p>And finally channels:</p>
<div><div><pre><code>/CHANNEL ADD -auto -bots *!*user@host -botcmd "/^msg $0 op pass" #irssi efnet <div><div><pre><code>/CHANNEL ADD -auto -bots *!*bot@host.org -botcmd "/^msg $0 op pass" #irssi efnet
/CHANNEL ADD -auto #secret IRCnet password /CHANNEL ADD -auto #secret IRCnet password
</code></pre></div></div> </code></pre></div></div>
@ -395,7 +395,7 @@ Ctrl-X - set the next server in list active
<p><code>/HELP bind</code> tells pretty much everything there is to know about keyboard bindings. However, theres the problem of how to bind some non-standard keys. They might differ a bit with each terminal, so youll need to find out what exactly the keypress produces. Easiest way to check that would be to see what it prints in <code>cat</code>. Heres an example for pressing F1 key:</p> <p><code>/HELP bind</code> tells pretty much everything there is to know about keyboard bindings. However, theres the problem of how to bind some non-standard keys. They might differ a bit with each terminal, so youll need to find out what exactly the keypress produces. Easiest way to check that would be to see what it prints in <code>cat</code>. Heres an example for pressing F1 key:</p>
<div><div><pre><code> [user@host] ~% cat <div><div><pre><code> [cras@hurina] ~% cat
^[OP ^[OP
</code></pre></div></div> </code></pre></div></div>

View File

@ -43,7 +43,7 @@ has a few predefined networks, to list them:
And to connect to one of those networks and join a channel: And to connect to one of those networks and join a channel:
/CONNECT LiberaChat /CONNECT liberachat
/JOIN #irssi /JOIN #irssi
To add more networks: To add more networks:
@ -67,7 +67,7 @@ wait for 2 seconds before joining channels:
If you have irssi 0.8.18 or higher and the irc network supports it, you can use If you have irssi 0.8.18 or higher and the irc network supports it, you can use
SASL instead of nickserv, which is more reliable: SASL instead of nickserv, which is more reliable:
/NETWORK ADD -sasl_username yourname -sasl_password yourpassword -sasl_mechanism PLAIN ExampleNet /NETWORK ADD -sasl_username yourname -sasl_password yourpassword -sasl_mechanism PLAIN liberachat
These commands have many more options, see their help for details: These commands have many more options, see their help for details:
@ -218,7 +218,7 @@ IRC network, other servers are automatically connected in same network if the
And finally channels: And finally channels:
/CHANNEL ADD -auto -bots *!*user@host -botcmd "/^msg $0 op pass" #irssi efnet /CHANNEL ADD -auto -bots *!*bot@host.org -botcmd "/^msg $0 op pass" #irssi efnet
/CHANNEL ADD -auto #secret IRCnet password /CHANNEL ADD -auto #secret IRCnet password
-bots and -botcmd should be the only ones needing a bit of explaining. Theyre -bots and -botcmd should be the only ones needing a bit of explaining. Theyre
@ -442,7 +442,7 @@ They might differ a bit with each terminal, so youll need to find out what
exactly the keypress produces. Easiest way to check that would be to see what exactly the keypress produces. Easiest way to check that would be to see what
it prints in cat. Heres an example for pressing F1 key: it prints in cat. Heres an example for pressing F1 key:
[user@host] ~% cat [cras@hurina] ~% cat
^[OP ^[OP
So in irssi you would use /BIND ^[OP /ECHO F1 pressed. If you use multiple So in irssi you would use /BIND ^[OP /ECHO F1 pressed. If you use multiple

View File

@ -1,19 +1,18 @@
servers = ( servers = (
{ address = "irc.dal.net"; chatnet = "DALnet"; port = "6667"; }, { address = "irc.dal.net"; chatnet = "DALnet"; port = "6667"; },
{ address = "ssl.efnet.org"; chatnet = "EFNet"; port = "9999"; use_tls = "yes"; tls_verify = "no"; }, { address = "ssl.efnet.org"; chatnet = "EFNet"; port = "9999"; use_tls = "yes"; tls_verify = "no"; },
{ address = "irc.esper.net"; chatnet = "EsperNet"; port = "6697"; use_tls = "yes"; tls_verify = "yes"; }, { address = "irc.esper.net"; chatnet = "EsperNet"; port = "6697"; use_tls = "yes"; tls_verify = "yes"; },
{ address = "chat.freenode.net"; chatnet = "Freenode"; port = "6697"; use_tls = "yes"; tls_verify = "yes"; }, { address = "irc.libera.chat"; chatnet = "liberachat";port = "6697"; use_tls = "yes"; tls_verify = "yes"; },
{ address = "irc.gamesurge.net"; chatnet = "GameSurge"; port = "6667"; }, { address = "irc.gamesurge.net"; chatnet = "GameSurge"; port = "6667"; },
{ address = "ssl.ircnet.ovh"; chatnet = "IRCnet"; port = "6697"; use_tls = "yes"; tls_verify = "yes"; }, { address = "ssl.ircnet.ovh"; chatnet = "IRCnet"; port = "6697"; use_tls = "yes"; tls_verify = "yes"; },
{ address = "open.ircnet.net"; chatnet = "IRCnet"; port = "6667"; }, { address = "open.ircnet.net"; chatnet = "IRCnet"; port = "6667"; },
{ address = "irc.ircsource.net"; chatnet = "IRCSource"; port = "6667"; }, { address = "irc.ircsource.net"; chatnet = "IRCSource"; port = "6667"; },
{ address = "irc.libera.chat"; chatnet = "LiberaChat"; port = "6697"; use_tls = "yes"; tls_verify = "yes"; }, { address = "irc.netfuze.net"; chatnet = "NetFuze"; port = "6667"; },
{ address = "irc.netfuze.net"; chatnet = "NetFuze"; port = "6667"; }, { address = "irc.oftc.net"; chatnet = "OFTC"; port = "6697"; use_tls = "yes"; tls_verify = "yes"; },
{ address = "irc.oftc.net"; chatnet = "OFTC"; port = "6697"; use_tls = "yes"; tls_verify = "yes"; }, { address = "irc.quakenet.org"; chatnet = "QuakeNet"; port = "6667"; },
{ address = "irc.quakenet.org"; chatnet = "QuakeNet"; port = "6667"; }, { address = "irc.rizon.net"; chatnet = "Rizon"; port = "6697"; use_tls = "yes"; tls_verify = "yes"; },
{ address = "irc.rizon.net"; chatnet = "Rizon"; port = "6697"; use_tls = "yes"; tls_verify = "yes"; }, { address = "silc.silcnet.org"; chatnet = "SILC"; port = "706"; },
{ address = "silc.silcnet.org"; chatnet = "SILC"; port = "706"; }, { address = "irc.undernet.org"; chatnet = "Undernet"; port = "6667"; }
{ address = "irc.undernet.org"; chatnet = "Undernet"; port = "6667"; }
); );
chatnets = { chatnets = {
@ -35,7 +34,7 @@ chatnets = {
max_msgs = "4"; max_msgs = "4";
max_whois = "1"; max_whois = "1";
}; };
Freenode = { liberachat = {
type = "IRC"; type = "IRC";
max_kicks = "1"; max_kicks = "1";
max_msgs = "4"; max_msgs = "4";
@ -59,12 +58,6 @@ chatnets = {
max_msgs = "4"; max_msgs = "4";
max_whois = "1"; max_whois = "1";
}; };
LiberaChat = {
type = "IRC";
max_kicks = "1";
max_msgs = "4";
max_whois = "1";
};
NetFuze = { NetFuze = {
type = "IRC"; type = "IRC";
max_kicks = "1"; max_kicks = "1";
@ -101,16 +94,15 @@ chatnets = {
}; };
channels = ( channels = (
{ name = "#lobby"; chatnet = "EsperNet"; autojoin = "No"; }, { name = "#lobby"; chatnet = "EsperNet"; autojoin = "No"; },
{ name = "#freenode"; chatnet = "Freenode"; autojoin = "No"; }, { name = "#libera"; chatnet = "liberachat";autojoin = "No"; },
{ name = "#gamesurge"; chatnet = "GameSurge"; autojoin = "No"; }, { name = "#irssi"; chatnet = "liberachat";autojoin = "No"; },
{ name = "#irssi"; chatnet = "IRCNet"; autojoin = "No"; }, { name = "#gamesurge"; chatnet = "GameSurge"; autojoin = "No"; },
{ name = "#ircsource"; chatnet = "IRCSource"; autojoin = "No"; }, { name = "#irssi"; chatnet = "IRCNet"; autojoin = "No"; },
{ name = "#libera"; chatnet = "LiberaChat"; autojoin = "No"; }, { name = "#ircsource"; chatnet = "IRCSource"; autojoin = "No"; },
{ name = "#irssi"; chatnet = "LiberaChat"; autojoin = "No"; }, { name = "#netfuze"; chatnet = "NetFuze"; autojoin = "No"; },
{ name = "#netfuze"; chatnet = "NetFuze"; autojoin = "No"; }, { name = "#oftc"; chatnet = "OFTC"; autojoin = "No"; },
{ name = "#oftc"; chatnet = "OFTC"; autojoin = "No"; }, { name = "silc"; chatnet = "SILC"; autojoin = "No"; }
{ name = "silc"; chatnet = "SILC"; autojoin = "No"; }
); );
aliases = { aliases = {

View File

@ -1,5 +1,5 @@
project('irssi', 'c', project('irssi', 'c',
version : '1.3-head', version : '1.3.2',
meson_version : '>=0.49', meson_version : '>=0.49',
default_options : ['warning_level=1']) default_options : ['warning_level=1'])
@ -53,6 +53,8 @@ require_glib_internal = get_option('install-glib') == 'force'
want_static_dependency = get_option('static-dependency') == 'yes' want_static_dependency = get_option('static-dependency') == 'yes'
package_version = get_option('PACKAGE_VERSION') != '' ? get_option('PACKAGE_VERSION') : meson.project_version()
chat_modules = ['irc'] chat_modules = ['irc']
run_command('mkdir', meson.current_build_dir() / incdir) run_command('mkdir', meson.current_build_dir() / incdir)
@ -273,7 +275,12 @@ endif
dep += glib_dep dep += glib_dep
dep += gmodule_dep dep += gmodule_dep
openssl_dep = dependency('openssl', static : want_static_dependency) if glib_internal and want_static_dependency and want_fuzzer
openssl_proj = subproject('openssl', default_options : ['default_library=static', 'asm=disabled'])
openssl_dep = openssl_proj.get_variable('openssl_dep')
else
openssl_dep = dependency('openssl', static : want_static_dependency)
endif
dep += openssl_dep dep += openssl_dep
############ ############
@ -535,7 +542,7 @@ foreach h : headers
endforeach endforeach
conf.set('HAVE_LIBUTF8PROC', have_libutf8proc) conf.set('HAVE_LIBUTF8PROC', have_libutf8proc)
conf.set_quoted('PACKAGE_VERSION', meson.project_version()) conf.set_quoted('PACKAGE_VERSION', package_version)
conf.set_quoted('PACKAGE_TARNAME', meson.project_name()) conf.set_quoted('PACKAGE_TARNAME', meson.project_name())
configure_file(output : 'irssi-config.h', configure_file(output : 'irssi-config.h',
@ -576,7 +583,11 @@ pc_requires = []
if not glib_internal if not glib_internal
pc_requires += glib_dep pc_requires += glib_dep
endif endif
pc.generate(filebase : 'irssi-1', name : 'Irssi', description : 'Irssi chat client', requires : pc_requires) pc.generate(filebase : 'irssi-1',
name : 'Irssi',
description : 'Irssi chat client',
version : package_version,
requires : pc_requires)
########### ###########
# irssi.1 # # irssi.1 #

View File

@ -15,3 +15,4 @@ option('static-dependency', type : 'combo', description : 'Request static depen
option('install-glib', type : 'combo', description : 'Download and install GLib for you', choices : ['no', 'yes', 'force']) option('install-glib', type : 'combo', description : 'Download and install GLib for you', choices : ['no', 'yes', 'force'])
option('docdir', type : 'string', description : 'Documentation directory') option('docdir', type : 'string', description : 'Documentation directory')
option('fhs-prefix', type : 'string', description : 'System prefix for Termux') option('fhs-prefix', type : 'string', description : 'System prefix for Termux')
option('PACKAGE_VERSION', type : 'string', description : 'Override PACKAGE_VERSION in tarballs')

View File

@ -6,36 +6,27 @@ use Irssi::Irc;
use strict; use strict;
use vars qw($VERSION %IRSSI); use vars qw($VERSION %IRSSI);
$VERSION = "1.00"; $VERSION = "1.01";
%IRSSI = ( %IRSSI = (
authors => 'Timo Sirainen', authors => 'Timo Sirainen',
name => 'quitmsg', name => 'quitmsg',
description => 'Random quit messages', description => 'Random quit messages',
license => 'Public Domain', license => 'Public Domain',
changed => 'Sun Mar 10 23:18 EET 2002' changed => 'Mon Jul 22 20:00 EET 2020'
); );
my $quitfile = glob "~/.irssi/irssi.quit"; my $quitfile = Irssi::get_irssi_dir() . "/irssi.quit";
sub cmd_quit { sub cmd_quit {
my ($data, $server, $channel) = @_; my ($data, $server, $channel) = @_;
return if ($data ne ""); return if ($data ne "");
open (f, "<", $quitfile) || return; open (my $fh, "<", $quitfile) || return;
my $lines = 0; while(<f>) { $lines++; }; my @lines = <$fh>;
my $line = int(rand($lines))+1; my $quitmsg = $lines[int(rand(@lines))];
chomp($quitmsg);
my $quitmsg; close($fh);
seek(f, 0, 0); $. = 0;
while(<f>) {
next if ($. != $line);
chomp;
$quitmsg = $_;
last;
}
close(f);
foreach my $server (Irssi::servers) { foreach my $server (Irssi::servers) {
$server->command("/disconnect ".$server->{tag}." $quitmsg"); $server->command("/disconnect ".$server->{tag}." $quitmsg");

View File

@ -5,7 +5,7 @@
use strict; use strict;
our $VERSION = '2003020807'; our $VERSION = '2020042700';
our %IRSSI = ( our %IRSSI = (
authors => 'Stefan \'tommie\' Tomanek', authors => 'Stefan \'tommie\' Tomanek',
contact => 'stefan@pico.ruhr.de', contact => 'stefan@pico.ruhr.de',
@ -23,12 +23,15 @@ use Irssi 20020324;
use CPAN::Meta::YAML; use CPAN::Meta::YAML;
use LWP::UserAgent; use LWP::UserAgent;
use POSIX; use POSIX;
use version;
# GnuPG is not always needed # GnuPG is not always needed
$have_gpg = 0; $have_gpg = 0;
eval "use GnuPG qw(:algo :trust);"; eval "use GnuPG qw(:algo :trust);";
$have_gpg = 1 if not ($@); $have_gpg = 1 if not ($@);
my $irssi_version = qv(Irssi::parse_special('v$J') =~ s/-.*//r);
sub show_help { sub show_help {
my $help = "scriptassist $VERSION my $help = "scriptassist $VERSION
/scriptassist check /scriptassist check
@ -39,15 +42,15 @@ sub show_help {
Search the script database Search the script database
/scriptassist info <scripts> /scriptassist info <scripts>
Display information about <scripts> Display information about <scripts>
".#/scriptassist ratings <scripts> /scriptassist ratings <scripts|all>
# Retrieve the average ratings of the the scripts Retrieve the average ratings of the the scripts
#/scriptassist top <num> /scriptassist top <num>
# Retrieve the first <num> top rated scripts Retrieve the first <num> top rated scripts
"/scriptassist new <num> /scriptassist new <num>
Display the newest <num> scripts Display the newest <num> scripts
".#/scriptassist rate <script> <stars> /scriptassist rate <script>
# Rate the script with a number of stars ranging from 0-5 Rate the script if you like it
"/scriptassist contact <script> /scriptassist contact <script>
Write an email to the author of the script Write an email to the author of the script
(Requires OpenURL) (Requires OpenURL)
/scriptassist cpan <module> /scriptassist cpan <module>
@ -95,6 +98,7 @@ sub call_openurl {
$code->($url); $code->($url);
} else { } else {
print CLIENTCRAP "%R>>%n Please install openurl.pl"; print CLIENTCRAP "%R>>%n Please install openurl.pl";
print CLIENTCRAP "%R>>%n or open < $url > manually";
} }
} }
@ -188,7 +192,7 @@ sub get_unknown {
foreach (keys %$db) { foreach (keys %$db) {
next unless defined $db->{$_}{commands}; next unless defined $db->{$_}{commands};
foreach my $item (split / /, $db->{$_}{commands}) { foreach my $item (split / /, $db->{$_}{commands}) {
return { $_ => $db->{$_} } if ($item =~ /^$cmd$/i); return { $_ => +{%{$db->{$_}}} } if ($item =~ /^$cmd$/i);
} }
} }
return undef; return undef;
@ -264,47 +268,80 @@ sub script_info {
$result{$sname}{modules}{$mod}{installed} = module_exist($mod); $result{$sname}{modules}{$mod}{installed} = module_exist($mod);
} }
} }
if (defined $xml->{$plname}{depends}) { # if (defined $xml->{$plname}{depends}) {
my $depends = $xml->{$plname}{depends}; # my $depends = $xml->{$plname}{depends};
foreach my $dep (split(/ /, $depends)) { # foreach my $dep (split(/ /, $depends)) {
$result{$sname}{depends}{$dep}{installed} = 1; # $result{$sname}{depends}{$dep}{installed} = 1; #(defined ${ 'Irssi::Script::'.$dep });
} # }
} # }
} }
return \%result; return \%result;
} }
sub get_rate_url {
my ($src) = @_;
my $ua = LWP::UserAgent->new(env_proxy=>1, keep_alive=>1, timeout=>30);
$ua->agent('ScriptAssist/'.$VERSION);
my $request = HTTP::Request->new('GET', $src);
my $response = $ua->request($request);
unless ($response->is_success) {
my $error = join "\n", $response->status_line(), (grep / at .* line \d+/, split "\n", $response->content()), '';
die("Fetching ratings location failed: $error");
}
my $votes_url;
for my $tag ($response->content() =~ /<script([^>]*)>/g) {
my $attr = " $tag ";
($votes_url = $1) =~ s/\.\w+$/.yml/
if $attr =~ /\sasync\s/ && $attr =~ m{\ssrc="(https?://.*?/votes\.\w+)"\s};
}
unless ($votes_url) {
die("Fetching ratings failed: Could not find votes script\n");
}
$request = HTTP::Request->new('GET', $votes_url);
$response = $ua->request($request);
if (!$response->is_success) {
my $error = join "\n", $response->status_line(), (grep / at .* line \d+/, split "\n", $response->content()), '';
die("Fetching ratings failed: $error");
}
my $data = $response->content();
utf8::decode($data);
CPAN::Meta::YAML->read_string($data)->[0];
}
sub rate_script { sub rate_script {
my ($script, $stars) = @_; my ($script, $stars) = @_;
my $ua = LWP::UserAgent->new(env_proxy=>1, keep_alive=>1, timeout=>30); my $xml = get_scripts();
$ua->agent('ScriptAssist/'.2003020803); my $votes = get_rate_url(map { $_->{source} } values %$xml);
my $request = HTTP::Request->new('GET', 'http://ratings.irssi.de/irssirate.pl?&stars='.$stars.'&mode=rate&script='.$script); my ($sname, $plname, $pname) = get_names($script, $xml);
my $response = $ua->request($request); die "Script $script not found\n" unless $votes->{$plname};
unless ($response->is_success() && $response->content() =~ /You already rated this script/) { return $votes->{$plname}{u}
return 1;
} else {
return 0;
}
} }
sub get_ratings { sub get_ratings {
my ($scripts, $limit) = @_; my ($scripts, $limit) = @_;
my $ua = LWP::UserAgent->new(env_proxy=>1, keep_alive=>1, timeout=>30); my $xml = get_scripts();
$ua->agent('ScriptAssist/'.2003020803); my $votes = get_rate_url(map { $_->{source} } values %$xml);
my $script = join(',', @{$scripts}); foreach (keys %{$votes}) {
my $request = HTTP::Request->new('GET', 'http://ratings.irssi.de/irssirate.pl?script='.$script.'&sort=rating&limit='.$limit); if ($xml->{$_}) {
my $response = $ua->request($request); $xml->{$_}{votes} = $votes->{$_}{v};
my %result;
if ($response->is_success()) {
foreach (split /\n/, $response->content()) {
if (/<tr><td><a href=".*?">(.*?)<\/a>/) {
my $entry = $1;
if (/"><\/td><td>([0-9.]+)<\/td><td>(.*?)<\/td><td>/) {
$result{$entry} = [$1, $2];
}
}
} }
} }
my %result;
if (@{$scripts}) {
foreach (@{$scripts}) {
my ($sname, $plname, $pname) = get_names($_, $xml);
next unless (defined $xml->{$plname} || ( exists $Irssi::Script::{$pname} && exists $Irssi::Script::{$pname}{IRSSI} ));
$result{$plname} = [$xml->{$plname}{votes}];
}
} else {
my @keys = sort { $xml->{$b}{votes} <=> $xml->{$a}{votes}
|| $xml->{$b}{modified} cmp $xml->{$a}{modified} }
grep { !$xml->{$_}{HIDDEN} && $xml->{$_}{votes} ne '' } keys %$xml;
foreach (splice @keys, 0, $limit) {
$result{$_} = [$xml->{$_}{votes}];
}
}
die "No such script found\n" unless keys %result;
return \%result; return \%result;
} }
@ -597,13 +634,8 @@ sub print_rate {
my (%data) = @_; my (%data) = @_;
my $line; my $line;
foreach my $script (sort keys(%data)) { foreach my $script (sort keys(%data)) {
if ($data{$script}) { call_openurl($data{$script});
$line .= "%go%n %9".$script."%9 has been rated";
} else {
$line .= "%ro%n %9".$script."%9 : Already rated this script";
}
} }
print CLIENTCRAP draw_box('ScriptAssist', $line, 'rating', 1) ;
} }
sub print_ratings { sub print_ratings {
@ -617,8 +649,7 @@ sub print_ratings {
push @line, "%yo%n"; push @line, "%yo%n";
} }
push @line, "%9".$script."%9"; push @line, "%9".$script."%9";
push @line, $data{$script}{rating}; push @line, "[".(length $data{$script}{rating} ? $data{$script}{rating} : 'no')." votes]";
push @line, "[".$data{$script}{votes}." votes]";
push @table, \@line; push @table, \@line;
} }
print CLIENTCRAP draw_box('ScriptAssist', array2table(@table), 'ratings', 1) ; print CLIENTCRAP draw_box('ScriptAssist', array2table(@table), 'ratings', 1) ;
@ -845,7 +876,8 @@ sub get_scripts {
} }
$fetched = 1; $fetched = 1;
my $data = $response->content(); my $data = $response->content();
my ($src, $type); my $src = $site;
my $type = '';
if ($site =~ /(.*\/).+\.(.+)/) { if ($site =~ /(.*\/).+\.(.+)/) {
$src = $1; $src = $1;
$type = $2; $type = $2;
@ -1115,9 +1147,9 @@ sub cmd_scripassist {
} elsif ($args[0] eq 'ratings' && defined $args[1]) { } elsif ($args[0] eq 'ratings' && defined $args[1]) {
shift @args; shift @args;
bg_do("ratings ".join(' ', @args)); bg_do("ratings ".join(' ', @args));
} elsif ($args[0] eq 'rate' && defined $args[1] && defined $args[2]) { } elsif ($args[0] eq 'rate' && defined $args[1]) {
shift @args; shift @args;
bg_do("rate ".join(' ', @args)) if ($args[2] >= 0 && $args[2] < 6); bg_do("rate ".join(' ', @args));
} elsif ($args[0] eq 'info' && defined $args[1]) { } elsif ($args[0] eq 'info' && defined $args[1]) {
shift @args; shift @args;
bg_do("info ".join(' ', @args)); bg_do("info ".join(' ', @args));
@ -1158,6 +1190,7 @@ sub sig_command_script_load {
sub sig_default_command { sub sig_default_command {
my ($cmd, $server) = @_; my ($cmd, $server) = @_;
return unless Irssi::settings_get_bool("scriptassist_check_unknown_commands"); return unless Irssi::settings_get_bool("scriptassist_check_unknown_commands");
return if ($cmd =~ /^\d+$/ && $irssi_version >= v1.2.0 && Irssi::settings_get_bool("window_number_commands"));
bg_do('unknown '.$cmd); bg_do('unknown '.$cmd);
} }
@ -1213,11 +1246,11 @@ foreach my $cmd ( ( 'check',
'search', 'search',
# '-h', # '-h',
'help', 'help',
# 'ratings', 'ratings',
# 'rate', 'rate',
'info', 'info',
# 'echo', # 'echo',
# 'top', 'top',
'cpan', 'cpan',
'autorun', 'autorun',
'new' ) ) { 'new' ) ) {

View File

@ -6,7 +6,7 @@
#define IRSSI_GLOBAL_CONFIG "irssi.conf" /* config file name in /etc/ */ #define IRSSI_GLOBAL_CONFIG "irssi.conf" /* config file name in /etc/ */
#define IRSSI_HOME_CONFIG "config" /* config file name in ~/.irssi/ */ #define IRSSI_HOME_CONFIG "config" /* config file name in ~/.irssi/ */
#define IRSSI_ABI_VERSION 36 #define IRSSI_ABI_VERSION 41
#define DEFAULT_SERVER_ADD_PORT 6667 #define DEFAULT_SERVER_ADD_PORT 6667
#define DEFAULT_SERVER_ADD_TLS_PORT 6697 #define DEFAULT_SERVER_ADD_TLS_PORT 6697

View File

@ -42,7 +42,7 @@ enum {
MSGLEVEL_HIDDEN = 0x10000000, /* Hidden from view */ MSGLEVEL_HIDDEN = 0x10000000, /* Hidden from view */
MSGLEVEL_RESERVED1 = 0x20000000, MSGLEVEL_RESERVED1 = 0x20000000,
MSGLEVEL_RESERVED2 = 0x40000000, MSGLEVEL_RESERVED2 = 0x40000000,
MSGLEVEL_FORMAT = 0x80000000 /* Format data */ MSGLEVEL_FORMAT = (int)0x80000000 /* Format data */
}; };
/* clang-format on */ /* clang-format on */

View File

@ -204,11 +204,10 @@ static void log_rotate_check(LOG_REC *log)
g_free(new_fname); g_free(new_fname);
} }
void log_write_rec(LOG_REC *log, const char *str, int level) void log_write_rec(LOG_REC *log, const char *str, int level, time_t now)
{ {
char *colorstr; char *colorstr;
struct tm *tm; struct tm *tm;
time_t now;
int hour, day; int hour, day;
g_return_if_fail(log != NULL); g_return_if_fail(log != NULL);
@ -217,7 +216,8 @@ void log_write_rec(LOG_REC *log, const char *str, int level)
if (log->handle == -1) if (log->handle == -1)
return; return;
now = time(NULL); if (now == (time_t) -1)
now = time(NULL);
tm = localtime(&now); tm = localtime(&now);
hour = tm->tm_hour; hour = tm->tm_hour;
day = tm->tm_mday; day = tm->tm_mday;
@ -282,8 +282,8 @@ LOG_ITEM_REC *log_item_find(LOG_REC *log, int type, const char *item,
return NULL; return NULL;
} }
void log_file_write(const char *server_tag, const char *item, int level, void log_file_write(const char *server_tag, const char *item, int level, time_t t, const char *str,
const char *str, int no_fallbacks) int no_fallbacks)
{ {
GSList *tmp, *fallbacks; GSList *tmp, *fallbacks;
char *tmpstr; char *tmpstr;
@ -309,7 +309,7 @@ void log_file_write(const char *server_tag, const char *item, int level,
fallbacks = g_slist_append(fallbacks, rec); fallbacks = g_slist_append(fallbacks, rec);
else if (log_item_find(rec, LOG_ITEM_TARGET, item, else if (log_item_find(rec, LOG_ITEM_TARGET, item,
server_tag) != NULL) server_tag) != NULL)
log_write_rec(rec, str, level); log_write_rec(rec, str, level, t);
} }
if (!found && !no_fallbacks && fallbacks != NULL) { if (!found && !no_fallbacks && fallbacks != NULL) {
@ -319,7 +319,7 @@ void log_file_write(const char *server_tag, const char *item, int level,
g_strdup(str); g_strdup(str);
for (tmp = fallbacks; tmp != NULL; tmp = tmp->next) for (tmp = fallbacks; tmp != NULL; tmp = tmp->next)
log_write_rec(tmp->data, tmpstr, level); log_write_rec(tmp->data, tmpstr, level, t);
g_free(tmpstr); g_free(tmpstr);
} }

View File

@ -51,9 +51,9 @@ void log_item_destroy(LOG_REC *log, LOG_ITEM_REC *item);
LOG_ITEM_REC *log_item_find(LOG_REC *log, int type, const char *item, LOG_ITEM_REC *log_item_find(LOG_REC *log, int type, const char *item,
const char *servertag); const char *servertag);
void log_file_write(const char *server_tag, const char *item, int level, void log_file_write(const char *server_tag, const char *item, int level, time_t t, const char *str,
const char *str, int no_fallbacks); int no_fallbacks);
void log_write_rec(LOG_REC *log, const char *str, int level); void log_write_rec(LOG_REC *log, const char *str, int level, time_t now);
int log_start_logging(LOG_REC *log); int log_start_logging(LOG_REC *log);
void log_stop_logging(LOG_REC *log); void log_stop_logging(LOG_REC *log);

View File

@ -95,7 +95,6 @@ int i_input_add_poll(int fd, int priority, int condition, GInputFunction functio
#pragma GCC diagnostic ignored "-Wdeprecated-declarations" #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
int g_timeval_cmp(const GTimeVal *tv1, const GTimeVal *tv2) int g_timeval_cmp(const GTimeVal *tv1, const GTimeVal *tv2)
{ {
#pragma GCC diagnostic pop
if (tv1->tv_sec < tv2->tv_sec) if (tv1->tv_sec < tv2->tv_sec)
return -1; return -1;
if (tv1->tv_sec > tv2->tv_sec) if (tv1->tv_sec > tv2->tv_sec)
@ -105,11 +104,8 @@ int g_timeval_cmp(const GTimeVal *tv1, const GTimeVal *tv2)
tv1->tv_usec > tv2->tv_usec ? 1 : 0; tv1->tv_usec > tv2->tv_usec ? 1 : 0;
} }
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
long get_timeval_diff(const GTimeVal *tv1, const GTimeVal *tv2) long get_timeval_diff(const GTimeVal *tv1, const GTimeVal *tv2)
{ {
#pragma GCC diagnostic pop
long secs, usecs; long secs, usecs;
secs = tv1->tv_sec - tv2->tv_sec; secs = tv1->tv_sec - tv2->tv_sec;
@ -122,6 +118,22 @@ long get_timeval_diff(const GTimeVal *tv1, const GTimeVal *tv2)
return usecs; return usecs;
} }
#pragma GCC diagnostic pop
#if GLIB_CHECK_VERSION(2, 56, 0)
/* nothing */
#else
/* compatibility code for old GLib */
GDateTime *g_date_time_new_from_iso8601(const gchar *iso_date, GTimeZone *default_tz)
{
GTimeVal time;
if (g_time_val_from_iso8601(iso_date, &time)) {
return g_date_time_new_from_timeval_utc(&time);
} else {
return NULL;
}
}
#endif
int find_substr(const char *list, const char *item) int find_substr(const char *list, const char *item)
{ {

View File

@ -19,6 +19,13 @@ int g_timeval_cmp(const GTimeVal *tv1, const GTimeVal *tv2) G_GNUC_DEPRECATED;
long get_timeval_diff(const GTimeVal *tv1, const GTimeVal *tv2) G_GNUC_DEPRECATED; long get_timeval_diff(const GTimeVal *tv1, const GTimeVal *tv2) G_GNUC_DEPRECATED;
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
#if GLIB_CHECK_VERSION(2, 56, 0)
/* nothing */
#else
/* compatibility code for old GLib */
GDateTime *g_date_time_new_from_iso8601(const gchar *iso_date, GTimeZone *default_tz);
#endif
GSList *i_slist_find_string(GSList *list, const char *key); GSList *i_slist_find_string(GSList *list, const char *key);
GSList *i_slist_find_icase_string(GSList *list, const char *key); GSList *i_slist_find_icase_string(GSList *list, const char *key);
GList *i_list_find_string(GList *list, const char *key); GList *i_list_find_string(GList *list, const char *key);

View File

@ -191,8 +191,10 @@ static void server_setup_fill_optlist(SERVER_CONNECT_REC *conn, GHashTable *optl
/* ad-hoc TLS settings from command optlist */ /* ad-hoc TLS settings from command optlist */
if ((tmp = g_hash_table_lookup(optlist, "tls_cert")) != NULL || if ((tmp = g_hash_table_lookup(optlist, "tls_cert")) != NULL ||
(tmp = g_hash_table_lookup(optlist, "ssl_cert")) != NULL) (tmp = g_hash_table_lookup(optlist, "ssl_cert")) != NULL) {
conn->tls_cert = g_strdup(tmp); conn->tls_cert = g_strdup(tmp);
conn->use_tls = TRUE;
}
if ((tmp = g_hash_table_lookup(optlist, "tls_pkey")) != NULL || if ((tmp = g_hash_table_lookup(optlist, "tls_pkey")) != NULL ||
(tmp = g_hash_table_lookup(optlist, "ssl_pkey")) != NULL) (tmp = g_hash_table_lookup(optlist, "ssl_pkey")) != NULL)
conn->tls_pkey = g_strdup(tmp); conn->tls_pkey = g_strdup(tmp);
@ -220,10 +222,10 @@ static void server_setup_fill_optlist(SERVER_CONNECT_REC *conn, GHashTable *optl
if (g_hash_table_lookup(optlist, "notls_verify") != NULL) if (g_hash_table_lookup(optlist, "notls_verify") != NULL)
conn->tls_verify = FALSE; conn->tls_verify = FALSE;
if (g_hash_table_lookup(optlist, "tls_verify") != NULL || if (g_hash_table_lookup(optlist, "tls_verify") != NULL ||
g_hash_table_lookup(optlist, "ssl_verify") != NULL) g_hash_table_lookup(optlist, "ssl_verify") != NULL) {
conn->tls_verify = TRUE; conn->tls_verify = TRUE;
if ((conn->tls_cert != NULL && conn->tls_cert[0] != '\0') || conn->tls_verify)
conn->use_tls = TRUE; conn->use_tls = TRUE;
}
if (g_hash_table_lookup(optlist, "notls") != NULL) if (g_hash_table_lookup(optlist, "notls") != NULL)
conn->use_tls = FALSE; conn->use_tls = FALSE;
if (g_hash_table_lookup(optlist, "tls") != NULL || if (g_hash_table_lookup(optlist, "tls") != NULL ||
@ -457,8 +459,9 @@ static SERVER_SETUP_REC *server_setup_read(CONFIG_NODE *node)
port = config_node_get_int(node, "port", 0); port = config_node_get_int(node, "port", 0);
chatnet = config_node_get_str(node, "chatnet", NULL); chatnet = config_node_get_str(node, "chatnet", NULL);
if (server_setup_find(server, port, chatnet) != NULL) { if ((rec = server_setup_find(server, port, chatnet)) != NULL && rec->port == port) {
return NULL; /* duplicate server setup */
server_setup_remove(rec);
} }
rec = NULL; rec = NULL;
@ -484,8 +487,9 @@ static SERVER_SETUP_REC *server_setup_read(CONFIG_NODE *node)
rec->password = g_strdup(config_node_get_str(node, "password", NULL)); rec->password = g_strdup(config_node_get_str(node, "password", NULL));
rec->use_tls = config_node_get_bool(node, "use_tls", FALSE) || config_node_get_bool(node, "use_ssl", FALSE); rec->use_tls = config_node_get_bool(node, "use_tls", FALSE) || config_node_get_bool(node, "use_ssl", FALSE);
rec->tls_verify = config_node_get_bool(node, "tls_verify", TRUE) || rec->tls_verify = config_node_find(node, "tls_verify") != NULL ?
config_node_get_bool(node, "ssl_verify", FALSE); config_node_get_bool(node, "tls_verify", TRUE) :
config_node_get_bool(node, "ssl_verify", TRUE);
value = config_node_get_str(node, "tls_cert", NULL); value = config_node_get_str(node, "tls_cert", NULL);
if (value == NULL) if (value == NULL)
@ -548,7 +552,7 @@ static int compare_server_setup (CONFIG_NODE *node, SERVER_SETUP_REC *server)
return -1; return -1;
address = config_node_get_str(node, "address", NULL); address = config_node_get_str(node, "address", NULL);
chatnet = config_node_get_str(node, "chatnet", NULL); chatnet = config_node_get_str(node, "chatnet", "");
port = config_node_get_int(node, "port", 0); port = config_node_get_int(node, "port", 0);
if (address == NULL || chatnet == NULL) { if (address == NULL || chatnet == NULL) {
@ -556,7 +560,7 @@ static int compare_server_setup (CONFIG_NODE *node, SERVER_SETUP_REC *server)
} }
if (g_ascii_strcasecmp(address, server->address) != 0 || if (g_ascii_strcasecmp(address, server->address) != 0 ||
g_ascii_strcasecmp(chatnet, server->chatnet) != 0 || g_ascii_strcasecmp(chatnet, server->chatnet != NULL ? server->chatnet : "") != 0 ||
port != server->port) { port != server->port) {
return 1; return 1;
} }
@ -564,16 +568,20 @@ static int compare_server_setup (CONFIG_NODE *node, SERVER_SETUP_REC *server)
return 0; return 0;
} }
static void server_setup_save(SERVER_SETUP_REC *rec) static void server_setup_save(SERVER_SETUP_REC *rec, int old_port, const char *old_chatnet)
{ {
CONFIG_NODE *parent_node, *node; CONFIG_NODE *parent_node, *node;
SERVER_SETUP_REC search_rec = { 0 };
GSList *config_node; GSList *config_node;
parent_node = iconfig_node_traverse("(servers", TRUE); parent_node = iconfig_node_traverse("(servers", TRUE);
/* Try to find this channel in the configuration */ /* Try to find this channel in the configuration */
config_node = g_slist_find_custom(parent_node->value, rec, search_rec.address = rec->address;
(GCompareFunc)compare_server_setup); search_rec.chatnet = old_chatnet != NULL ? (char *) old_chatnet : rec->chatnet;
search_rec.port = old_port;
config_node = g_slist_find_custom(parent_node->value, &search_rec,
(GCompareFunc) compare_server_setup);
if (config_node != NULL) if (config_node != NULL)
/* Let's update this server record */ /* Let's update this server record */
node = config_node->data; node = config_node->data;
@ -654,16 +662,23 @@ static void server_setup_destroy(SERVER_SETUP_REC *rec)
g_free(rec); g_free(rec);
} }
void server_setup_add(SERVER_SETUP_REC *rec) void server_setup_modify(SERVER_SETUP_REC *rec, int old_port, const char *old_chatnet)
{ {
g_return_if_fail(g_slist_find(setupservers, rec) != NULL);
rec->type = module_get_uniq_id("SERVER SETUP", 0); rec->type = module_get_uniq_id("SERVER SETUP", 0);
if (g_slist_find(setupservers, rec) == NULL) server_setup_save(rec, old_port, old_chatnet);
setupservers = g_slist_append(setupservers, rec);
server_setup_save(rec);
signal_emit("server setup updated", 1, rec); signal_emit("server setup updated", 1, rec);
} }
void server_setup_add(SERVER_SETUP_REC *rec)
{
if (g_slist_find(setupservers, rec) == NULL)
setupservers = g_slist_append(setupservers, rec);
server_setup_modify(rec, -1, NULL);
}
void server_setup_remove_chatnet(const char *chatnet) void server_setup_remove_chatnet(const char *chatnet)
{ {
GSList *tmp, *next; GSList *tmp, *next;

View File

@ -41,6 +41,7 @@ SERVER_SETUP_REC *server_setup_find(const char *address, int port,
const char *chatnet); const char *chatnet);
void server_setup_add(SERVER_SETUP_REC *rec); void server_setup_add(SERVER_SETUP_REC *rec);
void server_setup_modify(SERVER_SETUP_REC *rec, int old_port, const char *old_chatnet);
void server_setup_remove(SERVER_SETUP_REC *rec); void server_setup_remove(SERVER_SETUP_REC *rec);
/* Remove servers attached to chatne */ /* Remove servers attached to chatne */

View File

@ -369,7 +369,7 @@ void server_connect_init(SERVER_REC *server)
server->type = module_get_uniq_id("SERVER", 0); server->type = module_get_uniq_id("SERVER", 0);
server_ref(server); server_ref(server);
server->current_incoming_meta = server->current_incoming_meta =
g_hash_table_new_full(g_str_hash, (GEqualFunc) g_strcmp0, g_hash_table_new_full(g_str_hash, (GEqualFunc) g_str_equal,
(GDestroyNotify) i_refstr_release, (GDestroyNotify) g_free); (GDestroyNotify) i_refstr_release, (GDestroyNotify) g_free);
server->nick = g_strdup(server->connrec->nick); server->nick = g_strdup(server->connrec->nick);

View File

@ -104,7 +104,7 @@ char *auto_word_complete(const char *line, int *pos)
/* check for words in autocompletion list */ /* check for words in autocompletion list */
replace = completion_find(word, TRUE); replace = completion_find(word, TRUE);
if (replace == NULL) { if (replace == NULL || (!g_strcmp0(replace, word))) {
ret = NULL; ret = NULL;
g_string_free(result, TRUE); g_string_free(result, TRUE);
} else { } else {

View File

@ -107,9 +107,14 @@ static void signal_window_item_changed(WINDOW_REC *window, WI_ITEM_REC *item)
static void sig_channel_joined(CHANNEL_REC *channel) static void sig_channel_joined(CHANNEL_REC *channel)
{ {
if (settings_get_bool("show_names_on_join") && if (settings_get_bool("show_names_on_join") && !channel->session_rejoin) {
!channel->session_rejoin) int limit = settings_get_int("show_names_on_join_limit");
fe_channels_nicklist(channel, CHANNEL_NICKLIST_FLAG_ALL); int flags = CHANNEL_NICKLIST_FLAG_ALL;
if (limit > 0 && g_hash_table_size(channel->nicks) > limit) {
flags |= CHANNEL_NICKLIST_FLAG_COUNT;
}
fe_channels_nicklist(channel, flags);
}
} }
/* SYNTAX: JOIN [-window] [-invite] [-<server tag>] <channels> [<keys>] */ /* SYNTAX: JOIN [-window] [-invite] [-<server tag>] <channels> [<keys>] */
@ -625,6 +630,7 @@ void fe_channels_init(void)
{ {
settings_add_bool("lookandfeel", "autoclose_windows", TRUE); settings_add_bool("lookandfeel", "autoclose_windows", TRUE);
settings_add_bool("lookandfeel", "show_names_on_join", TRUE); settings_add_bool("lookandfeel", "show_names_on_join", TRUE);
settings_add_int("lookandfeel", "show_names_on_join_limit", 18);
settings_add_int("lookandfeel", "names_max_columns", 6); settings_add_int("lookandfeel", "names_max_columns", 6);
settings_add_int("lookandfeel", "names_max_width", 0); settings_add_int("lookandfeel", "names_max_width", 0);

View File

@ -500,7 +500,7 @@ gboolean strarray_find_dest(char **array, const TEXT_DEST_REC *dest)
str += server_tag_len + 1; str += server_tag_len + 1;
} }
if (g_strcmp0(str, "") == 0 || g_strcmp0(str, "::all") == 0) { if (g_strcmp0(str, "*") == 0 || g_strcmp0(str, "::all") == 0) {
return TRUE; return TRUE;
} else if (g_ascii_strcasecmp(str, dest->target) == 0) { } else if (g_ascii_strcasecmp(str, dest->target) == 0) {
return TRUE; return TRUE;

View File

@ -48,6 +48,7 @@
#define AUTOLOG_INACTIVITY_CLOSE (60*5) #define AUTOLOG_INACTIVITY_CLOSE (60*5)
static int autolog_level; static int autolog_level;
static int log_server_time;
static int autoremove_tag; static int autoremove_tag;
static char *autolog_path; static char *autolog_path;
@ -502,8 +503,8 @@ static void autolog_open_check(TEXT_DEST_REC *dest)
autolog_open(server, server_tag, g_strcmp0(target, "*") ? target : deftarget); autolog_open(server, server_tag, g_strcmp0(target, "*") ? target : deftarget);
} }
static void log_single_line(WINDOW_REC *window, const char *server_tag, static void log_single_line(WINDOW_REC *window, const char *server_tag, const char *target,
const char *target, int level, const char *text) int level, time_t t, const char *text)
{ {
char windownum[MAX_INT_STRLEN]; char windownum[MAX_INT_STRLEN];
LOG_REC *log; LOG_REC *log;
@ -514,15 +515,16 @@ static void log_single_line(WINDOW_REC *window, const char *server_tag,
log = logs_find_item(LOG_ITEM_WINDOW_REFNUM, log = logs_find_item(LOG_ITEM_WINDOW_REFNUM,
windownum, NULL, NULL); windownum, NULL, NULL);
if (log != NULL) if (log != NULL)
log_write_rec(log, text, level); log_write_rec(log, text, level, t);
} }
log_file_write(server_tag, target, level, text, FALSE); log_file_write(server_tag, target, level, t, text, FALSE);
} }
static void log_line(TEXT_DEST_REC *dest, const char *text) static void log_line(TEXT_DEST_REC *dest, const char *text)
{ {
char **lines, **tmp; char **lines, **tmp;
time_t t = (time_t) -1;
if (dest->level == MSGLEVEL_NEVER) if (dest->level == MSGLEVEL_NEVER)
return; return;
@ -536,9 +538,18 @@ static void log_line(TEXT_DEST_REC *dest, const char *text)
/* text may contain one or more lines, log wants to eat them one /* text may contain one or more lines, log wants to eat them one
line at a time */ line at a time */
lines = g_strsplit(text, "\n", -1); lines = g_strsplit(text, "\n", -1);
if (log_server_time && dest->meta != NULL) {
char *val;
if ((val = g_hash_table_lookup(dest->meta, "time")) != NULL) {
GDateTime *time;
if ((time = g_date_time_new_from_iso8601(val, NULL)) != NULL) {
t = g_date_time_to_unix(time);
g_date_time_unref(time);
}
}
}
for (tmp = lines; *tmp != NULL; tmp++) for (tmp = lines; *tmp != NULL; tmp++)
log_single_line(dest->window, dest->server_tag, log_single_line(dest->window, dest->server_tag, dest->target, dest->level, t, *tmp);
dest->target, dest->level, *tmp);
g_strfreev(lines); g_strfreev(lines);
} }
@ -720,6 +731,13 @@ static void read_settings(void)
g_strfreev(autolog_ignore_targets); g_strfreev(autolog_ignore_targets);
autolog_ignore_targets = g_strsplit(settings_get_str("autolog_ignore_targets"), " ", -1); autolog_ignore_targets = g_strsplit(settings_get_str("autolog_ignore_targets"), " ", -1);
log_server_time = settings_get_choice("log_server_time");
if (log_server_time == 2) {
SETTINGS_REC *rec = settings_get_record("show_server_time");
if (rec != NULL)
log_server_time = settings_get_bool("show_server_time");
}
} }
void fe_log_init(void) void fe_log_init(void)
@ -731,7 +749,8 @@ void fe_log_init(void)
settings_add_bool("log", "autolog", FALSE); settings_add_bool("log", "autolog", FALSE);
settings_add_bool("log", "autolog_colors", FALSE); settings_add_bool("log", "autolog_colors", FALSE);
settings_add_bool("log", "autolog_only_saved_channels", FALSE); settings_add_bool("log", "autolog_only_saved_channels", FALSE);
settings_add_str("log", "autolog_path", "~/irclogs/$tag/$0.log"); settings_add_choice("log", "log_server_time", 2, "off;on;auto");
settings_add_str("log", "autolog_path", "~/irclogs/$tag/$0.log");
settings_add_level("log", "autolog_level", "all -crap -clientcrap -ctcps"); settings_add_level("log", "autolog_level", "all -crap -clientcrap -ctcps");
settings_add_str("log", "log_theme", ""); settings_add_str("log", "log_theme", "");
settings_add_str("log", "autolog_ignore_targets", ""); settings_add_str("log", "autolog_ignore_targets", "");

View File

@ -91,7 +91,9 @@ static SERVER_SETUP_REC *create_server_setup(GHashTable *optlist)
if (rec == NULL) if (rec == NULL)
rec = chat_protocol_get_default(); rec = chat_protocol_get_default();
else { else {
chatnet = g_hash_table_lookup(optlist, rec->chatnet); chatnet = g_hash_table_lookup(optlist, "network");
if (chatnet == NULL && g_hash_table_lookup(optlist, rec->chatnet) != NULL)
chatnet = rec->chatnet;
if (chatnet_find(chatnet) == NULL) { if (chatnet_find(chatnet) == NULL) {
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE,
TXT_UNKNOWN_CHATNET, chatnet); TXT_UNKNOWN_CHATNET, chatnet);
@ -108,11 +110,11 @@ static SERVER_SETUP_REC *create_server_setup(GHashTable *optlist)
static void cmd_server_add_modify(const char *data, gboolean add) static void cmd_server_add_modify(const char *data, gboolean add)
{ {
GHashTable *optlist; GHashTable *optlist;
SERVER_SETUP_REC *rec; SERVER_SETUP_REC *rec, *tmp;
char *addr, *portstr, *password, *value, *chatnet; char *addr, *portstr, *password, *value, *chatnet, *old_chatnet;
void *free_arg; void *free_arg;
gboolean newrec; gboolean newrec;
int port; int port, old_port, add_port;
if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_OPTIONS, if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_OPTIONS,
"server add", &optlist, &addr, &portstr, &password)) "server add", &optlist, &addr, &portstr, &password))
@ -120,27 +122,39 @@ static void cmd_server_add_modify(const char *data, gboolean add)
if (*addr == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); if (*addr == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
value = g_hash_table_lookup(optlist, "port"); port = old_port = -1;
if (*portstr != '\0') value = g_hash_table_lookup(optlist, "port");
port = atoi(portstr); if (value != NULL && *value != '\0')
else if (value != NULL && *value != '\0') port = add_port = atoi(value);
port = atoi(value);
else if (g_hash_table_lookup(optlist, "tls") || else if (g_hash_table_lookup(optlist, "tls") ||
g_hash_table_lookup(optlist, "ssl")) g_hash_table_lookup(optlist, "ssl"))
port = DEFAULT_SERVER_ADD_TLS_PORT; add_port = DEFAULT_SERVER_ADD_TLS_PORT;
else else
port = DEFAULT_SERVER_ADD_PORT; add_port = DEFAULT_SERVER_ADD_PORT;
if (*portstr != '\0')
old_port = atoi(portstr);
chatnet = g_hash_table_lookup(optlist, "network"); chatnet = g_hash_table_lookup(optlist, "network");
rec = server_setup_find(addr, port, chatnet); rec = server_setup_find(addr, old_port != -1 ? old_port : add_port, chatnet);
if (old_port == -1 && rec != NULL)
old_port = rec->port;
if (rec == NULL) { if (port == -1)
port = old_port != -1 ? old_port : add_port;
/* make sure the new port doesn't exist */
tmp = server_setup_find(addr, port, chatnet);
if (tmp != NULL && tmp->port == port)
rec = tmp;
if (rec == NULL || (rec->port != old_port && rec->port != port)) {
newrec = TRUE; newrec = TRUE;
if (add == FALSE) { if (add == FALSE) {
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, TXT_SETUPSERVER_NOT_FOUND,
TXT_SETUPSERVER_NOT_FOUND, addr, port); addr, old_port == -1 ? port : old_port);
cmd_params_free(free_arg); cmd_params_free(free_arg);
return; return;
} }
@ -154,8 +168,9 @@ static void cmd_server_add_modify(const char *data, gboolean add)
rec->port = port; rec->port = port;
} else { } else {
newrec = FALSE; newrec = FALSE;
if (*portstr != '\0' || g_hash_table_lookup(optlist, "port")) old_chatnet = g_strdup(rec->chatnet);
rec->port = port; old_port = rec->port;
rec->port = port;
if (*password != '\0') g_free_and_null(rec->password); if (*password != '\0') g_free_and_null(rec->password);
if (g_hash_table_lookup(optlist, "host")) { if (g_hash_table_lookup(optlist, "host")) {
@ -198,12 +213,16 @@ static void cmd_server_add_modify(const char *data, gboolean add)
value = g_hash_table_lookup(optlist, "ssl_cafile"); value = g_hash_table_lookup(optlist, "ssl_cafile");
if (value != NULL && *value != '\0') if (value != NULL && *value != '\0')
rec->tls_cafile = g_strdup(value); rec->tls_cafile = g_strdup(value);
else if (value != NULL && *value == '\0')
g_free_and_null(rec->tls_cafile);
value = g_hash_table_lookup(optlist, "tls_capath"); value = g_hash_table_lookup(optlist, "tls_capath");
if (value == NULL) if (value == NULL)
value = g_hash_table_lookup(optlist, "ssl_capath"); value = g_hash_table_lookup(optlist, "ssl_capath");
if (value != NULL && *value != '\0') if (value != NULL && *value != '\0')
rec->tls_capath = g_strdup(value); rec->tls_capath = g_strdup(value);
else if (value != NULL && *value == '\0')
g_free_and_null(rec->tls_capath);
value = g_hash_table_lookup(optlist, "tls_ciphers"); value = g_hash_table_lookup(optlist, "tls_ciphers");
if (value == NULL) if (value == NULL)
@ -259,7 +278,13 @@ static void cmd_server_add_modify(const char *data, gboolean add)
signal_emit("server add fill", 3, rec, optlist, GINT_TO_POINTER(add)); signal_emit("server add fill", 3, rec, optlist, GINT_TO_POINTER(add));
server_setup_add(rec); if (newrec) {
server_setup_add(rec);
} else {
server_setup_modify(rec, old_port, old_chatnet);
g_free(old_chatnet);
}
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE,
TXT_SETUPSERVER_ADDED, addr, port); TXT_SETUPSERVER_ADDED, addr, port);
@ -282,12 +307,14 @@ static void cmd_server_remove(const char *data)
SERVER_SETUP_REC *rec; SERVER_SETUP_REC *rec;
char *addr, *port, *chatnet; char *addr, *port, *chatnet;
void *free_arg; void *free_arg;
int portnum;
if (!cmd_get_params(data, &free_arg, 3, &addr, &port, &chatnet)) if (!cmd_get_params(data, &free_arg, 3, &addr, &port, &chatnet))
return; return;
if (*addr == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); if (*addr == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
if (*port == '\0') { if (*port == '\0') {
portnum = DEFAULT_SERVER_ADD_PORT;
if (*chatnet == '\0') if (*chatnet == '\0')
rec = server_setup_find(addr, -1, NULL); rec = server_setup_find(addr, -1, NULL);
else else
@ -295,17 +322,21 @@ static void cmd_server_remove(const char *data)
} }
else else
{ {
portnum = atoi(port);
if (*chatnet == '\0') if (*chatnet == '\0')
rec = server_setup_find(addr, atoi(port), NULL); rec = server_setup_find(addr, portnum, NULL);
else else
rec = server_setup_find(addr, atoi(port), chatnet); rec = server_setup_find(addr, portnum, chatnet);
} }
if (rec == NULL) if (rec == NULL)
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, TXT_SETUPSERVER_NOT_FOUND, addr, port); printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, TXT_SETUPSERVER_NOT_FOUND, addr,
portnum);
else { else {
portnum = rec->port;
server_setup_remove(rec); server_setup_remove(rec);
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, TXT_SETUPSERVER_REMOVED, addr, port); printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, TXT_SETUPSERVER_REMOVED, addr,
portnum);
} }
cmd_params_free(free_arg); cmd_params_free(free_arg);

View File

@ -34,6 +34,7 @@
#include <irssi/src/core/recode.h> #include <irssi/src/core/recode.h>
#include <irssi/src/core/utf8.h> #include <irssi/src/core/utf8.h>
#include <irssi/src/core/misc.h> #include <irssi/src/core/misc.h>
#include <irssi/src/core/refstrings.h>
static const char *format_backs = "04261537"; static const char *format_backs = "04261537";
static const char *format_fores = "kbgcrmyw"; static const char *format_fores = "kbgcrmyw";
@ -46,6 +47,8 @@ static int hide_text_style, hide_server_tags, hide_colors;
static int timestamp_level; static int timestamp_level;
static int timestamp_timeout; static int timestamp_timeout;
static GHashTable *global_meta;
int format_find_tag(const char *module, const char *tag) int format_find_tag(const char *module, const char *tag)
{ {
FORMAT_REC *formats; FORMAT_REC *formats;
@ -453,6 +456,27 @@ void format_read_arglist(va_list va, FORMAT_REC *format,
} }
} }
void format_dest_meta_stash(TEXT_DEST_REC *dest, const char *meta_key, const char *meta_value)
{
g_hash_table_replace(dest->meta, i_refstr_intern(meta_key), g_strdup(meta_value));
}
const char *format_dest_meta_stash_find(TEXT_DEST_REC *dest, const char *meta_key)
{
return g_hash_table_lookup(dest->meta, meta_key);
}
void format_dest_meta_clear_all(TEXT_DEST_REC *dest)
{
g_hash_table_remove_all(dest->meta);
}
static void clear_global_meta(WINDOW_REC *window, TEXT_DEST_REC *dest)
{
if (dest != NULL && dest->meta == global_meta)
g_hash_table_remove_all(global_meta);
}
void format_create_dest_tag_meta(TEXT_DEST_REC *dest, void *server, const char *server_tag, void format_create_dest_tag_meta(TEXT_DEST_REC *dest, void *server, const char *server_tag,
const char *target, int level, WINDOW_REC *window, const char *target, int level, WINDOW_REC *window,
GHashTable *meta) GHashTable *meta)
@ -465,7 +489,7 @@ void format_create_dest_tag_meta(TEXT_DEST_REC *dest, void *server, const char *
dest->level = level; dest->level = level;
dest->window = window != NULL ? window : dest->window = window != NULL ? window :
window_find_closest(server, target, level); window_find_closest(server, target, level);
dest->meta = meta; dest->meta = meta != NULL ? meta : global_meta;
} }
void format_create_dest_tag(TEXT_DEST_REC *dest, void *server, const char *server_tag, void format_create_dest_tag(TEXT_DEST_REC *dest, void *server, const char *server_tag,
@ -1705,12 +1729,18 @@ static void read_settings(void)
void formats_init(void) void formats_init(void)
{ {
signal_gui_print_text = signal_get_uniq_id("gui print text"); signal_gui_print_text = signal_get_uniq_id("gui print text");
global_meta =
g_hash_table_new_full(g_str_hash, (GEqualFunc) g_str_equal,
(GDestroyNotify) i_refstr_release, (GDestroyNotify) g_free);
read_settings(); read_settings();
signal_add("setup changed", (SIGNAL_FUNC) read_settings); signal_add("setup changed", (SIGNAL_FUNC) read_settings);
signal_add_last("gui print text finished", (SIGNAL_FUNC) clear_global_meta);
} }
void formats_deinit(void) void formats_deinit(void)
{ {
g_hash_table_destroy(global_meta);
signal_remove("setup changed", (SIGNAL_FUNC) read_settings); signal_remove("setup changed", (SIGNAL_FUNC) read_settings);
signal_remove("gui print text finished", (SIGNAL_FUNC) clear_global_meta);
} }

View File

@ -63,10 +63,15 @@ typedef struct _TEXT_DEST_REC {
int hilight_priority; int hilight_priority;
char *hilight_color; char *hilight_color;
int flags; int flags; /* PRINT_FLAG */
GHashTable *meta; GHashTable *meta;
} TEXT_DEST_REC; } TEXT_DEST_REC;
typedef struct _LINE_INFO_META_REC {
gint64 server_time;
GHashTable *hash;
} LINE_INFO_META_REC;
#define window_get_theme(window) \ #define window_get_theme(window) \
(window != NULL && (window)->theme != NULL ? \ (window != NULL && (window)->theme != NULL ? \
(window)->theme : current_theme) (window)->theme : current_theme)
@ -116,12 +121,16 @@ char *format_get_line_start(THEME_REC *theme, TEXT_DEST_REC *dest, time_t t);
void format_create_dest(TEXT_DEST_REC *dest, void format_create_dest(TEXT_DEST_REC *dest,
void *server, const char *target, void *server, const char *target,
int level, WINDOW_REC *window); int level, WINDOW_REC *window);
void format_create_dest_tag(TEXT_DEST_REC *dest, void *server, void format_create_dest_tag(TEXT_DEST_REC *dest, void *server, const char *server_tag,
const char *server_tag, const char *target, const char *target, int level, WINDOW_REC *window);
int level, WINDOW_REC *window);
void format_newline(TEXT_DEST_REC *dest); void format_newline(TEXT_DEST_REC *dest);
/* manipulate the meta table of a dest */
void format_dest_meta_stash(TEXT_DEST_REC *dest, const char *meta_key, const char *meta_value);
const char *format_dest_meta_stash_find(TEXT_DEST_REC *dest, const char *meta_key);
void format_dest_meta_clear_all(TEXT_DEST_REC *dest);
/* Return how many characters in `str' must be skipped before `len' /* Return how many characters in `str' must be skipped before `len'
characters of text is skipped. */ characters of text is skipped. */
int strip_real_length(const char *str, int len, int strip_real_length(const char *str, int len,

View File

@ -323,6 +323,71 @@ void hilight_update_text_dest(TEXT_DEST_REC *dest, HILIGHT_REC *rec)
static void hilight_print(int index, HILIGHT_REC *rec); static void hilight_print(int index, HILIGHT_REC *rec);
static void sig_render_line_text(TEXT_DEST_REC *dest, GString *str, LINE_INFO_META_REC *meta)
{
char *color, *tmp, *tmp2;
if (meta == NULL || meta->hash == NULL)
return;
color = g_hash_table_lookup(meta->hash, "hilight-color");
if ((tmp = g_hash_table_lookup(meta->hash, "hilight-line")) != NULL) {
/* hilight whole line */
tmp = strip_codes(str->str);
color = format_string_expand(
color != NULL ? color : settings_get_str("hilight_color"), NULL);
g_string_truncate(str, 0);
g_string_append(str, color);
g_string_append(str, tmp);
g_free(color);
g_free(tmp);
} else if ((tmp = g_hash_table_lookup(meta->hash, "hilight-start")) != NULL &&
(tmp2 = g_hash_table_lookup(meta->hash, "hilight-end")) != NULL) {
/* hilight part of the line */
int hilight_start, hilight_end;
int pos, color_pos, color_len;
char *middle;
GString *str2;
hilight_start = atoi(tmp);
hilight_end = atoi(tmp2);
/* start of the line */
pos = strip_real_length(str->str, hilight_start, NULL, NULL);
str2 = g_string_new_len(str->str, pos);
/* color */
color = format_string_expand(
color != NULL ? color : settings_get_str("hilight_color"), NULL);
g_string_append(str2, color);
g_free(color);
/* middle of the line, stripped */
middle = strip_codes(str->str + pos);
g_string_append_len(str2, middle, hilight_end - hilight_start);
g_free(middle);
/* end of the line */
pos = strip_real_length(str->str, hilight_end, &color_pos, &color_len);
if (color_pos > 0) {
g_string_append_len(str2, str->str + color_pos, color_len);
} else {
/* no colors in line, change back to default */
g_string_append_c(str2, 4);
g_string_append_c(str2, FORMAT_STYLE_DEFAULTS);
}
g_string_append(str2, str->str + pos);
g_string_assign(str, g_string_free(str2, FALSE));
}
}
static void sig_print_text(TEXT_DEST_REC *dest, const char *text, static void sig_print_text(TEXT_DEST_REC *dest, const char *text,
const char *stripped) const char *stripped)
{ {
@ -372,39 +437,50 @@ static void sig_print_text(TEXT_DEST_REC *dest, const char *text,
char *tmp = strip_codes(text); char *tmp = strip_codes(text);
newstr = g_strconcat(color, tmp, NULL); newstr = g_strconcat(color, tmp, NULL);
g_free(tmp); g_free(tmp);
format_dest_meta_stash(dest, "hilight-line", "\001");
} else { } else {
/* hilight part of the line */ /* hilight part of the line */
GString *tmp; GString *str;
char *middle; char *middle, *tmp;
int pos, color_pos, color_len; int pos, color_pos, color_len;
/* start of the line */ /* start of the line */
pos = strip_real_length(text, hilight_start, NULL, NULL); pos = strip_real_length(text, hilight_start, NULL, NULL);
tmp = g_string_new_len(text, pos); str = g_string_new_len(text, pos);
/* color */ /* color */
g_string_append(tmp, color); g_string_append(str, color);
/* middle of the line, stripped */ /* middle of the line, stripped */
middle = strip_codes(text + pos); middle = strip_codes(text + pos);
g_string_append_len(tmp, middle, hilight_len); g_string_append_len(str, middle, hilight_len);
g_free(middle); g_free(middle);
/* end of the line */ /* end of the line */
pos = strip_real_length(text, hilight_end, pos = strip_real_length(text, hilight_end,
&color_pos, &color_len); &color_pos, &color_len);
if (color_pos > 0) { if (color_pos > 0) {
g_string_append_len(tmp, text + color_pos, color_len); g_string_append_len(str, text + color_pos, color_len);
} else { } else {
/* no colors in line, change back to default */ /* no colors in line, change back to default */
g_string_append_c(tmp, 4); g_string_append_c(str, 4);
g_string_append_c(tmp, FORMAT_STYLE_DEFAULTS); g_string_append_c(str, FORMAT_STYLE_DEFAULTS);
} }
g_string_append(tmp, text + pos); g_string_append(str, text + pos);
newstr = tmp->str; newstr = str->str;
g_string_free(tmp, FALSE); g_string_free(str, FALSE);
format_dest_meta_stash(dest, "hilight-start",
tmp = g_strdup_printf("%d", hilight_start));
g_free(tmp);
format_dest_meta_stash(dest, "hilight-end",
tmp = g_strdup_printf("%d", hilight_end));
g_free(tmp);
} }
if (hilight->color != NULL)
format_dest_meta_stash(dest, "hilight-color", hilight->color);
signal_emit("print text", 3, dest, newstr, stripped); signal_emit("print text", 3, dest, newstr, stripped);
@ -721,6 +797,7 @@ void hilight_text_init(void)
read_hilight_config(); read_hilight_config();
signal_add_first("print text", (SIGNAL_FUNC) sig_print_text); signal_add_first("print text", (SIGNAL_FUNC) sig_print_text);
signal_add("gui render line text", (SIGNAL_FUNC) sig_render_line_text);
signal_add("setup reread", (SIGNAL_FUNC) read_hilight_config); signal_add("setup reread", (SIGNAL_FUNC) read_hilight_config);
signal_add("setup changed", (SIGNAL_FUNC) read_settings); signal_add("setup changed", (SIGNAL_FUNC) read_settings);
@ -735,6 +812,7 @@ void hilight_text_deinit(void)
nickmatch_deinit(nickmatch); nickmatch_deinit(nickmatch);
signal_remove("print text", (SIGNAL_FUNC) sig_print_text); signal_remove("print text", (SIGNAL_FUNC) sig_print_text);
signal_remove("gui render line text", (SIGNAL_FUNC) sig_render_line_text);
signal_remove("setup reread", (SIGNAL_FUNC) read_hilight_config); signal_remove("setup reread", (SIGNAL_FUNC) read_hilight_config);
signal_remove("setup changed", (SIGNAL_FUNC) read_settings); signal_remove("setup changed", (SIGNAL_FUNC) read_settings);

View File

@ -22,6 +22,7 @@
#include <irssi/src/fe-common/core/formats.h> #include <irssi/src/fe-common/core/formats.h>
FORMAT_REC fecommon_core_formats[] = { FORMAT_REC fecommon_core_formats[] = {
/* clang-format off */
{ MODULE_NAME, "Core", 0 }, { MODULE_NAME, "Core", 0 },
/* ---- */ /* ---- */
@ -87,8 +88,8 @@ FORMAT_REC fecommon_core_formats[] = {
{ "server_reconnect_removed", "Removed reconnection to server {server $0} port {hilight $1}", 3, { 0, 1, 0 } }, { "server_reconnect_removed", "Removed reconnection to server {server $0} port {hilight $1}", 3, { 0, 1, 0 } },
{ "server_reconnect_not_found", "Reconnection tag {server $0} not found", 1, { 0 } }, { "server_reconnect_not_found", "Reconnection tag {server $0} not found", 1, { 0 } },
{ "setupserver_added", "Server {server $0} saved", 2, { 0, 1 } }, { "setupserver_added", "Server {server $0} saved", 2, { 0, 1 } },
{ "setupserver_removed", "Server {server $0} removed", 2, { 0, 1 } }, { "setupserver_removed", "Server {server $0} {hilight $1} removed", 2, { 0, 1 } },
{ "setupserver_not_found", "Server {server $0} not found", 2, { 0, 1 } }, { "setupserver_not_found", "Server {server $0} {hilight $1} not found", 2, { 0, 1 } },
{ "your_nick", "Your nickname is {nick $0}", 1, { 0 } }, { "your_nick", "Your nickname is {nick $0}", 1, { 0 } },
/* ---- */ /* ---- */
@ -316,4 +317,5 @@ FORMAT_REC fecommon_core_formats[] = {
{ "tls_protocol_version", "Protocol: {hilight $0} ({hilight $1} bit, {hilight $2})", 3, { 0, 1, 0 } }, { "tls_protocol_version", "Protocol: {hilight $0} ({hilight $1} bit, {hilight $2})", 3, { 0, 1, 0 } },
{ NULL, NULL, 0 } { NULL, NULL, 0 }
/* clang-format on */
}; };

View File

@ -152,6 +152,7 @@ int LLVMFuzzerInitialize(int *argc, char ***argv) {
args_execute(0, NULL); args_execute(0, NULL);
core_preinit((*argv)[0]); core_preinit((*argv)[0]);
core_init(); core_init();
irssi_ssl_init();
irc_init(); irc_init();
fe_common_core_init(); fe_common_core_init();
fe_common_irc_init(); fe_common_irc_init();

View File

@ -1,6 +1,7 @@
#include "module.h" #include "module.h"
#include <irssi/src/core/expandos.h> #include <irssi/src/core/expandos.h>
#include <irssi/src/core/levels.h> #include <irssi/src/core/levels.h>
#include <irssi/src/core/misc.h>
#include <irssi/src/core/refstrings.h> #include <irssi/src/core/refstrings.h>
#include <irssi/src/core/servers.h> #include <irssi/src/core/servers.h>
#include <irssi/src/core/settings.h> #include <irssi/src/core/settings.h>
@ -16,21 +17,7 @@
TEXT_BUFFER_REC *color_buf; TEXT_BUFFER_REC *color_buf;
gboolean scrollback_format; gboolean scrollback_format;
gboolean show_server_time; gboolean show_server_time;
int signal_gui_render_line_text;
#if GLIB_CHECK_VERSION(2, 56, 0)
/* nothing */
#else
/* compatibility code for old GLib */
static GDateTime *g_date_time_new_from_iso8601(const gchar *iso_date, GTimeZone *default_tz)
{
GTimeVal time;
if (g_time_val_from_iso8601(iso_date, &time)) {
return g_date_time_new_from_timeval_utc(&time);
} else {
return NULL;
}
}
#endif
static void collector_free(GSList **collector) static void collector_free(GSList **collector)
{ {
@ -102,7 +89,7 @@ static void format_rec_set_dest(TEXT_BUFFER_FORMAT_REC *rec, const TEXT_DEST_REC
rec->flags = dest->flags & ~PRINT_FLAG_FORMAT; rec->flags = dest->flags & ~PRINT_FLAG_FORMAT;
} }
void textbuffer_meta_rec_free(TEXT_BUFFER_META_REC *rec) void textbuffer_meta_rec_free(LINE_INFO_META_REC *rec)
{ {
if (rec == NULL) if (rec == NULL)
return; return;
@ -113,18 +100,18 @@ void textbuffer_meta_rec_free(TEXT_BUFFER_META_REC *rec)
g_free(rec); g_free(rec);
} }
static void meta_hash_create(struct _TEXT_BUFFER_META_REC *meta) static void meta_hash_create(struct _LINE_INFO_META_REC *meta)
{ {
if (meta->hash == NULL) { if (meta->hash == NULL) {
meta->hash = g_hash_table_new_full(g_str_hash, (GEqualFunc) g_strcmp0, meta->hash = g_hash_table_new_full(g_str_hash, (GEqualFunc) g_str_equal,
(GDestroyNotify) i_refstr_release, (GDestroyNotify) i_refstr_release,
(GDestroyNotify) g_free); (GDestroyNotify) g_free);
} }
} }
static TEXT_BUFFER_META_REC *line_meta_create(GHashTable *meta_hash) static LINE_INFO_META_REC *line_meta_create(GHashTable *meta_hash)
{ {
struct _TEXT_BUFFER_META_REC *meta; struct _LINE_INFO_META_REC *meta;
GHashTableIter iter; GHashTableIter iter;
const char *key; const char *key;
const char *val; const char *val;
@ -132,7 +119,7 @@ static TEXT_BUFFER_META_REC *line_meta_create(GHashTable *meta_hash)
if (meta_hash == NULL || g_hash_table_size(meta_hash) == 0) if (meta_hash == NULL || g_hash_table_size(meta_hash) == 0)
return NULL; return NULL;
meta = g_new0(struct _TEXT_BUFFER_META_REC, 1); meta = g_new0(struct _LINE_INFO_META_REC, 1);
g_hash_table_iter_init(&iter, meta_hash); g_hash_table_iter_init(&iter, meta_hash);
while (g_hash_table_iter_next(&iter, (gpointer *) &key, (gpointer *) &val)) { while (g_hash_table_iter_next(&iter, (gpointer *) &key, (gpointer *) &val)) {
@ -278,7 +265,7 @@ static void sig_gui_print_text_finished(WINDOW_REC *window, TEXT_DEST_REC *dest)
info->meta = line_meta_create(dest->meta); info->meta = line_meta_create(dest->meta);
info->level |= MSGLEVEL_FORMAT; info->level = dest->level | MSGLEVEL_FORMAT;
/* the line will be inserted into the view with textbuffer_view_insert_line by /* the line will be inserted into the view with textbuffer_view_insert_line by
gui-printtext.c:view_add_eol */ gui-printtext.c:view_add_eol */
@ -362,8 +349,8 @@ char *textbuffer_line_get_text(TEXT_BUFFER_REC *buffer, LINE_REC *line, gboolean
THEME_REC *theme; THEME_REC *theme;
int formatnum; int formatnum;
TEXT_BUFFER_FORMAT_REC *format_rec; TEXT_BUFFER_FORMAT_REC *format_rec;
TEXT_BUFFER_META_REC *meta; LINE_INFO_META_REC *meta;
char *str; char *tmp2;
curr = line; curr = line;
line = NULL; line = NULL;
@ -396,6 +383,8 @@ char *textbuffer_line_get_text(TEXT_BUFFER_REC *buffer, LINE_REC *line, gboolean
} }
if (text != NULL && *text != '\0') { if (text != NULL && *text != '\0') {
GString *str;
reference_time = curr->info.time; reference_time = curr->info.time;
if (show_server_time && meta != NULL && meta->server_time != 0) { if (show_server_time && meta != NULL && meta->server_time != 0) {
current_time = meta->server_time; current_time = meta->server_time;
@ -403,18 +392,27 @@ char *textbuffer_line_get_text(TEXT_BUFFER_REC *buffer, LINE_REC *line, gboolean
current_time = curr->info.time; current_time = curr->info.time;
} }
str = g_string_new(text);
signal_emit_id(signal_gui_render_line_text, 3, &dest, str, meta);
if (g_strcmp0(text, str->str) == 0) {
g_string_free(str, TRUE);
} else {
g_free(text);
text = g_string_free(str, FALSE);
}
tmp = format_get_level_tag(theme, &dest); tmp = format_get_level_tag(theme, &dest);
str = !theme->info_eol ? format_add_linestart(text, tmp) : tmp2 = !theme->info_eol ? format_add_linestart(text, tmp) :
format_add_lineend(text, tmp); format_add_lineend(text, tmp);
g_free_not_null(tmp); g_free_not_null(tmp);
g_free_not_null(text); g_free_not_null(text);
text = str; text = tmp2;
tmp = format_get_line_start(theme, &dest, current_time); tmp = format_get_line_start(theme, &dest, current_time);
str = !theme->info_eol ? format_add_linestart(text, tmp) : tmp2 = !theme->info_eol ? format_add_linestart(text, tmp) :
format_add_lineend(text, tmp); format_add_lineend(text, tmp);
g_free_not_null(tmp); g_free_not_null(tmp);
g_free_not_null(text); g_free_not_null(text);
text = str; text = tmp2;
/* str = g_strconcat(text, "\n", NULL); */ /* str = g_strconcat(text, "\n", NULL); */
/* g_free(text); */ /* g_free(text); */
@ -447,6 +445,8 @@ static void read_settings(void)
void textbuffer_formats_init(void) void textbuffer_formats_init(void)
{ {
signal_gui_render_line_text = signal_get_uniq_id("gui render line text");
settings_add_bool("lookandfeel", "scrollback_format", TRUE); settings_add_bool("lookandfeel", "scrollback_format", TRUE);
settings_add_bool("lookandfeel", "show_server_time", FALSE); settings_add_bool("lookandfeel", "show_server_time", FALSE);

View File

@ -2,11 +2,7 @@
#define IRSSI_FE_TEXT_TEXTBUFFER_FORMATS_H #define IRSSI_FE_TEXT_TEXTBUFFER_FORMATS_H
#include <irssi/src/fe-text/textbuffer.h> #include <irssi/src/fe-text/textbuffer.h>
#include <irssi/src/fe-common/core/formats.h>
typedef struct _TEXT_BUFFER_META_REC {
gint64 server_time;
GHashTable *hash;
} TEXT_BUFFER_META_REC;
typedef struct _TEXT_BUFFER_FORMAT_REC { typedef struct _TEXT_BUFFER_FORMAT_REC {
char *module; char *module;
@ -22,7 +18,7 @@ typedef struct _TEXT_BUFFER_FORMAT_REC {
} TEXT_BUFFER_FORMAT_REC; } TEXT_BUFFER_FORMAT_REC;
void textbuffer_format_rec_free(TEXT_BUFFER_FORMAT_REC *rec); void textbuffer_format_rec_free(TEXT_BUFFER_FORMAT_REC *rec);
void textbuffer_meta_rec_free(TEXT_BUFFER_META_REC *rec); void textbuffer_meta_rec_free(LINE_INFO_META_REC *rec);
char *textbuffer_line_get_text(TEXT_BUFFER_REC *buffer, LINE_REC *line, gboolean raw); char *textbuffer_line_get_text(TEXT_BUFFER_REC *buffer, LINE_REC *line, gboolean raw);
void textbuffer_formats_init(void); void textbuffer_formats_init(void);
void textbuffer_formats_deinit(void); void textbuffer_formats_deinit(void);

View File

@ -24,7 +24,7 @@ typedef struct {
int level; int level;
time_t time; time_t time;
char *text; char *text;
struct _TEXT_BUFFER_META_REC *meta; struct _LINE_INFO_META_REC *meta;
struct _TEXT_BUFFER_FORMAT_REC *format; struct _TEXT_BUFFER_FORMAT_REC *format;
} LINE_INFO_REC; } LINE_INFO_REC;

View File

@ -53,9 +53,9 @@ loop:
/* here are the WHOX commands we send. the full spec can be found on [1]. /* here are the WHOX commands we send. the full spec can be found on [1].
(1) WHOX_CHANNEL_FULL_CMD for getting the user list when we join a channel. we request the fields (1) WHOX_CHANNEL_FULL_CMD for getting the user list when we join a channel. we request the fields
c (channel), u (user), h (host), n (nick), f (flags), d (hops), a (important, account!), and c (channel), u (user), h (host), n (nick), f (flags), d (hops), a (account), and r (the real
r (the real name goes last because it os the only that can contain spaces.) we request all name goes last because it is the only that can contain spaces.) we request all those fields
those fields as they are also included in the "regular" WHO reply we would get without WHOX. as they are also included in the "regular" WHO reply we would get without WHOX.
(2) WHOX_USERACCOUNT_CMD for getting the account names of people that joined. this code is (2) WHOX_USERACCOUNT_CMD for getting the account names of people that joined. this code is
obviously only used when we don't have extended-joins. we request n (nick) and a (account) obviously only used when we don't have extended-joins. we request n (nick) and a (account)
@ -265,7 +265,7 @@ static void query_send(IRC_SERVER_REC *server, int query)
cmd = NULL; cmd = NULL;
} }
irc_send_cmd(server, cmd); irc_send_cmd_later(server, cmd);
g_free(chanstr); g_free(chanstr);
g_free(chanstr_commas); g_free(chanstr_commas);
@ -440,6 +440,7 @@ void irc_channels_query_purge_accountquery(IRC_SERVER_REC *server, const char *n
g_free(cmd); g_free(cmd);
server->cmdcount--; server->cmdcount--;
server->cmdlater--;
} else { } else {
prev = tmp->next; prev = tmp->next;
} }
@ -528,7 +529,10 @@ static void sig_event_join(IRC_SERVER_REC *server, const char *data, const char
} }
if (g_hash_table_size(chanrec->nicks) < settings_get_int("channel_max_who_sync") && if (g_hash_table_size(chanrec->nicks) < settings_get_int("channel_max_who_sync") &&
server->isupport != NULL && g_hash_table_lookup(server->isupport, "whox") != NULL) { server->isupport != NULL && g_hash_table_lookup(server->isupport, "whox") != NULL &&
server->split_servers == NULL &&
g_hash_table_size(server->chanqueries->accountqueries) <
settings_get_int("account_max_chase")) {
char *cmd; char *cmd;
server_redirect_event(server, "who user", 1, nick, -1, server_redirect_event(server, "who user", 1, nick, -1,
"chanquery useraccount abort", /* failure signal */ "chanquery useraccount abort", /* failure signal */
@ -538,7 +542,7 @@ static void sig_event_join(IRC_SERVER_REC *server, const char *data, const char
cmd = g_strdup_printf(WHOX_USERACCOUNT_CMD, nick); cmd = g_strdup_printf(WHOX_USERACCOUNT_CMD, nick);
g_hash_table_add(server->chanqueries->accountqueries, g_strdup(nick)); g_hash_table_add(server->chanqueries->accountqueries, g_strdup(nick));
/* queue the command */ /* queue the command */
irc_send_cmd_full(server, cmd, FALSE, FALSE, FALSE); irc_send_cmd_later(server, cmd);
g_free(cmd); g_free(cmd);
} }
} }
@ -635,6 +639,7 @@ void channels_query_init(void)
{ {
settings_add_bool("misc", "channel_sync", TRUE); settings_add_bool("misc", "channel_sync", TRUE);
settings_add_int("misc", "channel_max_who_sync", 1000); settings_add_int("misc", "channel_max_who_sync", 1000);
settings_add_int("misc", "account_max_chase", 10);
signal_add("server connected", (SIGNAL_FUNC) sig_connected); signal_add("server connected", (SIGNAL_FUNC) sig_connected);
signal_add("server disconnected", (SIGNAL_FUNC) sig_disconnected); signal_add("server disconnected", (SIGNAL_FUNC) sig_disconnected);

View File

@ -63,6 +63,20 @@ IRC_CHANNEL_REC *irc_channel_create(IRC_SERVER_REC *server, const char *name,
#define get_join_key(key) \ #define get_join_key(key) \
(((key) == NULL || *(key) == '\0') ? "x" : (key)) (((key) == NULL || *(key) == '\0') ? "x" : (key))
static char *force_channel_name(IRC_SERVER_REC *server, const char *name)
{
char *chantypes;
if (server_ischannel(SERVER(server), name))
return g_strdup(name);
chantypes = g_hash_table_lookup(server->isupport, "chantypes");
if (chantypes == NULL || *chantypes == '\0')
chantypes = "#";
return g_strdup_printf("%c%s", *chantypes, name);
}
static void irc_channels_join(IRC_SERVER_REC *server, const char *data, static void irc_channels_join(IRC_SERVER_REC *server, const char *data,
int automatic) int automatic)
{ {
@ -99,8 +113,7 @@ static void irc_channels_join(IRC_SERVER_REC *server, const char *data,
tmp = chanlist; tmp = chanlist;
for (;; tmp++) { for (;; tmp++) {
if (*tmp != NULL) { if (*tmp != NULL) {
channel = server_ischannel(SERVER(server), *tmp) ? g_strdup(*tmp) : channel = force_channel_name(server, *tmp);
g_strdup_printf("#%s", *tmp);
chanrec = irc_channel_find(server, channel); chanrec = irc_channel_find(server, channel);
if (chanrec == NULL) { if (chanrec == NULL) {
@ -170,17 +183,14 @@ static void irc_channels_join(IRC_SERVER_REC *server, const char *data,
} }
/* function for finding IRC channels - adds support for !channels */ /* function for finding IRC channels - adds support for !channels */
static CHANNEL_REC *irc_channel_find_server(SERVER_REC *server, static CHANNEL_REC *irc_channel_find_server(IRC_SERVER_REC *server, const char *channel)
const char *channel)
{ {
GSList *tmp; GSList *tmp;
char *fmt_channel; char *fmt_channel;
/* if 'channel' has no leading # this lookup is going to fail, add a /* if 'channel' has no leading # this lookup is going to fail, add a
* octothorpe in front of it to handle this case. */ * octothorpe in front of it to handle this case. */
fmt_channel = server_ischannel(SERVER(server), channel) ? fmt_channel = force_channel_name(server, channel);
g_strdup(channel) :
g_strdup_printf("#%s", channel);
for (tmp = server->channels; tmp != NULL; tmp = tmp->next) { for (tmp = server->channels; tmp != NULL; tmp = tmp->next) {
CHANNEL_REC *rec = tmp->data; CHANNEL_REC *rec = tmp->data;
@ -189,12 +199,12 @@ static CHANNEL_REC *irc_channel_find_server(SERVER_REC *server,
continue; continue;
/* check both !ABCDEchannel and !channel */ /* check both !ABCDEchannel and !channel */
if (IRC_SERVER(server)->nick_comp_func(fmt_channel, rec->name) == 0) { if (server->nick_comp_func(fmt_channel, rec->name) == 0) {
g_free(fmt_channel); g_free(fmt_channel);
return rec; return rec;
} }
if (IRC_SERVER(server)->nick_comp_func(fmt_channel, rec->visible_name) == 0) { if (server->nick_comp_func(fmt_channel, rec->visible_name) == 0) {
g_free(fmt_channel); g_free(fmt_channel);
return rec; return rec;
} }
@ -210,7 +220,8 @@ static void sig_server_connected(SERVER_REC *server)
if (!IS_IRC_SERVER(server)) if (!IS_IRC_SERVER(server))
return; return;
server->channel_find_func = irc_channel_find_server; server->channel_find_func =
(CHANNEL_REC * (*) (SERVER_REC *, const char *) ) irc_channel_find_server;
server->channels_join = (void (*) (SERVER_REC *, const char *, int)) server->channels_join = (void (*) (SERVER_REC *, const char *, int))
irc_channels_join; irc_channels_join;
} }

View File

@ -121,9 +121,9 @@ static void sig_server_setup_fill_chatnet(IRC_SERVER_CONNECT_REC *conn,
if (ircnet->sasl_mechanism != NULL) { if (ircnet->sasl_mechanism != NULL) {
if (!g_ascii_strcasecmp(ircnet->sasl_mechanism, "plain")) { if (!g_ascii_strcasecmp(ircnet->sasl_mechanism, "plain")) {
/* The PLAIN method needs both the username and the password */ /* The PLAIN method needs both the username and the password */
conn->sasl_mechanism = SASL_MECHANISM_PLAIN;
if (ircnet->sasl_username != NULL && *ircnet->sasl_username && if (ircnet->sasl_username != NULL && *ircnet->sasl_username &&
ircnet->sasl_password != NULL && *ircnet->sasl_password) { ircnet->sasl_password != NULL && *ircnet->sasl_password) {
conn->sasl_mechanism = SASL_MECHANISM_PLAIN;
conn->sasl_username = g_strdup(ircnet->sasl_username); conn->sasl_username = g_strdup(ircnet->sasl_username);
conn->sasl_password = g_strdup(ircnet->sasl_password); conn->sasl_password = g_strdup(ircnet->sasl_password);
} else } else
@ -188,6 +188,7 @@ static void init_userinfo(void)
static void sig_server_setup_read(IRC_SERVER_SETUP_REC *rec, CONFIG_NODE *node) static void sig_server_setup_read(IRC_SERVER_SETUP_REC *rec, CONFIG_NODE *node)
{ {
int starttls;
g_return_if_fail(rec != NULL); g_return_if_fail(rec != NULL);
g_return_if_fail(node != NULL); g_return_if_fail(node != NULL);
@ -197,7 +198,10 @@ static void sig_server_setup_read(IRC_SERVER_SETUP_REC *rec, CONFIG_NODE *node)
rec->max_cmds_at_once = config_node_get_int(node, "cmds_max_at_once", 0); rec->max_cmds_at_once = config_node_get_int(node, "cmds_max_at_once", 0);
rec->cmd_queue_speed = config_node_get_int(node, "cmd_queue_speed", 0); rec->cmd_queue_speed = config_node_get_int(node, "cmd_queue_speed", 0);
rec->max_query_chans = config_node_get_int(node, "max_query_chans", 0); rec->max_query_chans = config_node_get_int(node, "max_query_chans", 0);
rec->starttls = config_node_get_bool(node, "starttls", STARTTLS_NOTSET); starttls = config_node_get_bool(node, "starttls", -1);
rec->starttls = starttls == -1 ? STARTTLS_NOTSET :
starttls == 0 ? STARTTLS_DISALLOW :
STARTTLS_ENABLED;
if (rec->starttls == STARTTLS_ENABLED) { if (rec->starttls == STARTTLS_ENABLED) {
rec->use_tls = 0; rec->use_tls = 0;
} }

View File

@ -84,10 +84,11 @@ static int ischannel_func(SERVER_REC *server, const char *data)
chantypes = "#&!+"; /* normal, local, secure, modeless */ chantypes = "#&!+"; /* normal, local, secure, modeless */
statusmsg = g_hash_table_lookup(irc_server->isupport, "statusmsg"); statusmsg = g_hash_table_lookup(irc_server->isupport, "statusmsg");
if (statusmsg == NULL) if (statusmsg == NULL && strchr(chantypes, '@') == NULL)
statusmsg = "@"; statusmsg = "@";
data += strspn(data, statusmsg); if (statusmsg != NULL)
data += strspn(data, statusmsg);
/* strchr(3) considers the trailing NUL as part of the string, make sure /* strchr(3) considers the trailing NUL as part of the string, make sure
* we didn't advance too much. */ * we didn't advance too much. */
@ -282,7 +283,6 @@ static void server_init_1(IRC_SERVER_REC *server)
irc_cap_toggle(server, CAP_SASL, TRUE); irc_cap_toggle(server, CAP_SASL, TRUE);
} }
irc_cap_toggle(server, CAP_MAXLINE, TRUE);
irc_cap_toggle(server, CAP_MULTI_PREFIX, TRUE); irc_cap_toggle(server, CAP_MULTI_PREFIX, TRUE);
irc_cap_toggle(server, CAP_EXTENDED_JOIN, TRUE); irc_cap_toggle(server, CAP_EXTENDED_JOIN, TRUE);
irc_cap_toggle(server, CAP_SETNAME, TRUE); irc_cap_toggle(server, CAP_SETNAME, TRUE);
@ -647,24 +647,6 @@ static void sig_server_quit(IRC_SERVER_REC *server, const char *msg)
g_free(recoded); g_free(recoded);
} }
static void cap_maxline(IRC_SERVER_REC *server)
{
unsigned int maxline = 0;
gboolean parse_successful = FALSE;
const char *maxline_str;
maxline_str = g_hash_table_lookup(server->cap_supported, CAP_MAXLINE);
if (maxline_str != NULL) {
parse_successful = parse_uint(maxline_str, NULL, 10, &maxline);
}
if (parse_successful &&
maxline >= MAX_IRC_MESSAGE_LEN + 2 /* 2 bytes for CR+LF */) {
server->max_message_len = maxline - 2;
}
}
void irc_server_send_action(IRC_SERVER_REC *server, const char *target, const char *data) void irc_server_send_action(IRC_SERVER_REC *server, const char *target, const char *data)
{ {
char *recoded; char *recoded;
@ -734,9 +716,10 @@ static int server_cmd_timeout(IRC_SERVER_REC *server, gint64 now)
{ {
REDIRECT_REC *redirect; REDIRECT_REC *redirect;
GSList *link; GSList *link;
GString *str;
long usecs; long usecs;
char *cmd; char *cmd;
int len; int crlf;
if (!IS_IRC_SERVER(server)) if (!IS_IRC_SERVER(server))
return 0; return 0;
@ -759,16 +742,34 @@ static int server_cmd_timeout(IRC_SERVER_REC *server, gint64 now)
redirect = server->cmdqueue->next->data; redirect = server->cmdqueue->next->data;
/* send command */ /* send command */
len = strlen(cmd); str = g_string_new(cmd);
irc_server_send_data(server, cmd, len);
/* add to rawlog without [CR+]LF */ if (str->len > 2 && str->str[str->len - 2] == '\r')
if (len > 2 && cmd[len-2] == '\r') crlf = 2;
cmd[len-2] = '\0'; else if (str->len > 1 && str->str[str->len - 1] == '\n')
else if (cmd[len-1] == '\n') crlf = 1;
cmd[len-1] = '\0'; else
rawlog_output(server->rawlog, cmd); crlf = 0;
server_redirect_command(server, cmd, redirect);
if (crlf)
g_string_truncate(str, str->len - crlf);
signal_emit("server outgoing modify", 3, server, str, crlf);
if (str->len) {
if (crlf == 2)
g_string_append(str, "\r\n");
else if (crlf == 1)
g_string_append(str, "\n");
irc_server_send_data(server, str->str, str->len);
/* add to rawlog without [CR+]LF */
if (crlf)
g_string_truncate(str, str->len - crlf);
rawlog_output(server->rawlog, str->str);
server_redirect_command(server, str->str, redirect);
}
g_string_free(str, TRUE);
/* remove from queue */ /* remove from queue */
server->cmdqueue = g_slist_remove(server->cmdqueue, cmd); server->cmdqueue = g_slist_remove(server->cmdqueue, cmd);
@ -1222,7 +1223,6 @@ void irc_servers_init(void)
signal_add_first("server disconnected", (SIGNAL_FUNC) sig_disconnected); signal_add_first("server disconnected", (SIGNAL_FUNC) sig_disconnected);
signal_add_last("server destroyed", (SIGNAL_FUNC) sig_destroyed); signal_add_last("server destroyed", (SIGNAL_FUNC) sig_destroyed);
signal_add_last("server quit", (SIGNAL_FUNC) sig_server_quit); signal_add_last("server quit", (SIGNAL_FUNC) sig_server_quit);
signal_add("server cap ack " CAP_MAXLINE, (SIGNAL_FUNC) cap_maxline);
signal_add("event 670", (SIGNAL_FUNC) event_starttls); signal_add("event 670", (SIGNAL_FUNC) event_starttls);
signal_add("event 451", (SIGNAL_FUNC) event_registerfirst); signal_add("event 451", (SIGNAL_FUNC) event_registerfirst);
signal_add("server cap end", (SIGNAL_FUNC) event_capend); signal_add("server cap end", (SIGNAL_FUNC) event_capend);
@ -1254,7 +1254,6 @@ void irc_servers_deinit(void)
signal_remove("server disconnected", (SIGNAL_FUNC) sig_disconnected); signal_remove("server disconnected", (SIGNAL_FUNC) sig_disconnected);
signal_remove("server destroyed", (SIGNAL_FUNC) sig_destroyed); signal_remove("server destroyed", (SIGNAL_FUNC) sig_destroyed);
signal_remove("server quit", (SIGNAL_FUNC) sig_server_quit); signal_remove("server quit", (SIGNAL_FUNC) sig_server_quit);
signal_remove("server cap ack " CAP_MAXLINE, (SIGNAL_FUNC) cap_maxline);
signal_remove("event 670", (SIGNAL_FUNC) event_starttls); signal_remove("event 670", (SIGNAL_FUNC) event_starttls);
signal_remove("event 451", (SIGNAL_FUNC) event_registerfirst); signal_remove("event 451", (SIGNAL_FUNC) event_registerfirst);
signal_remove("server cap end", (SIGNAL_FUNC) event_capend); signal_remove("server cap end", (SIGNAL_FUNC) event_capend);

View File

@ -15,7 +15,6 @@
#define MAX_IRC_USER_TAGS_LEN 4094 #define MAX_IRC_USER_TAGS_LEN 4094
#define CAP_LS_VERSION "302" #define CAP_LS_VERSION "302"
#define CAP_MAXLINE "oragono.io/maxline-2"
#define CAP_MESSAGE_TAGS "message-tags" #define CAP_MESSAGE_TAGS "message-tags"
#define CAP_SASL "sasl" #define CAP_SASL "sasl"
#define CAP_MULTI_PREFIX "multi-prefix" #define CAP_MULTI_PREFIX "multi-prefix"
@ -119,6 +118,7 @@ struct _IRC_SERVER_REC {
there actually is, to make flood control remember there actually is, to make flood control remember
how many messages can be sent before starting the how many messages can be sent before starting the
flood control */ flood control */
int cmdlater; /* number of commands in queue to be sent later */
GSList *cmdqueue; /* command, redirection, ... */ GSList *cmdqueue; /* command, redirection, ... */
gint64 wait_cmd; /* don't send anything to server before this */ gint64 wait_cmd; /* don't send anything to server before this */
gint64 last_cmd; /* last time command was sent to server */ gint64 last_cmd; /* last time command was sent to server */

View File

@ -47,11 +47,11 @@ static void strip_params_colon(char *const);
/* The core of the irc_send_cmd* functions. If `raw' is TRUE, the `cmd' /* The core of the irc_send_cmd* functions. If `raw' is TRUE, the `cmd'
won't be checked at all if it's 512 bytes or not, or if it contains won't be checked at all if it's 512 bytes or not, or if it contains
line feeds or not. Use with extreme caution! */ line feeds or not. Use with extreme caution! */
void irc_send_cmd_full(IRC_SERVER_REC *server, const char *cmd, void irc_send_cmd_full(IRC_SERVER_REC *server, const char *cmd, int irc_send_when, int raw)
int send_now, int immediate, int raw)
{ {
GString *str; GString *str;
int len; int len;
guint pos;
gboolean server_supports_tag; gboolean server_supports_tag;
g_return_if_fail(server != NULL); g_return_if_fail(server != NULL);
@ -67,6 +67,14 @@ void irc_send_cmd_full(IRC_SERVER_REC *server, const char *cmd,
irc_servers_start_cmd_timeout(); irc_servers_start_cmd_timeout();
server->cmdcount++; server->cmdcount++;
pos = g_slist_length(server->cmdqueue);
if (server->cmdlater > pos / 2) {
server->cmdlater = pos / 2;
pos = 0;
} else {
pos -= 2 * server->cmdlater;
}
if (!raw) { if (!raw) {
const char *tmp = cmd; const char *tmp = cmd;
@ -105,37 +113,56 @@ void irc_send_cmd_full(IRC_SERVER_REC *server, const char *cmd,
g_string_append(str, cmd); g_string_append(str, cmd);
} }
if (send_now) {
rawlog_output(server->rawlog, str->str);
server_redirect_command(server, str->str, server->redirect_next);
server->redirect_next = NULL;
}
if (!raw) { if (!raw) {
/* Add CR+LF to command */ /* Add CR+LF to command */
g_string_append_c(str, 13); g_string_append(str, "\r\n");
g_string_append_c(str, 10);
} }
if (send_now) { if (irc_send_when == IRC_SEND_NOW) {
irc_server_send_data(server, str->str, str->len); int crlf;
g_string_free(str, TRUE);
} else {
/* add to queue */ if (str->len > 2 && str->str[str->len - 2] == '\r')
if (immediate) { crlf = 2;
server->cmdqueue = g_slist_prepend(server->cmdqueue, else if (str->len > 1 && str->str[str->len - 1] == '\n')
server->redirect_next); crlf = 1;
server->cmdqueue = g_slist_prepend(server->cmdqueue, else
g_string_free(str, FALSE)); crlf = 0;
} else {
server->cmdqueue = g_slist_append(server->cmdqueue, if (crlf)
g_string_free(str, FALSE)); g_string_truncate(str, str->len - crlf);
server->cmdqueue = g_slist_append(server->cmdqueue,
server->redirect_next); signal_emit("server outgoing modify", 3, server, str, crlf);
if (str->len) {
if (crlf == 2)
g_string_append(str, "\r\n");
else if (crlf == 1)
g_string_append(str, "\n");
irc_server_send_data(server, str->str, str->len);
/* add to rawlog without [CR+]LF */
if (crlf)
g_string_truncate(str, str->len - crlf);
rawlog_output(server->rawlog, str->str);
server_redirect_command(server, str->str, server->redirect_next);
} }
g_string_free(str, TRUE);
} else if (irc_send_when == IRC_SEND_NEXT) {
/* add to queue */
server->cmdqueue = g_slist_prepend(server->cmdqueue, server->redirect_next);
server->cmdqueue = g_slist_prepend(server->cmdqueue, g_string_free(str, FALSE));
} else if (irc_send_when == IRC_SEND_NORMAL) {
server->cmdqueue = g_slist_insert(server->cmdqueue, server->redirect_next, pos);
server->cmdqueue = g_slist_insert(server->cmdqueue, g_string_free(str, FALSE), pos);
} else if (irc_send_when == IRC_SEND_LATER) {
server->cmdqueue = g_slist_append(server->cmdqueue, g_string_free(str, FALSE));
server->cmdqueue = g_slist_append(server->cmdqueue, server->redirect_next);
server->cmdlater++;
} else {
g_warn_if_reached();
} }
server->redirect_next = NULL;
server->redirect_next = NULL;
} }
/* Send command to IRC server */ /* Send command to IRC server */
@ -149,7 +176,7 @@ void irc_send_cmd(IRC_SERVER_REC *server, const char *cmd)
(server->cmdcount < server->max_cmds_at_once || (server->cmdcount < server->max_cmds_at_once ||
server->cmd_queue_speed <= 0); server->cmd_queue_speed <= 0);
irc_send_cmd_full(server, cmd, send_now, FALSE, FALSE); irc_send_cmd_full(server, cmd, send_now ? IRC_SEND_NOW : IRC_SEND_NORMAL, FALSE);
} }
/* Send command to IRC server */ /* Send command to IRC server */
@ -173,7 +200,7 @@ void irc_send_cmd_now(IRC_SERVER_REC *server, const char *cmd)
{ {
g_return_if_fail(cmd != NULL); g_return_if_fail(cmd != NULL);
irc_send_cmd_full(server, cmd, TRUE, TRUE, FALSE); irc_send_cmd_full(server, cmd, IRC_SEND_NOW, FALSE);
} }
/* Send command to server putting it at the beginning of the queue of /* Send command to server putting it at the beginning of the queue of
@ -183,7 +210,15 @@ void irc_send_cmd_first(IRC_SERVER_REC *server, const char *cmd)
{ {
g_return_if_fail(cmd != NULL); g_return_if_fail(cmd != NULL);
irc_send_cmd_full(server, cmd, FALSE, TRUE, FALSE); irc_send_cmd_full(server, cmd, IRC_SEND_NEXT, FALSE);
}
/* Send command to server putting it at the end of the queue. */
void irc_send_cmd_later(IRC_SERVER_REC *server, const char *cmd)
{
g_return_if_fail(cmd != NULL);
irc_send_cmd_full(server, cmd, IRC_SEND_LATER, FALSE);
} }
static char *split_nicks(const char *cmd, char **pre, char **nicks, char **post, int arg) static char *split_nicks(const char *cmd, char **pre, char **nicks, char **post, int arg)

View File

@ -27,6 +27,13 @@ typedef struct _REDIRECT_REC REDIRECT_REC;
extern char *current_server_event; /* current server event being processed */ extern char *current_server_event; /* current server event being processed */
enum {
IRC_SEND_NOW, /* */
IRC_SEND_NEXT,
IRC_SEND_NORMAL,
IRC_SEND_LATER
};
/* Send command to IRC server */ /* Send command to IRC server */
void irc_send_cmd(IRC_SERVER_REC *server, const char *cmd); void irc_send_cmd(IRC_SERVER_REC *server, const char *cmd);
void irc_send_cmdv(IRC_SERVER_REC *server, const char *cmd, ...) G_GNUC_PRINTF (2, 3); void irc_send_cmdv(IRC_SERVER_REC *server, const char *cmd, ...) G_GNUC_PRINTF (2, 3);
@ -42,11 +49,12 @@ void irc_send_cmd_now(IRC_SERVER_REC *server, const char *cmd);
commands to send -- it will go out as soon as possible in accordance commands to send -- it will go out as soon as possible in accordance
to the flood protection settings. */ to the flood protection settings. */
void irc_send_cmd_first(IRC_SERVER_REC *server, const char *cmd); void irc_send_cmd_first(IRC_SERVER_REC *server, const char *cmd);
/* Send command to server putting it at the end of the queue. */
void irc_send_cmd_later(IRC_SERVER_REC *server, const char *cmd);
/* The core of the irc_send_cmd* functions. If `raw' is TRUE, the `cmd' /* The core of the irc_send_cmd* functions. If `raw' is TRUE, the `cmd'
won't be checked at all if it's 512 bytes or not, or if it contains won't be checked at all if it's 512 bytes or not, or if it contains
line feeds or not. Use with extreme caution! */ line feeds or not. Use with extreme caution! */
void irc_send_cmd_full(IRC_SERVER_REC *server, const char *cmd, void irc_send_cmd_full(IRC_SERVER_REC *server, const char *cmd, int irc_send_when, int raw);
int send_now, int immediate, int raw);
/* Extract a tag value from tags */ /* Extract a tag value from tags */
GHashTable *irc_parse_message_tags(const char *tags); GHashTable *irc_parse_message_tags(const char *tags);

View File

@ -104,7 +104,7 @@ static int sig_check_lag(void)
if (rec->lag_sent != 0) { if (rec->lag_sent != 0) {
/* waiting for lag reply */ /* waiting for lag reply */
if (max_lag > 1 && now - rec->lag_sent > max_lag * G_TIME_SPAN_SECOND) { if (max_lag > 1 && now - (rec->lag_sent / G_TIME_SPAN_SECOND) > max_lag) {
/* too much lag, disconnect */ /* too much lag, disconnect */
signal_emit("server lag disconnect", 1, rec); signal_emit("server lag disconnect", 1, rec);
rec->connection_lost = TRUE; rec->connection_lost = TRUE;

View File

@ -43,13 +43,6 @@ static void event_join(IRC_SERVER_REC *server, const char *data,
g_return_if_fail(data != NULL); g_return_if_fail(data != NULL);
if (g_ascii_strcasecmp(nick, server->nick) == 0) {
/* You joined, do not massjoin */
send_massjoin = FALSE;
} else {
send_massjoin = TRUE;
}
params = event_get_params(data, 3, &channel, &account, &realname); params = event_get_params(data, 3, &channel, &account, &realname);
ptr = strchr(channel, 7); /* ^G does something weird.. */ ptr = strchr(channel, 7); /* ^G does something weird.. */
@ -62,6 +55,19 @@ static void event_join(IRC_SERVER_REC *server, const char *data,
return; return;
} }
if (g_ascii_strcasecmp(nick, server->nick) == 0) {
/* do not overwrite our /UPGRADEd ownnick */
if (chanrec->session_rejoin) {
g_free(params);
return;
} else {
/* You joined, do not massjoin */
send_massjoin = FALSE;
}
} else {
send_massjoin = TRUE;
}
/* check that the nick isn't already in nicklist. seems to happen /* check that the nick isn't already in nicklist. seems to happen
sometimes (server desyncs or something?) */ sometimes (server desyncs or something?) */
nickrec = nicklist_find(CHANNEL(chanrec), nick); nickrec = nicklist_find(CHANNEL(chanrec), nick);

View File

@ -318,13 +318,17 @@ void dcc_chat_input(CHAT_DCC_REC *dcc)
} }
if (ret > 0) { if (ret > 0) {
SERVER_REC *server;
char *recoded; char *recoded;
dcc->transfd += ret; dcc->transfd += ret;
recoded = recode_in(SERVER(dcc->server), str, dcc->nick); server = SERVER(dcc->server);
recoded = recode_in(server, str, dcc->nick);
signal_emit("dcc chat message", 2, dcc, recoded); signal_emit("dcc chat message", 2, dcc, recoded);
g_free(recoded); g_free(recoded);
if (server != NULL)
server_meta_clear_all(server);
} }
} while (ret > 0); } while (ret > 0);
} }

View File

@ -92,7 +92,7 @@ static void ison_send(IRC_SERVER_REC *server, GString *cmd)
server_redirect_event(server, "ison", 1, NULL, -1, NULL, server_redirect_event(server, "ison", 1, NULL, -1, NULL,
"event 303", "notifylist event", NULL); "event 303", "notifylist event", NULL);
irc_send_cmd(server, cmd->str); irc_send_cmd_later(server, cmd->str);
g_string_truncate(cmd, 0); g_string_truncate(cmd, 0);
} }
@ -183,7 +183,9 @@ static void whois_send(IRC_SERVER_REC *server, const char *nicks,
"", "event empty", NULL); "", "event empty", NULL);
g_free(str); g_free(str);
irc_send_cmdv(server, "WHOIS %s", whois_request); str = g_strdup_printf("WHOIS %s", whois_request);
irc_send_cmd_later(server, str);
g_free(str);
} }
static void whois_send_server(IRC_SERVER_REC *server, char *nick) static void whois_send_server(IRC_SERVER_REC *server, char *nick)

View File

@ -54,10 +54,11 @@ log_close(log)
Irssi::Log log Irssi::Log log
void void
log_write_rec(log, str, level) log_write_rec(log, str, level, now = -1)
Irssi::Log log Irssi::Log log
char *str char *str
int level int level
time_t now
void void
log_start_logging(log) log_start_logging(log)

View File

@ -19,6 +19,8 @@ while (<>) {
s/GList \* of ([^,]*)s/glistptr_\1/g; s/GList \* of ([^,]*)s/glistptr_\1/g;
s/GSList of ([^,]*)s/gslist_\1/g; s/GSList of ([^,]*)s/gslist_\1/g;
s/GString \*[^,]*/gstring/g;
s/char \*[^,]*/string/g; s/char \*[^,]*/string/g;
s/ulong \*[^,]*/ulongptr/g; s/ulong \*[^,]*/ulongptr/g;
s/int \*[^,]*/intptr/g; s/int \*[^,]*/intptr/g;
@ -52,12 +54,13 @@ while (<>) {
CLIENT_REC => 'Irssi::Irc::Client', CLIENT_REC => 'Irssi::Irc::Client',
# fe-common # fe-common
THEME_REC => 'Irssi::UI::Theme', THEME_REC => 'Irssi::UI::Theme',
KEYINFO_REC => 'Irssi::UI::Keyinfo', KEYINFO_REC => 'Irssi::UI::Keyinfo',
PROCESS_REC => 'Irssi::UI::Process', PROCESS_REC => 'Irssi::UI::Process',
TEXT_DEST_REC => 'Irssi::UI::TextDest', TEXT_DEST_REC => 'Irssi::UI::TextDest',
WINDOW_REC => 'Irssi::UI::Window', LINE_INFO_META_REC => 'Irssi::UI::LineInfoMeta',
WI_ITEM_REC => 'iobject', WINDOW_REC => 'Irssi::UI::Window',
WI_ITEM_REC => 'iobject',
# fe-text # fe-text
TEXTBUFFER_VIEW_REC => 'Irssi::TextUI::TextBufferView', TEXTBUFFER_VIEW_REC => 'Irssi::TextUI::TextBufferView',

View File

@ -86,6 +86,13 @@ send_raw_first(server, cmd)
CODE: CODE:
irc_send_cmd_first(server, cmd); irc_send_cmd_first(server, cmd);
void
send_raw_later(server, cmd)
Irssi::Irc::Server server
char *cmd
CODE:
irc_send_cmd_later(server, cmd);
void void
send_raw_split(server, cmd, nickarg, max_nicks) send_raw_split(server, cmd, nickarg, max_nicks)
Irssi::Irc::Server server Irssi::Irc::Server server

View File

@ -86,7 +86,8 @@ void perl_signal_args_to_c(void (*callback)(void *, int, void **), void *cb_arg,
unsigned long v_ulong; unsigned long v_ulong;
GSList *v_gslist; GSList *v_gslist;
GList *v_glist; GList *v_glist;
} saved_args[SIGNAL_MAX_ARGUMENTS]; GString *v_gstring;
} saved_args[SIGNAL_MAX_ARGUMENTS];
AV *aargs; AV *aargs;
void *p[SIGNAL_MAX_ARGUMENTS]; void *p[SIGNAL_MAX_ARGUMENTS];
PERL_SIGNAL_ARGS_REC *rec; PERL_SIGNAL_ARGS_REC *rec;
@ -146,6 +147,12 @@ void perl_signal_args_to_c(void (*callback)(void *, int, void **), void *cb_arg,
} else if (g_strcmp0(rec->args[n], "intptr") == 0) { } else if (g_strcmp0(rec->args[n], "intptr") == 0) {
saved_args[n].v_int = SvIV(SvRV(arg)); saved_args[n].v_int = SvIV(SvRV(arg));
c_arg = &saved_args[n].v_int; c_arg = &saved_args[n].v_int;
} else if (g_strcmp0(rec->args[n], "gstring") == 0) {
char *pv;
size_t len;
pv = SvPV(SvRV(arg), len);
c_arg = saved_args[n].v_gstring = g_string_new_len(pv, len);
} else if (strncmp(rec->args[n], "glistptr_", 9) == 0) { } else if (strncmp(rec->args[n], "glistptr_", 9) == 0) {
GList *gl; GList *gl;
int is_str; int is_str;
@ -220,6 +227,16 @@ void perl_signal_args_to_c(void (*callback)(void *, int, void **), void *cb_arg,
SV *t = SvRV(arg); SV *t = SvRV(arg);
SvIOK_only(t); SvIOK_only(t);
SvIV_set(t, saved_args[n].v_int); SvIV_set(t, saved_args[n].v_int);
} else if (g_strcmp0(rec->args[n], "gstring") == 0) {
GString *str;
SV *t;
str = saved_args[n].v_gstring;
t = SvRV(arg);
SvPOK_only(t);
sv_setpvn(t, str->str, str->len);
g_string_free(str, TRUE);
} else if (strncmp(rec->args[n], "gslist_", 7) == 0) { } else if (strncmp(rec->args[n], "gslist_", 7) == 0) {
g_slist_free(saved_args[n].v_gslist); g_slist_free(saved_args[n].v_gslist);
} else if (strncmp(rec->args[n], "glistptr_", 9) == 0) { } else if (strncmp(rec->args[n], "glistptr_", 9) == 0) {
@ -306,7 +323,10 @@ static void perl_call_signal(PERL_SCRIPT_REC *script, SV *func,
perlarg = newSViv(*(unsigned long *) arg); perlarg = newSViv(*(unsigned long *) arg);
else if (g_strcmp0(rec->args[n], "intptr") == 0) else if (g_strcmp0(rec->args[n], "intptr") == 0)
saved_args[n] = perlarg = newRV_noinc(newSViv(*(int *) arg)); saved_args[n] = perlarg = newRV_noinc(newSViv(*(int *) arg));
else if (g_strcmp0(rec->args[n], "formatnum_args") == 0 && n >= 3) { else if (g_strcmp0(rec->args[n], "gstring") == 0) {
GString *str = arg;
saved_args[n] = perlarg = newRV_noinc(newSVpvn(str->str, str->len));
} else if (g_strcmp0(rec->args[n], "formatnum_args") == 0 && n >= 3) {
const THEME_REC *theme; const THEME_REC *theme;
const MODULE_THEME_REC *rec; const MODULE_THEME_REC *rec;
const FORMAT_REC *formats; const FORMAT_REC *formats;
@ -399,6 +419,7 @@ static void perl_call_signal(PERL_SCRIPT_REC *script, SV *func,
if (SvTRUE(ERRSV)) { if (SvTRUE(ERRSV)) {
char *error = g_strdup(SvPV_nolen(ERRSV)); char *error = g_strdup(SvPV_nolen(ERRSV));
perl_signal_remove_script(script);
signal_emit("script error", 2, script, error); signal_emit("script error", 2, script, error);
g_free(error); g_free(error);
rec = NULL; rec = NULL;
@ -415,8 +436,21 @@ static void perl_call_signal(PERL_SCRIPT_REC *script, SV *func,
if (g_strcmp0(rec->args[n], "intptr") == 0) { if (g_strcmp0(rec->args[n], "intptr") == 0) {
int *val = arg; int *val = arg;
*val = SvIV(SvRV(saved_args[n])); *val = SvIV(SvRV(saved_args[n]));
} else if (g_strcmp0(rec->args[n], "gstring") == 0) {
SV *os, *ns;
GString *str = arg;
os = sv_2mortal(newSVpvn(str->str, str->len));
ns = SvRV(saved_args[n]);
if (sv_cmp(os, ns) != 0) {
size_t len;
char *pv = SvPV(ns, len);
g_string_truncate(str, 0);
g_string_append_len(str, pv, len);
}
} else if (strncmp(rec->args[n], "glistptr_", 9) == 0) { } else if (strncmp(rec->args[n], "glistptr_", 9) == 0) {
GList **ret = arg; GList **ret = arg;
GList *out = NULL; GList *out = NULL;
void *val; void *val;
int count; int count;

View File

@ -83,6 +83,7 @@ static int perl_source_event(PERL_SOURCE_REC *rec)
if (SvTRUE(ERRSV)) { if (SvTRUE(ERRSV)) {
char *error = g_strdup(SvPV_nolen(ERRSV)); char *error = g_strdup(SvPV_nolen(ERRSV));
perl_source_remove_script(rec->script);
signal_emit("script error", 2, rec->script, error); signal_emit("script error", 2, rec->script, error);
g_free(error); g_free(error);
} }

View File

@ -101,28 +101,10 @@ PPCODE:
} }
XPUSHs(sv_2mortal(newRV_noinc((SV *) hv))); XPUSHs(sv_2mortal(newRV_noinc((SV *) hv)));
void Irssi::UI::LineInfoMeta
textbuffer_line_get_meta(line) textbuffer_line_get_meta(line)
Irssi::TextUI::Line line Irssi::TextUI::Line line
PREINIT: CODE:
HV *hv; RETVAL = line->line->info.meta;
LINE_REC *l; OUTPUT:
TEXT_BUFFER_META_REC *m; RETVAL
GHashTableIter iter;
char *key;
char *val;
PPCODE:
hv = newHV();
l = line->line;
if (l->info.meta != NULL) {
m = l->info.meta;
if (m->hash != NULL) {
g_hash_table_iter_init(&iter, m->hash);
while (
g_hash_table_iter_next(&iter, (gpointer *) &key, (gpointer *) &val)) {
(void) hv_store(hv, key, strlen(key), new_pv(val), 0);
}
}
(void) hv_store(hv, "server_time", 11, newSViv(m->server_time), 0);
}
XPUSHs(sv_2mortal(newRV_noinc((SV *) hv)));

View File

@ -49,14 +49,14 @@ textbuffer_view_scroll_line(view, line)
Irssi::TextUI::TextBufferView view Irssi::TextUI::TextBufferView view
Irssi::TextUI::Line line Irssi::TextUI::Line line
CODE: CODE:
textbuffer_view_scroll_line(view, line->line); textbuffer_view_scroll_line(view, Line(line));
Irssi::TextUI::LineCache Irssi::TextUI::LineCache
textbuffer_view_get_line_cache(view, line) textbuffer_view_get_line_cache(view, line)
Irssi::TextUI::TextBufferView view Irssi::TextUI::TextBufferView view
Irssi::TextUI::Line line Irssi::TextUI::Line line
CODE: CODE:
RETVAL = textbuffer_view_get_line_cache(view, line->line); RETVAL = textbuffer_view_get_line_cache(view, Line(line));
OUTPUT: OUTPUT:
RETVAL RETVAL
@ -65,7 +65,7 @@ textbuffer_view_remove_line(view, line)
Irssi::TextUI::TextBufferView view Irssi::TextUI::TextBufferView view
Irssi::TextUI::Line line Irssi::TextUI::Line line
CODE: CODE:
textbuffer_view_remove_line(view, line->line); textbuffer_view_remove_line(view, Line(line));
void void
textbuffer_view_remove_all_lines(view) textbuffer_view_remove_all_lines(view)
@ -82,7 +82,7 @@ textbuffer_view_set_bookmark(view, name, line)
char *name char *name
Irssi::TextUI::Line line Irssi::TextUI::Line line
CODE: CODE:
textbuffer_view_set_bookmark(view, name, line->line); textbuffer_view_set_bookmark(view, name, Line(line));
void void
textbuffer_view_set_bookmark_bottom(view, name) textbuffer_view_set_bookmark_bottom(view, name)

View File

@ -156,3 +156,22 @@ print(dest, str)
char *str char *str
CODE: CODE:
printtext_dest(dest, "%s", str); printtext_dest(dest, "%s", str);
#*******************************
MODULE = Irssi::UI::Formats PACKAGE = Irssi::UI::TextDest PREFIX = format_dest_
#*******************************
void
format_dest_meta_stash(dest, meta_key, meta_value)
Irssi::UI::TextDest dest
char *meta_key
char *meta_value
char *
format_dest_meta_stash_find(dest, meta_key)
Irssi::UI::TextDest dest
char *meta_key
CODE:
RETVAL = (char *) format_dest_meta_stash_find(dest, meta_key);
OUTPUT:
RETVAL

View File

@ -64,6 +64,26 @@ static void perl_text_dest_fill_hash(HV *hv, TEXT_DEST_REC *dest)
(void) hv_store(hv, "hilight_color", 13, new_pv(dest->hilight_color), 0); (void) hv_store(hv, "hilight_color", 13, new_pv(dest->hilight_color), 0);
} }
static void perl_line_info_meta_fill_hash(HV *hv, LINE_INFO_META_REC *meta)
{
GHashTableIter iter;
char *key;
char *val;
if (meta != NULL) {
if (meta->hash != NULL) {
g_hash_table_iter_init(&iter, meta->hash);
while (
g_hash_table_iter_next(&iter, (gpointer *) &key, (gpointer *) &val)) {
(void) hv_store(hv, key, strlen(key), new_pv(val), 0);
}
}
if (meta->server_time) {
(void) hv_store(hv, "server_time", 11, newSViv(meta->server_time), 0);
}
}
}
static void perl_exec_fill_hash(HV *hv, EXEC_WI_REC *item) static void perl_exec_fill_hash(HV *hv, EXEC_WI_REC *item)
{ {
g_return_if_fail(hv != NULL); g_return_if_fail(hv != NULL);
@ -81,6 +101,7 @@ static PLAIN_OBJECT_INIT_REC fe_plains[] = {
{ "Irssi::UI::Process", (PERL_OBJECT_FUNC) perl_process_fill_hash }, { "Irssi::UI::Process", (PERL_OBJECT_FUNC) perl_process_fill_hash },
{ "Irssi::UI::Window", (PERL_OBJECT_FUNC) perl_window_fill_hash }, { "Irssi::UI::Window", (PERL_OBJECT_FUNC) perl_window_fill_hash },
{ "Irssi::UI::TextDest", (PERL_OBJECT_FUNC) perl_text_dest_fill_hash }, { "Irssi::UI::TextDest", (PERL_OBJECT_FUNC) perl_text_dest_fill_hash },
{ "Irssi::UI::LineInfoMeta", (PERL_OBJECT_FUNC) perl_line_info_meta_fill_hash },
{ NULL, NULL } { NULL, NULL }
}; };

View File

@ -12,3 +12,4 @@ typedef WINDOW_REC *Irssi__UI__Window;
typedef TEXT_DEST_REC *Irssi__UI__TextDest; typedef TEXT_DEST_REC *Irssi__UI__TextDest;
typedef THEME_REC *Irssi__UI__Theme; typedef THEME_REC *Irssi__UI__Theme;
typedef KEYINFO_REC *Irssi__UI__Keyinfo; typedef KEYINFO_REC *Irssi__UI__Keyinfo;
typedef LINE_INFO_META_REC *Irssi__UI__LineInfoMeta;

View File

@ -3,6 +3,7 @@ Irssi::UI::Theme T_PlainObj
Irssi::UI::Window T_PlainObj Irssi::UI::Window T_PlainObj
Irssi::UI::Keyinfo T_PlainObj Irssi::UI::Keyinfo T_PlainObj
Irssi::UI::TextDest T_PlainObj Irssi::UI::TextDest T_PlainObj
Irssi::UI::LineInfoMeta T_PlainObj
INPUT INPUT

14
subprojects/openssl.wrap Normal file
View File

@ -0,0 +1,14 @@
[wrap-file]
directory = openssl-1.1.1l
source_url = https://www.openssl.org/source/openssl-1.1.1l.tar.gz
source_filename = openssl-1.1.1l.tar.gz
source_hash = 0b7a3e5e59c34827fe0c3a74b7ec8baef302b98fa80088d7f9153aa16fa76bd1
patch_filename = openssl_1.1.1l-1_patch.zip
patch_url = https://wrapdb.mesonbuild.com/v2/openssl_1.1.1l-1/get_patch
patch_hash = 670db31580039e06c17f48bcd31e489f453fe72c22006de6d693b9b033f1003a
[provide]
libcrypto = libcrypto_dep
libssl = libssl_dep
openssl = openssl_dep