Compare commits

...

330 commits

Author SHA1 Message Date
ailin-nemui
43f1727ef9
Merge pull request #1611 from horgh/horgh/muon-meson-fmt-workflow
Add muon-meson fmt GitHub Actions workflow
2026-01-27 08:02:34 +00:00
William Storey
54bb34e14f Add muon fmt GitHub Actions workflow 2026-01-26 21:02:10 -08:00
William Storey
7ca9fd5aee Format root meson.build 2026-01-26 21:02:10 -08:00
Ailin Nemui
221d520c37 run meson formatter 2026-01-25 22:07:44 +01:00
ailin-nemui
80b8875fea
Merge pull request #1607 from ailin-nemui/gio-resolver-fixes
GResolver fixes
2026-01-25 18:22:20 +00:00
Ailin Nemui
88afc78aac GResolver fixes
fix issues brought up by @horgh in #1580
2026-01-25 00:25:44 +01:00
ailin-nemui
00466fe5be
Merge pull request #1605 from ailin-nemui/gio-resolver-old
add compatibility code for older GResolver
2026-01-24 20:04:17 +00:00
ailin-nemui
64db7abcec
Merge pull request #1606 from ailin-nemui/comment-warning
fix space in end comment
2026-01-24 20:03:33 +00:00
Ailin Nemui
0157a4424b fix clang-format-xs boot code 2026-01-24 20:53:29 +01:00
Ailin Nemui
00146211d0 fix space in end comment 2026-01-24 18:06:21 +01:00
Ailin Nemui
e9281b2f11 add compatibility code for older GResolver 2026-01-24 18:05:05 +01:00
ailin-nemui
3629a122c6
Merge pull request #1604 from ailin-nemui/perl-irc-dcc
make Irssi::Irc usable without dcc
2026-01-24 15:28:52 +00:00
Ailin Nemui
45d3013f9e up abi 2026-01-24 14:27:18 +01:00
Ailin Nemui
a54677ce99 up perl api 2026-01-24 14:27:16 +01:00
Ailin Nemui
2012668bef make Irssi::Irc usable without dcc 2026-01-24 14:27:16 +01:00
Ailin Nemui
51322d6af1 restore ip4_any 2026-01-24 13:53:23 +01:00
ailin-nemui
3c65684643
Merge pull request #1568 from nikolas/patch-2
Add a few more compile dependencies to INSTALL document
2026-01-23 21:18:17 +00:00
nikolas
c6d15ee461 Add a few more compile dependencies to INSTALL document 2026-01-23 22:17:39 +01:00
ailin-nemui
62031f5bdc
Merge pull request #1580 from ailin-nemui/gio-resolver
use GIO resolver
2026-01-23 20:42:55 +00:00
Ailin Nemui
e64ed836a5 up glib wrap 2026-01-23 21:21:10 +01:00
Ailin Nemui
51f2a4f7fb use GIO resolver
change: rename resolve_prefer_ipv6 -> irssiproxy_prefer_ipv6
2026-01-23 21:21:10 +01:00
ailin-nemui
d5be7d7756
Merge pull request #1578 from ailin-nemui/cygwin
make compilation work on cygwin
2026-01-23 20:20:43 +00:00
ailin-nemui
81887a6224
Merge pull request #1599 from ailin-nemui/docs
run syncdocs.sh
2025-12-27 21:46:58 +00:00
ailin-nemui
97304bb7c0
Merge pull request #1600 from ailin-nemui/github
github actions: update package lists
2025-12-27 21:46:19 +00:00
Ailin Nemui
d30cdafcff github actions: update package lists 2025-12-27 22:41:02 +01:00
Ailin Nemui
82b253f63e run syncdocs.sh
added New-users and qna, removed faq and startup-HOWTO from sync
2025-12-27 22:35:23 +01:00
ailin-nemui
ebdf863925
Merge pull request #1597 from ailin-nemui/scripts
run syncscripts.sh
2025-12-27 19:42:18 +00:00
Ailin Nemui
d145f24c22 run syncscripts.sh
autoop 1.10 -> 1.11
mail 2.92 -> 2.93
scriptassist 2022053100 -> 2023111700
2025-12-27 20:41:26 +01:00
ailin-nemui
6c72dc14fa
Merge pull request #1594 from soulseller/fix/hide-text-style-colors
formats: fix hide_text_style and hide_colors to mitigate color bleed
2025-11-27 11:16:35 +00:00
soulseller
3811b1ffc9 formats: fix hide_text_style and hide_colors to mitigate color bleed 2025-11-27 00:59:18 +02:00
ailin-nemui
89dc74cbdd
Merge pull request #1591 from soulseller/fix/netsplit-nickname-truncation
fe-netsplit: fix nickname truncation to avoid trailing comma-space
2025-11-25 13:19:12 +00:00
ailin-nemui
bab97b4c0c
Merge pull request #1588 from arza-zara/patch-1
Increase default scrollback_lines
2025-11-25 12:23:40 +00:00
soulseller
5416843d2d fe-netsplit: fix nickname truncation to avoid trailing comma-space 2025-11-23 15:15:24 +02:00
ailin-nemui
f4a4bcb4b8
Merge pull request #1590 from jremes-foss/lusers-in-typo-fix
Typo fix in docs/help/in/lusers.in
2025-11-22 15:08:00 +00:00
Juha Remes
3316202c48 Typo fix in docs/help/in/lusers.in 2025-11-22 14:27:53 +00:00
arza
f293277765
Increase default scrollback_lines
It seems common that people miss important messages when being away and want to increase the scrollback.
2025-09-23 00:01:54 +03:00
ailin-nemui
e70993c4b6
Merge pull request #1577 from ailin-nemui/glib276
replace str->str & g_string_free with g_string_free_and_steal
2025-07-26 17:32:43 +00:00
Ailin Nemui
989ddd8429 replace shared_module with shared_library
according to mesonbuild irc chat
2025-07-25 19:49:53 +02:00
Ailin Nemui
df8aa42778 make compilation work on cygwin 2025-07-25 16:20:28 +01:00
ailin-nemui
cc24b2c54c
Merge pull request #1579 from ailin-nemui/ghvoid
fix xbps github action
2025-07-25 14:48:09 +00:00
Ailin Nemui
d21ff2e658 fix xbps 2025-07-25 16:24:11 +02:00
Ailin Nemui
8eee36d1ea replace str->str & g_string_free with g_string_free_and_steal
solving unused warning in GLib 2.76
2025-07-22 12:03:49 +02:00
ailin-nemui
995e77c30d
Merge pull request #1575 from irssi/hilight_syntax_update
Add -priority to hilight syntax line
2025-07-21 16:51:55 +00:00
ailin-nemui
216715bc81
Merge pull request #1576 from ailin-nemui/solaris
fix github solaris test
2025-07-21 16:51:40 +00:00
Ailin Nemui
9f0b2bc50d detect third argument type of puts 2025-07-21 18:35:09 +02:00
Ailin Nemui
6276fe1a68 debug logging solarisvm prepare 2025-07-20 23:03:52 +02:00
Jari Matilainen
7681cb7585
Add -priority to hilight syntax line 2025-07-20 22:40:59 +02:00
ailin-nemui
aa285d45cd
Merge pull request #1572 from ailin-nemui/perl-redefined
fix _GNU_SOURCE redefined warning due to perl ccflags
2025-07-13 17:57:31 +00:00
Ailin Nemui
838f8d179e fix _GNU_SOURCE redefined warning due to perl ccflags 2025-07-13 19:33:52 +02:00
ailin-nemui
599448af2e
Merge pull request #1566 from ar-an-ribe/fix-for-issue-1513
Resolve issue #1513.
2025-05-02 05:56:26 +00:00
Christian Carey
f12ed4ff54 Resolve issue #1513. 2025-05-02 00:02:46 -04:00
ailin-nemui
4ec9d10904
Merge pull request #1560 from ailin-nemui/wchar
add missing include for wcwidth thread test
2025-04-29 20:34:42 +00:00
Ailin Nemui
9fd6df2a15 add missing include for wcwidth thread test 2025-04-29 22:27:14 +02:00
ailin-nemui
4b33824249
Merge pull request #1565 from ailin-nemui/void
Void Linux github action fixes
2025-04-29 20:26:31 +00:00
Ailin Nemui
8eea7bef92 curl render 2025-04-29 22:19:02 +02:00
Ailin Nemui
af4fa60d3e s/gsed/sed 2025-04-29 22:14:52 +02:00
ailin-nemui
824c1aa376
Merge pull request #1563 from ailin-nemui/void
test the void
2025-04-29 20:08:05 +00:00
Ailin Nemui
5c53f2a329 test the void 2025-04-29 22:03:33 +02:00
ailin-nemui
f857f29eaf
Merge pull request #1564 from ailin-nemui/pep440
adapt pep440 dev version in make-dist.sh
2025-04-29 20:02:49 +00:00
Ailin Nemui
4857586564 adapt pep440 dev version in make-dist.sh 2025-04-29 20:52:56 +02:00
ailin-nemui
b14bc4a2fc
Merge pull request #1559 from ailin-nemui/bitwarnings
make bitfields unsigned
2025-04-27 12:41:57 +00:00
Ailin Nemui
c7c8d074bd up abi 2025-04-27 14:31:53 +02:00
Ailin Nemui
8acda3f9eb make bitfields unsigned 2025-04-27 14:31:01 +02:00
ailin-nemui
39d15558d2
Merge pull request #1561 from ailin-nemui/ghactions
update to ubuntu 22.04 in github actions
2025-04-27 10:35:46 +00:00
Ailin Nemui
b9511a9b7e update to ubuntu 22.04 in github actions 2025-04-27 12:23:54 +02:00
ailin-nemui
4449455113
Merge pull request #1558 from ailin-nemui/darwin-warning
fe-text: remove const for better Darwin support
2025-04-14 17:23:36 +00:00
Emil Engler
32adf7c1dd fe-text: remove const for better Darwin support
This commit removes the `const` qualifier from certain member fields,
as the Darwin version of several `<term.h>` related functions only
accept a `char *` rather than a `const char *`, thereby resulting in
dozens of compiler warnings.
2025-04-14 18:16:04 +02:00
ailin-nemui
a5441f62b9
Merge pull request #1542 from sortie/HOST_NOT_FOUND
Fix using HOST_NOT_FOUND instead of EAI_NONAME.
2025-04-14 13:36:51 +00:00
ailin-nemui
a1c8edfa44
Merge pull request #1541 from sortie/inet_aton
Replace obsolescent inet_addr(3)/inet_aton(3) with inet_pton(3).
2025-04-14 13:36:44 +00:00
ailin-nemui
efd8f9b3a5
Merge pull request #1540 from sortie/select
Include <sys/select.h> to get select(3).
2025-04-14 13:36:35 +00:00
Jonas 'Sortie' Termansen
f24d859c80 Fix using HOST_NOT_FOUND instead of EAI_NONAME.
HOST_NOT_FOUND is a gethostbyname(3) error condition rather than a
getaddrinfo(3) error condition and cannot be passed to net_gethosterror
as documented as it calls gai_strerror(3). EAI_NONAME is the appropriate
similar error condition as standardized by POSIX for getaddrinfo(3).
2025-04-14 15:09:27 +02:00
Jonas 'Sortie' Termansen
38440cf340 Replace obsolescent inet_addr(3)/inet_aton(3) with inet_pton(3).
inet_addr has become obsolescent as of POSIX-1.2024 and is not available
on strict POSIX 2024 libc implementations.

inet_pton(3) is the standard and portable replacement available on all
POSIX-1.2001 systems.
2025-04-14 15:08:55 +02:00
Jonas 'Sortie' Termansen
4b2951c828 Include <sys/select.h> to get select(3).
This is the header required by POSIX-1.2024.

This change is needed to build irssi on operating systems such as Sortix
that have a strict libc without obsolete behaviors.
2025-04-14 15:08:02 +02:00
ailin-nemui
5a9a9ababa
Merge pull request #1557 from ailin-nemui/solarisvm
test solaris build with github/vmactions
2025-04-14 13:07:23 +00:00
Ailin Nemui
6dce0a091b test solaris build with vmactions 2025-04-08 09:03:10 +02:00
Ailin Nemui
382bde9ab3 namespace TERM_REC functions (conflict with curses.h) 2025-04-08 09:03:00 +02:00
Ailin Nemui
7bac5eb762 include curses.h when needed 2025-04-08 09:03:00 +02:00
ailin-nemui
fca3e83e68
Merge pull request #1543 from Steering7253/master
add ipaddr and family to perl SERVER_REC (and connrec)
2025-04-08 06:05:42 +00:00
ailin-nemui
23ec63ae39
Merge pull request #1556 from Steering7253/fix_sasl_multi_cap
fix irssi SASL negotiation with multiple CAP ACK
2025-04-07 20:37:18 +00:00
steering7253
99c37387a4
bump ABI_VERSION 2025-04-07 14:36:10 -06:00
ailin-nemui
85bb6ef008
Merge pull request #1552 from ailin-nemui/tv2
initialise memory in ctcp ping reply
2025-04-07 20:33:53 +00:00
steering7253
49d7302e98
fix irssi SASL negotiation with multiple CAP ACK
when attempting SASL, if multiple CAP ACK were received (for example,
because a script sent an additional CAP REQ), then any not containing
`sasl` would cause SASL to fail (immediately aborting the connection
with no message, depending on sasl_disconnect_on_failure setting)

check not only if SASL is set in this line, but also if we've already
seen it in a previous line.
2025-04-07 13:53:39 -06:00
steering7253
26fd0585cd
add ipaddr and family to connrec and perl SERVER_REC 2025-04-07 13:51:49 -06:00
Ailin Nemui
d6c146a1fa initialise memory in ctcp ping reply 2025-03-24 08:54:01 +01:00
ailin-nemui
ee4471a118
Merge pull request #1546 from ailin-nemui/setuptools
fix github workflow setuptools
2024-12-16 20:00:54 +00:00
Ailin Nemui
e8e5bf5d81 patch old setuptools for python 3.12 for github workflow 2024-12-16 20:57:44 +01:00
Ailin Nemui
a7bb40f530 pin setuptools and meson ver for make dist in workflow 2024-12-16 20:57:27 +01:00
Ailin Nemui
a775f50572 add glib dependency to github workflows 2024-12-16 20:57:27 +01:00
Ailin Nemui
ca1cd7a26a new setuptools broken in github workflow 2024-12-16 20:57:27 +01:00
ailin-nemui
344dd0fbd4
Merge pull request #1545 from plundra/plundra/actions-upload-fix
github workflows: Bump actions/upload-artifact from deprecated (defunct) v1 to v4.
2024-12-16 19:56:05 +00:00
Pontus Lundkvist
ae094ba3e6 Bump actions/upload-artifact from deprecated (defunct) v1 to v4. 2024-11-18 22:43:57 +01:00
ailin-nemui
0697e3eaf1
Merge pull request #1527 from ardovm/capsicumdoc
Mention the section for capsicum settings.
2024-05-13 20:11:09 +00:00
Arrigo Marchiori
2dce273264 Mention the section of the capsicum settings. 2024-04-27 21:38:21 +02:00
ailin-nemui
5c15937554
Merge pull request #1525 from ailin-nemui/bans
fix /ban command
2024-04-12 21:18:39 +00:00
Ailin Nemui
19e7d3f6b8 up abi 2024-04-12 23:00:52 +02:00
Ailin Nemui
822fd50132 fix /ban command 2024-04-12 22:55:20 +02:00
ailin-nemui
4b48cdce65
Merge pull request #1523 from irssi/from-codeberg
From codeberg
2024-04-02 06:29:49 +00:00
ailin-nemui
c906b769fd
Merge pull request #1522 from dwfreed/fix-missing-nl
Ensure all text files have newlines at the end
2024-04-02 06:27:24 +00:00
Doug Freed
9d0787fc10 Ensure all files have newlines at the end 2024-04-02 05:23:10 +00:00
ailin-nemui
89f3e1acf5
Merge pull request #1519 from ailin-nemui/openssl3
deprecated openssl3 function
2024-04-01 20:36:00 +00:00
ailin-nemui
7b56ffdc2e
Merge pull request #1518 from ailin-nemui/dylib
fix deprecation in new glib module_open
2024-04-01 20:35:05 +00:00
ailin-nemui
bb4ed2b14f
Merge pull request #1521 from ailin-nemui/nodejs
github actions nodejs churn
2024-04-01 20:33:21 +00:00
Ailin Nemui
455dcb18ec deprecated openssl3 function 2024-04-01 22:31:53 +02:00
Ailin Nemui
111e9160a9 github actions nodejs churn 2024-04-01 22:28:17 +02:00
ailin-nemui
d30653f7f9
Merge pull request #1520 from irssi/readme-perl-ver
Update minimum required Perl version in readme
2024-04-01 20:11:15 +00:00
ailin-nemui
c48354307e
Update minimum required Perl version in readme 2024-04-01 22:10:35 +02:00
Ailin Nemui
e13df83dc8 new code for g_module_open which might work with apple dylibs given new enough glib 2024-04-01 17:38:30 +02:00
ailin-nemui
b18832bf3b
Merge pull request #1500 from patrick-irc/scram
Added support for SCRAM-SHA-1, SCRAM-SHA-256 and SCRAM-SHA-512
2024-04-01 15:17:16 +00:00
Ailin Nemui
2f2fa029f9 up abi 2024-04-01 16:37:35 +02:00
Ailin Nemui
08bb648850 proper sasl mechanism variable initialisation 2024-04-01 16:33:57 +02:00
Ailin Nemui
98b391f62e minor cleanup 2024-04-01 16:33:36 +02:00
Patrick Okraku
f2b97631e1 Added support for SCRAM-SHA-1, SCRAM-SHA-256 and SCRAM-SHA-512 2024-04-01 15:12:01 +02:00
ailin-nemui
215be29035 Merge pull request 'Fix github issue #1504 - irssi switches to af_unix if network name contains /' (!6) from ticho/irssi:gh1504 into master
Reviewed-on: https://codeberg.org/irssi/irssi/pulls/6
2024-04-01 08:42:17 +00:00
Andrej Kacian
e295caa866 Fix github issue #1504 - irssi switches to af_unix if network name contains /
In addition to looking for a /, we also check if the network name is
known.
2024-04-01 08:42:17 +00:00
ailin-nemui
91dac0e5a1
Merge pull request #1512 from ailin-nemui/shquote
missing shell quotes
2024-03-31 16:53:57 +00:00
ailin-nemui
aebc0667a6
Merge pull request #1515 from maflcko/patch-1
Update server.c: Add missing include
2024-03-31 16:53:44 +00:00
maflcko
cf6615a70e
Update server.c: Add missing include 2024-03-28 19:33:24 +01:00
Ailin Nemui
4dd57cf24e missing shell quotes 2024-02-23 17:04:41 +01:00
ailin-nemui
b3f6ed0b11
Merge pull request #1511 from soliton-/patch-1
typo fixes
2024-02-01 21:24:30 +00:00
Gunter Labes
41f8213fe0
typo fixes 2024-02-01 21:56:20 +01:00
ailin-nemui
504fd7bc60
Merge pull request #1510 from ailin-nemui/perl-again
restore locale if perl breaks it
2024-01-27 17:42:42 +00:00
Ailin Nemui
a0caf5e5e6 restore locale if perl breaks it 2023-12-22 15:06:23 +01:00
Ailin Nemui
514f1cdcf6 Revert "Merge pull request #1498 from ailin-nemui/perl5380locale"
This reverts commit 48bc90eb17, reversing
changes made to 2a1291f26f.
2023-12-22 15:06:23 +01:00
ailin-nemui
2f16b554b5
Merge pull request #1509 from ailin-nemui/compile-deps
explicitly list pkg-config as build dependency
2023-12-19 12:53:20 +00:00
Ailin Nemui
a11df816b7 explicitly list pkg-config as build dependency, since meson needs it to find glib 2023-12-19 13:51:46 +01:00
ailin-nemui
89adcc4ee8
Merge pull request #1505 from irssi/vague666-patch-1
Update bind.in
2023-11-11 13:55:37 +00:00
Jari Matilainen
ed2825f28b
Update bind.in
Better explanation for upper-/lowercase usage for keys
2023-11-11 02:13:34 +01:00
ailin-nemui
363fbf048f
Merge pull request #1502 from irssi/ailin-nemui/window-default-help
Add SET window_default_ to See also in window help
2023-10-31 10:00:46 +00:00
ailin-nemui
ea434591f4
Add SET window_default_ to See also in window help 2023-10-31 10:58:14 +01:00
Ailin Nemui
465d3188a4 Merge tag '1.4.5' into integrate/1.4.5 2023-10-01 19:19:33 +02:00
Ailin Nemui
bcf07a2546 tag as 1.4.5 2023-10-01 15:46:01 +02:00
ailin-nemui
ce4dd911bc Merge pull request #1497 from ailin-nemui/github-workflow-error
Slightly improve GitHub workflow

(cherry picked from commit 2a1291f26f)
2023-10-01 14:25:50 +02:00
ailin-nemui
6438fcfe70 Merge pull request #1498 from ailin-nemui/perl5380locale
Restore locale after loading Perl

(cherry picked from commit 48bc90eb17)
2023-10-01 14:03:11 +02:00
ailin-nemui
91593cfec3 Merge pull request #1495 from ailin-nemui/terminclude
fe-text: include the real tputs(3) from term.h
(cherry picked from commit db32744ee4)
2023-10-01 14:01:47 +02:00
ailin-nemui
7145e1ef20 Merge pull request #1494 from RealKindOne/master
Add -notls and -notls_verify into help file and src/core/chat-commands.c

(cherry picked from commit e7f1268478)
2023-10-01 14:01:21 +02:00
ailin-nemui
db4dad3dd0 Merge pull request #1493 from ailin-nemui/macsuffix
add explicit name_suffix to shared modules

(cherry picked from commit f1c9fb4296)
2023-10-01 14:01:11 +02:00
ailin-nemui
1226a587b7 Merge pull request #1492 from ailin-nemui/meson-apple
document meson apple workaround

(cherry picked from commit 8c8e4e34d4)
2023-10-01 13:57:17 +02:00
ailin-nemui
5a0dc0db09 Merge pull request #1488 from emilengler/remove-unused-var
core: remove unused len variable
(cherry picked from commit f04375668c)
2023-10-01 13:55:52 +02:00
ailin-nemui
590ca4dbdf Merge pull request #1484 from ailin-nemui/realposix
change realpath to use syntax based on _POSIX_VERSION

(cherry picked from commit f9c9485d15)
2023-10-01 13:54:39 +02:00
ailin-nemui
edfbc1f2f6 Merge pull request #1478 from ailin-nemui/buildperl
update perl requirement in install file

(cherry picked from commit 3f203dc382)
2023-10-01 13:53:35 +02:00
ailin-nemui
7f32ed012c Merge pull request #1474 from ailin-nemui/perl5380
fix usage of $type in ExtUtils::ParseXS 3.50

(cherry picked from commit da49ec62e6)
2023-10-01 13:51:11 +02:00
ailin-nemui
7f67b5deb0 Merge pull request #1471 from irssi/from-codeberg
Sync

(cherry picked from commit 274977a587)
2023-10-01 13:50:19 +02:00
ailin-nemui
8afbd6511c Merge pull request #1467 from ScoreUnder/perl_warning_to_stderr
Print perl import warning to STDERR

(cherry picked from commit e732b601f7)
2023-10-01 13:48:49 +02:00
ailin-nemui
6b65492b65 Merge pull request #1462 from mauke/upgrade-tilde-expand
expand ~ to $HOME in /upgrade

(cherry picked from commit 5c42345ea2)
2023-10-01 13:47:36 +02:00
ailin-nemui
160c2401a5 Merge pull request #1458 from ailin-nemui/help-toglev
update level toggle help

(cherry picked from commit c6ad171fe9)
2023-10-01 13:46:28 +02:00
ailin-nemui
48bc90eb17
Merge pull request #1498 from ailin-nemui/perl5380locale
Restore locale after loading Perl
2023-10-01 11:31:07 +00:00
Ailin Nemui
dfca0a9f84 Restore locale after loading Perl 2023-09-22 14:59:22 +02:00
ailin-nemui
2a1291f26f
Merge pull request #1497 from ailin-nemui/github-workflow-error
Slightly improve GitHub workflow
2023-09-14 13:32:44 +00:00
Ailin Nemui
7c5b2db269 add separate annotation-warnings step
see 2908d82845/src/Runner.Worker/Handlers/OutputManager.cs (L320)
see https://github.com/actions/runner/issues/763#issuecomment-1435735340
2023-09-14 15:24:19 +02:00
ailin-nemui
db32744ee4
Merge pull request #1495 from ailin-nemui/terminclude
fe-text: include the real tputs(3) from term.h
2023-09-13 20:55:21 +00:00
Ailin Nemui
4bc354d5e4 load all modules in the right order during check 2023-09-13 22:54:46 +02:00
Ailin Nemui
8c2fa0687e silence clang perl warning on affected version 2023-09-13 22:51:29 +02:00
Emil Engler
4ceafbeea4 fe-text: include the real tputs(3) from term.h
This commit includes the real `tpus(3)` function from the appropriate
`term.h` header file, if found.

This commit is necessary to fix a compiler warning on Darwin.
2023-09-12 17:20:21 +02:00
ailin-nemui
f04375668c
Merge pull request #1488 from emilengler/remove-unused-var
core: remove unused len variable
2023-09-12 14:53:59 +00:00
Ailin Nemui
fe6013be42 improve code formatting 2023-09-12 13:51:36 +02:00
ailin-nemui
f1c9fb4296
Merge pull request #1493 from ailin-nemui/macsuffix
add explicit name_suffix to shared modules
2023-09-12 11:27:03 +00:00
ailin-nemui
e7f1268478
Merge pull request #1494 from RealKindOne/master
Add -notls and -notls_verify into help file and src/core/chat-commands.c
2023-09-09 11:00:37 +00:00
KindOne
9ab78d0160 Add -notls and -notls_verify into help file and src/core/chat-commands.c 2023-09-09 05:25:30 -04:00
ailin-nemui
8c8e4e34d4
Merge pull request #1492 from ailin-nemui/meson-apple
document meson apple workaround
2023-09-06 14:04:20 +00:00
Ailin Nemui
523a42e6f0 document meson apple workaround
workaround for https://github.com/mesonbuild/meson/issues/11165
2023-09-04 21:42:18 +02:00
ailin-nemui
58ca3af360
Merge pull request #1491 from ailin-nemui/serveradd-crash
stop crash on server add
2023-08-26 17:11:38 +00:00
Ailin Nemui
a037f68f02 stop crash on server add
reported by nsprra
2023-08-22 22:28:36 +02:00
ailin-nemui
07b971cf0c
Merge pull request #1486 from vague666/edit_command_history
patch by petteri_ to enable bash-like editing of window history
2023-08-18 13:57:14 +00:00
Emil Engler
3aa9734c1c
core: remove unused len variable
This commit removes the unused `len` variable, which gets set quite a
few times, but whose value is totally unused.

This also fixes a compiler warning I get on my Darwin.
2023-08-14 12:01:31 +02:00
vague666
96dbcef166 patch by petteri_ to enable bash-like editing of window history 2023-08-14 11:35:06 +02:00
Ailin Nemui
c0db0b8cb8 add explicit name_suffix to shared modules 2023-08-10 10:19:01 +02:00
ailin-nemui
f9c9485d15
Merge pull request #1484 from ailin-nemui/realposix
change realpath to use syntax based on _POSIX_VERSION
2023-08-09 18:52:16 +00:00
Ailin Nemui
1131a881cf change realpath to use syntax based on _POSIX_VERSION 2023-08-08 07:59:31 +02:00
ailin-nemui
3f203dc382
Merge pull request #1478 from ailin-nemui/buildperl
update perl requirement in install file
2023-07-19 18:26:45 +00:00
Ailin Nemui
c93c61bf99 update perl requirement in install file 2023-07-19 20:04:25 +02:00
ailin-nemui
da49ec62e6
Merge pull request #1474 from ailin-nemui/perl5380
fix usage of $type in ExtUtils::ParseXS 3.50
2023-07-18 22:05:28 +00:00
Ailin Nemui
3ec05851a0 fix usage of $type in ExtUtils::ParseXS 3.50 2023-07-04 12:33:01 +02:00
ailin-nemui
274977a587
Merge pull request #1471 from irssi/from-codeberg
Sync
2023-05-25 11:00:40 +00:00
ailin-nemui
83ebc0a0e3
Merge pull request #1457 from examknow/listmode-timestamps
properly format listmodes and their timestamps
2023-05-25 11:00:32 +00:00
Ailin Nemui
685816e945 up abi 2023-05-25 11:48:31 +02:00
Ailin Nemui
0355ed0bea format 2023-05-25 11:42:15 +02:00
Ailin Nemui
0bcff291e9 order 2023-05-25 11:36:25 +02:00
ailin-nemui
ffe4dbac67 Merge pull request 'Fix logic in how own actions are printed for other protocols' (!5) from ticho/irssi:nonirc-own-action-print-fix into master
Reviewed-on: https://codeberg.org/irssi/irssi/pulls/5
2023-05-05 11:33:59 +00:00
Andrej Kacian
9e9858638d Fix logic in how own actions are printed for other protocols
When working with channels belonging to other, non-IRC protocols,
calling irc_channel_find() returns NULL, which makes irssi
use IRCTXT_OWN_ACTION_TARGET format, instead of the correct
IRCTXT_OWN_ACTION.

Using generic channel_find() instead fixes the issue.
2023-05-04 23:10:27 +02:00
ailin-nemui
e732b601f7
Merge pull request #1467 from ScoreUnder/perl_warning_to_stderr
Print perl import warning to STDERR
2023-04-15 14:08:31 +00:00
Score_Under
c5df1c01cc
Print perl import warning to STDERR
Printing to STDOUT can interfere with programs which intend to produce
machine-readable output and yet for whatever reason import Irssi.pm from
outside of irssi.

Closes https://github.com/irssi/irssi/issues/1465
2023-04-15 00:39:38 +01:00
ailin-nemui
a8a2460531
Merge pull request #1463 from ailin-nemui/github-ubuntu
update github workflows ubuntu
2023-04-04 13:29:32 +00:00
Ailin Nemui
a93c51796d update github workflows ubuntu 2023-04-04 15:18:54 +02:00
ailin-nemui
5c42345ea2
Merge pull request #1462 from mauke/upgrade-tilde-expand
expand ~ to $HOME in /upgrade
2023-04-04 13:12:50 +00:00
Lukas Mai
ca148a0122 expand ~ to $HOME in /upgrade
Fixes #1460.
2023-04-04 11:24:18 +02:00
ailin-nemui
c6ad171fe9
Merge pull request #1458 from ailin-nemui/help-toglev
update level toggle help
2023-03-31 12:43:36 +00:00
Ailin Nemui
960d185b42 update level toggle help 2023-03-31 14:42:50 +02:00
Ailin Nemui
152468efd0 Merge tag '1.4.4' into integrate/1.4.4 2023-03-31 04:24:56 +08:00
Ailin Nemui
a09fcb9093 tag as 1.4.4 2023-03-28 14:12:28 +02:00
David Schultz
ee12134812
clean up time_ago()
Co-authored-by: Doug Freed <dwfreed@mtu.edu>
2023-03-27 19:37:48 -05:00
David Schultz
201296a0da add time_ago() in addition to timestamps; deduplicate qlist logic 2023-03-27 18:21:36 -05:00
ailin-nemui
78d00b99b4 Merge pull request #1456 from ailin-nemui/collector
fix stale special collector use after free

(cherry picked from commit c03057f36a)
2023-03-27 23:21:04 +02:00
ailin-nemui
9948a18fce Merge pull request #1455 from irssi/vague666-typo-fix
Update ignore.in

(cherry picked from commit 6671fec9a9)
2023-03-27 23:21:00 +02:00
ailin-nemui
6d3284f7e9 Merge pull request #1454 from irssi/from-codeberg
Sync

(cherry picked from commit 2b91c45f5d)
2023-03-27 23:20:56 +02:00
ailin-nemui
38a80b21ea Merge pull request #1453 from irssi/vague666-ignore-in-update
Update ignore.in

(cherry picked from commit 706b6fff81)
2023-03-27 23:20:43 +02:00
ailin-nemui
d1319b422b Merge pull request #1452 from irssi/vague666-levels-in-update
Update levels.in

(cherry picked from commit 1c9990acab)
2023-03-27 23:20:30 +02:00
ailin-nemui
75fd596084 Merge pull request #1447 from ailin-nemui/signalsfile-fix
fix signalsfile some more

(cherry picked from commit c1fd4b17f5)
2023-03-27 23:19:50 +02:00
ailin-nemui
82618ce25d Merge pull request #1446 from ailin-nemui/signalsfile-fix
fix signals file

(cherry picked from commit 2ac1f01b94)
2023-03-27 23:19:43 +02:00
ailin-nemui
377824ae7f Merge pull request #1442 from lheckemann/master
Support receiving monospace

(cherry picked from commit c06be88d8f)
2023-03-27 23:19:16 +02:00
ailin-nemui
2f0a165569 Merge pull request #1439 from irssi/from-codeberg
Sync

(cherry picked from commit de43e9e067)
2023-03-27 23:18:15 +02:00
ailin-nemui
0438c7f0b2 Merge pull request #1438 from qoreQyaS/master
Lang-Fix: Use more general messages
(cherry picked from commit 162dc256be)
2023-03-27 23:18:00 +02:00
ailin-nemui
af8e40b744 Merge pull request #1434 from irssi/ailin-nemui/statusbar-help
correct statusbar help text

(cherry picked from commit 7445ad1f15)
2023-03-27 23:17:36 +02:00
ailin-nemui
473cf8ca3f Merge pull request #1432 from horgh/horgh/win-logfile
Check window logfile parameter

(cherry picked from commit 6f5026fd49)
2023-03-27 23:17:12 +02:00
ailin-nemui
f422b98613 Merge pull request #1431 from ailin-nemui/missing-news
add missing news reference

(cherry picked from commit f8500320cf)
2023-03-27 23:15:41 +02:00
ailin-nemui
8a8fb77408 Merge pull request #1429 from ailin-nemui/docs-revamp
remove ported sections from manual and add links

(cherry picked from commit 42f83fc130)
2023-03-27 23:14:58 +02:00
ailin-nemui
8f79457769 Merge pull request #1428 from ailin-nemui/flip-level
add (hide)level flip command

(cherry picked from commit 88cc48651d)
2023-03-27 23:14:28 +02:00
ailin-nemui
1426ae87b1 Merge pull request #1424 from ailin-nemui/lastlog
fix lastlog -window

(cherry picked from commit 6e3745f423)
2023-03-27 23:13:48 +02:00
ailin-nemui
f32701b906 Merge pull request #1421 from j1mmie/patch-1
Add parameter LIST to STATUSBAR documentation

(cherry picked from commit b988b2925b)
2023-03-27 23:00:46 +02:00
Ailin Nemui
f21df708b0 up version 2023-03-27 22:59:49 +02:00
ailin-nemui
c03057f36a
Merge pull request #1456 from ailin-nemui/collector
fix stale special collector use after free
2023-03-27 20:46:56 +00:00
ailin-nemui
d627e56021
Merge pull request #1450 from ailin-nemui/fix-1449
fix crash on connect in startup
2023-03-27 20:46:41 +00:00
David Schultz
9324ff9f68 this should work for everyone 2023-03-27 11:05:40 -05:00
David Schultz
556f580f67 add support for ircd-hybrid quiet lists 2023-03-26 19:27:48 -05:00
Ailin Nemui
c554a45738 fix stale special collector use after free
reported by ednash and investigated by @dwfreed
2023-03-26 23:37:12 +02:00
David Schultz
2db9dfbb46 properly format listmodes and their timestamps 2023-03-26 16:36:27 -05:00
ailin-nemui
6671fec9a9
Merge pull request #1455 from irssi/vague666-typo-fix
Update ignore.in
2023-03-21 08:49:09 +00:00
Jari Matilainen
5153bb3ff5
Update ignore.in
Fix typo
2023-03-21 09:44:01 +01:00
ailin-nemui
2b91c45f5d
Merge pull request #1454 from irssi/from-codeberg
Sync
2023-03-21 07:05:33 +00:00
ailin-nemui
bdec87e208 Merge pull request 'Fix logic in how actions are printed for other protocols' (!3) from ticho/irssi:nonirc-action-print-fix into master
Reviewed-on: https://codeberg.org/irssi/irssi/pulls/3
2023-03-21 06:25:57 +00:00
Andrej Kacian
3057c9e920 Fix logic in how actions are printed for other protocols
This causes subsequent window_item_set_active() check, further
down in the same function, to evaluate correctly, and getting
the action message printed using correct format.
2023-03-21 06:25:57 +00:00
ailin-nemui
1c9990acab
Merge pull request #1452 from irssi/vague666-levels-in-update
Update levels.in
2023-03-20 19:31:56 +00:00
ailin-nemui
706b6fff81
Merge pull request #1453 from irssi/vague666-ignore-in-update
Update ignore.in
2023-03-20 19:31:40 +00:00
Jari Matilainen
82bfd3abfe
Update ignore.in
Add NOHILIGHT description to help
2023-03-20 11:04:39 +01:00
Jari Matilainen
0334de0a05
Update levels.in
Make it more clear what NOHILIGHT can be used for
2023-03-20 11:00:37 +01:00
Ailin Nemui
7d3640ce2e fix crash on connect in startup
fixes #1449

does not completely fix the issue (connect still does not work, error message is misleading)
2023-02-25 20:44:12 +01:00
ailin-nemui
c1fd4b17f5
Merge pull request #1447 from ailin-nemui/signalsfile-fix
fix signalsfile some more
2023-02-13 08:51:33 +00:00
Ailin Nemui
25273898bf still didn't work 2023-02-12 16:31:23 +01:00
ailin-nemui
2ac1f01b94
Merge pull request #1446 from ailin-nemui/signalsfile-fix
fix signals file
2023-02-12 13:51:44 +00:00
Ailin Nemui
fcbe19eb8c fix signals file 2023-02-12 10:35:12 +01:00
ailin-nemui
72df66524b
Merge pull request #1445 from jesopo/ipv6-default
switch to prefering ipv6 by default
2023-02-09 17:41:11 +00:00
jesopo
9a29bf1022 switch to prefering ipv6 by default 2023-02-09 17:18:52 +00:00
ailin-nemui
c06be88d8f
Merge pull request #1442 from lheckemann/master
Support receiving monospace
2023-02-02 17:03:53 +01:00
Linus Heckemann
b91a56c2cd Support receiving monospace
0x11 (decimal 17) is used to denote monospace by a number of clients
according to https://modern.ircdocs.horse/formatting.html
2023-01-28 19:31:14 +01:00
ailin-nemui
3fb147ec72
Merge pull request #1441 from ailin-nemui/gh-actions
chores: update for github workflows deprecations
2023-01-22 16:49:20 +01:00
Ailin Nemui
274868d560 chores: update for github workflows deprecations 2023-01-22 16:39:05 +01:00
ailin-nemui
de43e9e067
Merge pull request #1439 from irssi/from-codeberg
Sync
2023-01-21 16:48:36 +01:00
ailin-nemui
fe8f2a5dc8
Merge pull request #1440 from ailin-nemui/termux-git
update termux package to git+
2023-01-21 16:44:18 +01:00
ailin-nemui
6bab6e2c06
update termux package to git+
20bd0f0dc0
2023-01-21 16:38:40 +01:00
ailin-nemui
251522685d Merge pull request 'Expose location of signals.txt via pkg-config' (!1) from ticho/irssi:signalsfile into master
Reviewed-on: https://codeberg.org/irssi/irssi/pulls/1
2023-01-19 21:50:41 +00:00
Andrej Kacian
c65bf6899f Expose location of signals.txt via pkg-config
Adds "signalsfile" variable to installed irssi-1.pc.
2023-01-19 22:41:51 +01:00
ailin-nemui
162dc256be
Merge pull request #1438 from qoreQyaS/master
Lang-Fix: Use more general messages
2022-12-25 17:51:32 +01:00
Sven "qoreQyaS" Grewe
f852cc4eb3 Lang-Fix: Use more general messages
* Changed the messages for /window level and /window immortal to a more
  general tone.
  Executing both commands without parameter show the current state but
  the old messages indicate a change of state.

Signed-off-by: Sven "qoreQyaS" Grewe <git@gucke.net>
2022-12-25 16:09:27 +01:00
ailin-nemui
6f5026fd49
Merge pull request #1432 from horgh/horgh/win-logfile
Check window logfile parameter
2022-12-23 10:34:56 +01:00
Will Storey
3415718ea7 Check a logfile parameter is given
Previously this continued with an empty filename, resulting in a broken
config file.

Fixes #1392.
2022-12-23 10:01:51 +01:00
Will Storey
6dfcde5acd Fix indentation issues in fe-log.c 2022-12-23 10:01:51 +01:00
ailin-nemui
8eca391b74
Merge pull request #1430 from ailin-nemui/config-lol
add list_of_lists to config and more error messages
2022-12-23 09:59:51 +01:00
ailin-nemui
7445ad1f15
Merge pull request #1434 from irssi/ailin-nemui/statusbar-help
correct statusbar help text
2022-12-18 21:53:34 +01:00
ailin-nemui
a83f94484c
correct statusbar help text 2022-12-18 21:53:27 +01:00
Ailin Nemui
19be330489 up abi 2022-12-18 21:11:54 +01:00
Ailin Nemui
e7fb82db89 update glib version to fix timezone assertion bug 2022-12-18 20:00:29 +01:00
Ailin Nemui
1453f46fcf add timezone to g_date_time_new_from_iso8601 call 2022-12-18 16:34:15 +01:00
ailin-nemui
f8500320cf
Merge pull request #1431 from ailin-nemui/missing-news
add missing news reference
2022-12-18 12:27:29 +01:00
Ailin Nemui
7f4bf738a3 add missing news reference 2022-12-18 12:27:00 +01:00
Ailin Nemui
8d7449d26f add list_of_lists to config and more error messages 2022-12-18 12:20:07 +01:00
ailin-nemui
b988b2925b
Merge pull request #1421 from j1mmie/patch-1
Add parameter LIST to STATUSBAR documentation
2022-12-18 12:18:13 +01:00
Jimmie Tyrrell
41071247f2 Add parameter LIST to STATUSBAR documentation
This command was not outlined in the documentation. `/STATUSBAR LIST` is an integral part of statusbar management and should be included.
2022-12-18 12:17:26 +01:00
ailin-nemui
42f83fc130
Merge pull request #1429 from ailin-nemui/docs-revamp
remove ported sections from manual and add links
2022-12-18 12:14:22 +01:00
Ailin Nemui
119d3203e1 remove ported sections from manual and add links 2022-12-18 12:13:38 +01:00
ailin-nemui
88cc48651d
Merge pull request #1428 from ailin-nemui/flip-level
add (hide)level flip command
2022-11-29 20:05:52 +01:00
Ailin Nemui
261a7ce76e add (hide)level flip command 2022-11-27 17:14:19 +01:00
ailin-nemui
6e3745f423
Merge pull request #1424 from ailin-nemui/lastlog
fix lastlog -window
2022-11-26 15:09:50 +01:00
Ailin Nemui
7d20ea92ae fix lastlog -window 2022-11-13 11:35:41 +01:00
Ailin Nemui
684094aa85 Merge tag '1.4.3' into integrate/1.4.3 2022-10-29 12:22:58 +02:00
Ailin Nemui
c99c8b444d tag as 1.4.3 2022-10-29 12:13:46 +02:00
ailin-nemui
f9f6341c20 Merge pull request #1420 from ailin-nemui/starttls-config
enable saving of -disallow_starttls

(cherry picked from commit afba148056)
2022-10-29 12:07:34 +02:00
ailin-nemui
9a95edc69a Merge pull request #1419 from ailin-nemui/init-irc-funcs
move irc server functions to object creation time

(cherry picked from commit a661e2fb35)
2022-10-29 12:07:23 +02:00
ailin-nemui
93a94308bd Merge pull request #1417 from ailin-nemui/loop
do not freeze on alt+left/right

(cherry picked from commit 0c97433c7c)
2022-10-29 12:07:05 +02:00
ailin-nemui
afba148056
Merge pull request #1420 from ailin-nemui/starttls-config
enable saving of -disallow_starttls
2022-10-15 08:52:40 +02:00
ailin-nemui
a661e2fb35
Merge pull request #1419 from ailin-nemui/init-irc-funcs
move irc server functions to object creation time
2022-10-15 08:52:32 +02:00
ailin-nemui
0c97433c7c
Merge pull request #1417 from ailin-nemui/loop
do not freeze on alt+left/right
2022-10-15 08:52:20 +02:00
ailin-nemui
26f9750ad1 Merge pull request #1414 from irssi/vague666-patch-4
Add -nocap to /connect and /server connect syntax

(cherry picked from commit 55913ade13)
2022-10-14 22:41:21 +02:00
ailin-nemui
277923aaac Merge pull request #1413 from irssi/vague666-patch-3
Update /server syntax line

(cherry picked from commit 238d7cfd08)
2022-10-14 22:41:21 +02:00
ailin-nemui
23419e5866 Merge pull request #1415 from irssi/vague666-patch-5
/server: Add help for -cap/-nocap

(cherry picked from commit f76d41953f)
2022-10-14 22:41:21 +02:00
ailin-nemui
2c18da3cc6 Merge pull request #1411 from irssi/vague666-patch-1
/connect: Add help for -nocap

(cherry picked from commit 38b18bd84d)
2022-10-14 22:41:21 +02:00
ailin-nemui
c01b35b062 Merge pull request #1407 from madpilot78/Fix_libnv_detection
Fix libnv detection on recent FreeBSD

(cherry picked from commit f32d0ab51a)
2022-10-14 22:41:21 +02:00
ailin-nemui
f51bc42429 Merge pull request #1380 from ailin-nemui/scriptassist
run syncscripts.sh

(cherry picked from commit 68823eb6af)
2022-10-14 21:46:50 +02:00
ailin-nemui
be5f917f07 Merge pull request #1393 from ailin-nemui/eval-help
minor rendering fix in eval help

(cherry picked from commit 0bf18beed7)
2022-10-14 21:46:30 +02:00
Ailin Nemui
833f41179d enable saving of -disallow_starttls 2022-10-14 21:37:09 +02:00
Ailin Nemui
c2457c7d94 move irc server functions to object creation time 2022-10-14 21:06:51 +02:00
Ailin Nemui
093dcd423f no infinite loops please 2022-09-22 22:25:02 +02:00
ailin-nemui
55913ade13
Merge pull request #1414 from irssi/vague666-patch-4
Add -nocap to /connect and /server connect syntax
2022-09-14 09:24:35 +02:00
ailin-nemui
de2bf6707f fix clang-format 2022-09-14 09:19:18 +02:00
ailin-nemui
238d7cfd08
Merge pull request #1413 from irssi/vague666-patch-3
Update /server syntax line
2022-09-13 09:52:30 +02:00
ailin-nemui
f76d41953f
Merge pull request #1415 from irssi/vague666-patch-5
/server: Add help for -cap/-nocap
2022-09-13 09:51:57 +02:00
ailin-nemui
38b18bd84d
Merge pull request #1411 from irssi/vague666-patch-1
/connect: Add help for -nocap
2022-09-13 09:51:43 +02:00
Jari Matilainen
d448ca3341
/server: Add help for -cap/-nocap 2022-09-12 14:17:34 +02:00
Jari Matilainen
07041c37d4
Add -nocap to /connect and /server connect syntax 2022-09-12 14:15:11 +02:00
Jari Matilainen
fe77b7e06f
Update /server syntax line 2022-09-12 14:07:05 +02:00
Jari Matilainen
03edebd54c
/connect: Add help for -nocap 2022-09-12 14:03:21 +02:00
ailin-nemui
f32d0ab51a
Merge pull request #1407 from madpilot78/Fix_libnv_detection
Fix libnv detection on recent FreeBSD
2022-08-19 10:42:05 +02:00
Guido Falsi
7baefc3315 Fix libnv detection on recent FreeBSD
On recent FreeBSD systems it is required to include the sys/nv.h file, otherwise symbols are missing.

Reported here: https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=265397

Patch suggested by: Kristof Provost <kp@freebsd.org>
2022-08-19 10:32:47 +02:00
ailin-nemui
58109aeeed
Merge pull request #1403 from lnde/fetext-sigterm
Re-write SIGTERM handling
2022-08-12 12:17:49 +02:00
Andreas Lundin
a237321b33 re-write SIGTERM handling
Exit safely on SIGTERM by emitting "gui exit" from the main loops of
fe-text and fe-none rather than from the signal handler itself.

Based on feedback from Nei and dwfreed.
2022-08-11 20:09:59 +00:00
ailin-nemui
555030a2ad
Merge pull request #1405 from ailin-nemui/no-chatnet-crash
fix crash when loading server without chatnet
2022-08-08 22:20:19 +02:00
Ailin Nemui
252656cad4 fix crash when loading server without chatnet 2022-07-24 19:32:47 +02:00
Ailin Nemui
722d3c4c3d Merge tag '1.4.2' into integrate/1.4.2 2022-07-13 20:33:59 +02:00
Ailin Nemui
bc805f9bcd tag as 1.4.2 2022-07-13 20:08:52 +02:00
ailin-nemui
476774662a Merge pull request #1398 from ailin-nemui/lastlog-crash
get line texts before printing lastlog

(cherry picked from commit a57cc1c55e)
2022-07-13 19:12:01 +02:00
ailin-nemui
a57cc1c55e
Merge pull request #1398 from ailin-nemui/lastlog-crash
get line texts before printing lastlog
2022-07-13 19:10:50 +02:00
Ailin Nemui
7fe7de3c2e get line texts before printing lastlog 2022-07-12 20:50:01 +02:00
ailin-nemui
1b6b92ffff Merge pull request #1388 from ailin-nemui/default-hash-chan
default to hash channels

(cherry picked from commit a5f5ea7d79)
2022-07-03 00:14:14 +02:00
ailin-nemui
730c3c1a12 Merge pull request #1377 from ailin-nemui/meson
fix yet another meson regression

(cherry picked from commit 07aa061b6d)
2022-07-03 00:14:14 +02:00
ailin-nemui
c6a7f02042 Merge pull request #1383 from ailin-nemui/pc-moduledir
add irssimoduledir to irssi-1.pc

(cherry picked from commit 545d97f8d6)
2022-07-03 00:14:14 +02:00
ailin-nemui
f17fb68257 Merge pull request #1387 from ailin-nemui/textbufferview
Textbufferview

(cherry picked from commit 783dd37533)
2022-07-03 00:14:14 +02:00
ailin-nemui
3404d822c8 Merge pull request #1384 from ailin-nemui/meson-system-includes
use -isystem instead of -I for include directories

(cherry picked from commit 593afc2e40)
2022-07-03 00:14:14 +02:00
ailin-nemui
5b0f7f7899
Merge pull request #1394 from ailin-nemui/faster-termux-pkg
use less time on termux pkg
2022-07-02 16:09:05 +02:00
Ailin Nemui
3fec4d894f use less time on termux pkg
hard-code the values instead of building perl
2022-07-02 14:12:15 +02:00
ailin-nemui
0bf18beed7
Merge pull request #1393 from ailin-nemui/eval-help
minor rendering fix in eval help
2022-06-30 23:25:35 +02:00
Ailin Nemui
f135339e27 minor rendering fix in eval help 2022-06-30 23:13:48 +02:00
ailin-nemui
593afc2e40
Merge pull request #1384 from ailin-nemui/meson-system-includes
use -isystem instead of -I for include directories
2022-06-18 12:43:01 +02:00
ailin-nemui
783dd37533
Merge pull request #1387 from ailin-nemui/textbufferview
Textbufferview
2022-06-18 12:42:47 +02:00
Ailin Nemui
4dc3eb1048 update clang-format 2022-06-13 09:41:46 +02:00
Ailin Nemui
453e65bbfe misc cleanup 2022-06-13 09:41:46 +02:00
Ailin Nemui
b028b8e19d fix recount of lines after scroll 2022-06-13 09:41:46 +02:00
Ailin Nemui
48edd6f5fa fix recount of lines after window set 2022-06-13 08:22:18 +02:00
ailin-nemui
a5f5ea7d79
Merge pull request #1388 from ailin-nemui/default-hash-chan
default to hash channels
2022-06-13 07:39:29 +02:00
Ailin Nemui
891ef5df10 default to hash channels 2022-06-13 02:44:33 +02:00
Ailin Nemui
04b914dcb0 fix visible lines expiring from cache 2022-06-13 01:17:19 +02:00
Ailin Nemui
67aa2baf62 fix memory leak when updating single line 2022-06-13 01:17:19 +02:00
Ailin Nemui
ae8ec99d5c fix scrollback redraw not updating linecount 2022-06-13 01:17:19 +02:00
ailin-nemui
68823eb6af
Merge pull request #1380 from ailin-nemui/scriptassist
run syncscripts.sh
2022-06-12 18:11:05 +02:00
ailin-nemui
545d97f8d6
Merge pull request #1383 from ailin-nemui/pc-moduledir
add irssimoduledir to irssi-1.pc
2022-06-12 18:10:50 +02:00
Ailin Nemui
279fa4e5b8 remove relevant code from termux receipe 2022-06-12 17:18:53 +02:00
Ailin Nemui
528632bba2 use -isystem instead of -I for include directories
limits warnings to our own code
2022-06-12 17:13:28 +02:00
Ailin Nemui
34d45ac678 add irssimoduledir to irssi-1.pc
for module authors to know where to install to
2022-06-12 16:52:31 +02:00
Ailin Nemui
88745d2941 run syncscripts.sh 2022-06-12 12:34:33 +02:00
ailin-nemui
07aa061b6d
Merge pull request #1377 from ailin-nemui/meson
fix yet another meson regression
2022-06-12 05:33:41 +02:00
Ailin Nemui
ac35fe010e fix yet another meson regression
broken by meson 0.60.0
2022-06-11 22:58:56 +02:00
Ailin Nemui
de46fee864 update website 2022-06-11 18:10:29 +02:00
Ailin Nemui
f2c5e60766 revert branding 2022-06-07 15:47:49 +02:00
167 changed files with 4109 additions and 1803 deletions

View file

@ -3,8 +3,8 @@ name: abicheck
env: env:
build_options: -Dbuildtype=debug -Denable-true-color=yes -Dwith-proxy=yes -Dc_args=-DPERL_EUPXS_ALWAYS_EXPORT build_options: -Dbuildtype=debug -Denable-true-color=yes -Dwith-proxy=yes -Dc_args=-DPERL_EUPXS_ALWAYS_EXPORT
prefix: /usr/local prefix: /usr/local
apt_build_deps: ninja-build libutf8proc-dev libperl-dev libotr5-dev apt_build_deps: ninja-build libutf8proc-dev libperl-dev libotr5-dev libglib2.0-dev
get_pip_build_deps: pip3 install setuptools; pip3 install wheel; pip3 install 'meson<0.59.0' get_pip_build_deps: pip3 install 'setuptools<66'; pip3 install wheel; pip3 install 'meson<0.59.0'
getabidef_def: getabidef() { awk '$1=="#define" && $2=="IRSSI_ABI_VERSION" { print $3 }' "$1"/include/irssi/src/common.h; } getabidef_def: getabidef() { awk '$1=="#define" && $2=="IRSSI_ABI_VERSION" { print $3 }' "$1"/include/irssi/src/common.h; }
jobs: jobs:
build-base-ref: build-base-ref:
@ -17,7 +17,7 @@ jobs:
echo "$HOME/.local/bin" >> $GITHUB_PATH echo "$HOME/.local/bin" >> $GITHUB_PATH
- name: prepare required software - name: prepare required software
run: | run: |
sudo apt install $apt_build_deps sudo apt update; sudo apt install $apt_build_deps
eval "$get_pip_build_deps" eval "$get_pip_build_deps"
- name: checkout base ref - name: checkout base ref
uses: actions/checkout@main uses: actions/checkout@main
@ -36,8 +36,8 @@ jobs:
base_abi=$(getabidef base$prefix) base_abi=$(getabidef base$prefix)
echo base abi : $base_abi echo base abi : $base_abi
./base$prefix/bin/irssi --version ./base$prefix/bin/irssi --version
echo "::set-output name=base_abi::$base_abi" echo base_abi=$base_abi >> $GITHUB_OUTPUT
- uses: actions/upload-artifact@v2 - uses: actions/upload-artifact@v4
with: with:
name: base.inst name: base.inst
path: base path: base
@ -52,7 +52,7 @@ jobs:
echo "$HOME/.local/bin" >> $GITHUB_PATH echo "$HOME/.local/bin" >> $GITHUB_PATH
- name: prepare required software - name: prepare required software
run: | run: |
sudo apt install $apt_build_deps sudo apt update; sudo apt install $apt_build_deps
eval "$get_pip_build_deps" eval "$get_pip_build_deps"
- name: checkout merge ref - name: checkout merge ref
uses: actions/checkout@main uses: actions/checkout@main
@ -70,8 +70,8 @@ jobs:
merge_abi=$(getabidef merge$prefix) merge_abi=$(getabidef merge$prefix)
echo merge abi : $merge_abi echo merge abi : $merge_abi
./merge$prefix/bin/irssi --version ./merge$prefix/bin/irssi --version
echo "::set-output name=merge_abi::$merge_abi" echo merge_abi=$merge_abi >> $GITHUB_OUTPUT
- uses: actions/upload-artifact@v2 - uses: actions/upload-artifact@v4
with: with:
name: merge.inst name: merge.inst
path: merge path: merge
@ -87,14 +87,14 @@ jobs:
steps: steps:
- name: prepare required software - name: prepare required software
run: | run: |
sudo apt install abigail-tools sudo apt update; sudo apt install abigail-tools
- name: fetch base build - name: fetch base build
uses: actions/download-artifact@v2 uses: actions/download-artifact@v4
with: with:
name: base.inst name: base.inst
path: base path: base
- name: fetch merge build - name: fetch merge build
uses: actions/download-artifact@v2 uses: actions/download-artifact@v4
with: with:
name: merge.inst name: merge.inst
path: merge path: merge
@ -103,7 +103,7 @@ jobs:
abipkgdiff -l base merge >abipkgdiff.out && diff_ret=0 || diff_ret=$? abipkgdiff -l base merge >abipkgdiff.out && diff_ret=0 || diff_ret=$?
echo "diff_ret=$diff_ret" >> $GITHUB_ENV echo "diff_ret=$diff_ret" >> $GITHUB_ENV
cat abipkgdiff.out cat abipkgdiff.out
- uses: actions/upload-artifact@v2 - uses: actions/upload-artifact@v4
with: with:
path: abipkgdiff.out path: abipkgdiff.out
- run: | - run: |

View file

@ -5,23 +5,50 @@ on:
pull_request: pull_request:
name: Check Irssi name: Check Irssi
env: env:
apt_build_deps: libutf8proc-dev libperl-dev libotr5-dev apt_build_deps: ninja-build libutf8proc-dev libperl-dev libotr5-dev libglib2.0-dev
apt_build_deps_meson: ninja-build
get_pip_build_deps_meson: pip3 install setuptools${setuptools_ver}; pip3 install wheel; pip3 install meson${meson_ver} get_pip_build_deps_meson: pip3 install setuptools${setuptools_ver}; pip3 install wheel; pip3 install meson${meson_ver}
build_options_meson: -Dwith-proxy=yes -Dwith-bot=yes -Dwith-perl=yes -Dwith-otr=yes build_options_meson: -Dwith-proxy=yes -Dwith-bot=yes -Dwith-perl=yes -Dwith-otr=yes
prefix: ~/irssi-build prefix: ~/irssi-build
jobs: jobs:
dist: dist:
runs-on: ubuntu-latest runs-on: ubuntu-latest
env:
meson_ver: <0.63.0
setuptools_ver: <66
steps: steps:
- name: prepare required software - name: prepare required software
run: | run: |
sudo apt update && sudo apt install $apt_build_deps sudo apt update && sudo apt install $apt_build_deps
eval "$get_pip_build_deps_meson"
patch ~/.local/lib/python3.12/site-packages/pkg_resources/__init__.py <<- PATCH
--- __init__.py 2024-12-16 20:37:46.733230351 +0100
+++ __init__.py 2024-12-16 20:38:42.479554540 +0100
@@ -2188,7 +2188,8 @@ def resolve_egg_link(path):
return next(dist_groups, ())
-register_finder(pkgutil.ImpImporter, find_on_path)
+if hasattr(pkgutil, 'ImpImporter'):
+ register_finder(pkgutil.ImpImporter, find_on_path)
if hasattr(importlib_machinery, 'FileFinder'):
register_finder(importlib_machinery.FileFinder, find_on_path)
@@ -2345,7 +2346,8 @@ def file_ns_handler(importer, path_item,
return subpath
-register_namespace_handler(pkgutil.ImpImporter, file_ns_handler)
+if hasattr(pkgutil, 'ImpImporter'):
+ register_namespace_handler(pkgutil.ImpImporter, file_ns_handler)
register_namespace_handler(zipimport.zipimporter, file_ns_handler)
if hasattr(importlib_machinery, 'FileFinder'):
PATCH
- uses: actions/checkout@main - uses: actions/checkout@main
- name: make dist - name: make dist
run: | run: |
./utils/make-dist.sh ./utils/make-dist.sh
- uses: actions/upload-artifact@v2 - uses: actions/upload-artifact@v4
with: with:
path: irssi-*.tar.gz path: irssi-*.tar.gz
retention-days: 1 retention-days: 1
@ -34,24 +61,21 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
os: [ubuntu-18.04, ubuntu-latest] os: [ubuntu-22.04, ubuntu-latest]
builder: [meson]
compiler: [clang, gcc] compiler: [clang, gcc]
flags: [regular] flags: [regular]
setuptools_ver: [<66]
include: include:
- os: ubuntu-18.04 - os: ubuntu-22.04
builder: meson
meson_ver: ==0.53.2 meson_ver: ==0.53.2
setuptools_ver: <51 setuptools_ver: <51
- os: ubuntu-latest - os: ubuntu-latest
builder: meson
meson_ver: <0.63.0 meson_ver: <0.63.0
- os: ubuntu-latest - os: ubuntu-latest
builder: meson
flags: meson-latest FAILURE-OK flags: meson-latest FAILURE-OK
steps: steps:
- name: fetch dist - name: fetch dist
uses: actions/download-artifact@v2 uses: actions/download-artifact@v4
- name: set PATH - name: set PATH
run: | run: |
echo "$HOME/.local/bin" >> $GITHUB_PATH echo "$HOME/.local/bin" >> $GITHUB_PATH
@ -60,8 +84,8 @@ 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 update && sudo apt install $apt_build_deps $apt_build_deps_${{ matrix.builder }} sudo apt update && sudo apt install $apt_build_deps
eval "$get_pip_build_deps_${{ matrix.builder }}" eval "$get_pip_build_deps_meson"
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
run: tar xaf artifact/irssi-*.tar.gz run: tar xaf artifact/irssi-*.tar.gz
@ -72,14 +96,12 @@ jobs:
meson Build $build_options_meson --prefix=${prefix/\~/~} meson Build $build_options_meson --prefix=${prefix/\~/~}
ninja -C Build ninja -C Build
ninja -C Build install ninja -C Build install
if: ${{ matrix.builder == 'meson' }}
- name: run tests with Meson - name: run tests with Meson
run: | run: |
# ninja test # ninja test
cd irssi-*/ cd irssi-*/
ninja -C Build test ninja -C Build test
find -name testlog.txt -exec sed -i -e '/Inherited environment:.* GITHUB/d' {} + -exec cat {} + find -name testlog.txt -exec sed -i -e '/Inherited environment:.* GITHUB/d' {} + -exec cat {} +
if: ${{ matrix.builder == 'meson' }}
- name: run launch test - name: run launch test
env: env:
TERM: xterm TERM: xterm
@ -93,9 +115,66 @@ jobs:
^set -clear log_day_changed ^set -clear log_day_changed
^set -clear log_open_string ^set -clear log_open_string
^set log_timestamp * ^set log_timestamp *
^window log on' > irssi-test/startup ^window log on
echo load perl >> irssi-test/startup load irc
echo load proxy >> irssi-test/startup load dcc
echo ^quit >> irssi-test/startup load flood
load notifylist
load perl
load otr
load proxy
^quit' > irssi-test/startup
irssi-build/bin/irssi --home irssi-test | perl -Mutf8 -C ~/render.pl
cat irc.log.*
annotation-warnings:
runs-on: ubuntu-latest
if: ${{ github.event_name == 'pull_request' }}
env:
CC: clang
steps:
- name: prepare required software
run: |
sudo apt update && sudo apt install $apt_build_deps
- uses: actions/checkout@main
- name: Setup local annotations
uses: irssi-import/actions-irssi/problem-matchers@master
- name: set PATH
run: |
echo "$HOME/.local/bin" >> $GITHUB_PATH
- name: prepare required software
env:
meson_ver: ${{ matrix.meson_ver }}
setuptools_ver: ${{ matrix.setuptools_ver }}
run: |
sudo apt update && sudo apt install $apt_build_deps
eval "$get_pip_build_deps_meson"
curl -SLf https://github.com/irssi-import/actions-irssi/raw/master/check-irssi/render.pl -o ~/render.pl && chmod +x ~/render.pl
- name: build and install with meson
run: |
meson Build $build_options_meson --prefix=${prefix/\~/~}
ninja -C Build
ninja -C Build install >/dev/null
- name: run launch test
env:
TERM: xterm
run: |
# automated irssi launch test
cd
mkdir irssi-test
echo 'echo automated irssi launch test
^set settings_autosave off
^set -clear log_close_string
^set -clear log_day_changed
^set -clear log_open_string
^set log_timestamp *
^window log on
load irc
load dcc
load flood
load notifylist
load perl
load otr
load proxy
^quit' > irssi-test/startup
irssi-build/bin/irssi --home irssi-test | perl -Mutf8 -C ~/render.pl irssi-build/bin/irssi --home irssi-test | perl -Mutf8 -C ~/render.pl
cat irc.log.* cat irc.log.*

View file

@ -44,7 +44,7 @@ jobs:
dry-run: false dry-run: false
sanitizer: ${{ matrix.sanitizer }} sanitizer: ${{ matrix.sanitizer }}
- name: Upload Crash - name: Upload Crash
uses: actions/upload-artifact@v1 uses: actions/upload-artifact@v4
if: failure() && steps.build.outcome == 'success' if: failure() && steps.build.outcome == 'success'
with: with:
name: ${{ matrix.sanitizer }}-artifacts name: ${{ matrix.sanitizer }}-artifacts

View file

@ -2,10 +2,10 @@ on: [pull_request]
name: clang-format name: clang-format
jobs: jobs:
check-clang-format: check-clang-format:
runs-on: ubuntu-20.04 runs-on: ubuntu-22.04
steps: steps:
- name: install clang-format - name: install clang-format
run: sudo apt install clang-format-11 run: sudo apt install clang-format-14
- uses: actions/checkout@main - uses: actions/checkout@main
- name: fetch target ref - name: fetch target ref
run: run:
@ -20,9 +20,9 @@ jobs:
- name: run git-clang-format and Check if no changes are needed - name: run git-clang-format and Check if no changes are needed
run: run:
| |
CLANG_FORMAT=clang-format-11 git-clang-format-11 --diff FETCH_HEAD HEAD | tee git-clang-format.diff CLANG_FORMAT=clang-format-14 git-clang-format-14 --diff FETCH_HEAD HEAD | tee git-clang-format.diff
cmp -s <(echo no modified files to format) git-clang-format.diff || cmp -s <(echo -n) git-clang-format.diff cmp -s <(echo no modified files to format) git-clang-format.diff || cmp -s <(echo -n) git-clang-format.diff
- uses: actions/upload-artifact@v1 - uses: actions/upload-artifact@v4
if: failure() if: failure()
with: with:
name: git-clang-format.diff name: git-clang-format.diff

32
.github/workflows/muon-fmt.yml vendored Normal file
View file

@ -0,0 +1,32 @@
name: Format meson files
on:
push:
pull_request:
permissions: {}
jobs:
muon-meson-fmt:
name: Format
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@main
with:
persist-credentials: false
# Build from source because Ubuntu 24.04 apt only has muon 0.2.0.
# Newer muons seem to format differently.
- name: Build muon from source
run: |
git clone --depth 1 --branch 0.5.0 https://github.com/muon-build/muon /tmp/muon
cd /tmp/muon
./bootstrap.sh build
build/muon-bootstrap setup build
build/muon-bootstrap -C build samu
sudo build/muon -C build install
- name: Run muon fmt
run: |
find . -name meson.build -print0 | xargs -0 muon fmt -c .muon_fmt.ini -i
git diff --exit-code

104
.github/workflows/solarisvm.yml vendored Normal file
View file

@ -0,0 +1,104 @@
on:
push:
branches:
- master
pull_request:
workflow_dispatch:
name: Check Irssi on Solaris
env:
get_pip_build_deps_meson: pip3 install setuptools${setuptools_ver}; pip3 install wheel
prefix: ~/irssi-build
jobs:
dist:
runs-on: ubuntu-latest
env:
setuptools_ver: <66
steps:
- name: prepare required software
run: |
sudo apt update && sudo apt install $apt_build_deps
eval "$get_pip_build_deps_meson"
patch ~/.local/lib/python3.12/site-packages/pkg_resources/__init__.py <<- PATCH
--- __init__.py 2024-12-16 20:37:46.733230351 +0100
+++ __init__.py 2024-12-16 20:38:42.479554540 +0100
@@ -2188,7 +2188,8 @@ def resolve_egg_link(path):
return next(dist_groups, ())
-register_finder(pkgutil.ImpImporter, find_on_path)
+if hasattr(pkgutil, 'ImpImporter'):
+ register_finder(pkgutil.ImpImporter, find_on_path)
if hasattr(importlib_machinery, 'FileFinder'):
register_finder(importlib_machinery.FileFinder, find_on_path)
@@ -2345,7 +2346,8 @@ def file_ns_handler(importer, path_item,
return subpath
-register_namespace_handler(pkgutil.ImpImporter, file_ns_handler)
+if hasattr(pkgutil, 'ImpImporter'):
+ register_namespace_handler(pkgutil.ImpImporter, file_ns_handler)
register_namespace_handler(zipimport.zipimporter, file_ns_handler)
if hasattr(importlib_machinery, 'FileFinder'):
PATCH
- uses: actions/checkout@main
- name: make dist
run: |
./utils/make-dist.sh
- uses: actions/upload-artifact@v4
with:
path: irssi-*.tar.gz
retention-days: 1
install:
runs-on: ubuntu-latest
needs: dist
steps:
- name: fetch dist
uses: actions/download-artifact@v4
- name: Test in Solaris
uses: vmactions/solaris-vm@v1
with:
usesh: true
sync: rsync
release: "11.4-gcc"
prepare: |
pkg update --accept || echo 1:$?
pkg install meson || echo 2:$?
pkgutil -y -i curl || echo 3:$?
pkgutil -y -i gtar || echo 4:$?
pkgutil -y -i findutils || echo 5:$?
run: |
set -ex
export PKG_CONFIG_PATH=/usr/lib/64/pkgconfig
curl -SLf https://github.com/irssi-import/actions-irssi/raw/master/check-irssi/render.pl -o ~/render.pl && chmod +x ~/render.pl
gtar xzf artifact/irssi-*.tar.gz
# ninja install
cd irssi-*/
meson Build -Dwith-proxy=yes -Dwith-bot=yes -Dwith-perl=yes --prefix=$HOME/irssi-build
ninja -C Build
ninja -C Build install
# ninja test
ninja -C Build test
gfind -name testlog.txt -exec gsed -i -e '/Inherited environment:.* GITHUB/d' {} + -exec cat {} +
export TERM=xterm
# automated irssi launch test
cd
mkdir irssi-test
echo 'echo automated irssi launch test
^set settings_autosave off
^set -clear log_close_string
^set -clear log_day_changed
^set -clear log_open_string
^set log_timestamp *
^window log on
load irc
load dcc
load flood
load notifylist
load perl
load otr
load proxy
^quit' > irssi-test/startup
irssi-build/bin/irssi --home irssi-test | perl -Mutf8 -C ~/render.pl
cat irc.log.*

View file

@ -18,50 +18,44 @@ jobs:
path: src.irssi.git path: src.irssi.git
- name: download termux docker container - name: download termux docker container
uses: docker://termux/package-builder:latest uses: docker://termux/package-builder:latest
- name: build perl package
run: |
./scripts/run-docker.sh ./build-package.sh -i perl
- name: create irssi build receipe - name: create irssi build receipe
run: | run: |
mkdir packages/irssi-an mkdir packages/irssi-an
cat << 'BUILD_SH' > packages/irssi-an/build.sh cat << 'BUILD_SH' > packages/irssi-an/build.sh
TERMUX_PKG_HOMEPAGE=https://ailin-nemui.github.io/irssi/ TERMUX_PKG_HOMEPAGE=https://irssi.org/
TERMUX_PKG_DESCRIPTION="Terminal based IRC client" TERMUX_PKG_DESCRIPTION="Terminal based IRC client"
TERMUX_PKG_LICENSE="GPL-2.0" TERMUX_PKG_LICENSE="GPL-2.0"
TERMUX_PKG_MAINTAINER="@ailin-nemui" TERMUX_PKG_MAINTAINER="@irssi"
TERMUX_PKG_VERSION=@VERSION@ TERMUX_PKG_VERSION=@VERSION@
TERMUX_PKG_REVISION=@REVISION@ TERMUX_PKG_REVISION=@REVISION@
TERMUX_PKG_SRCURL=file:///home/builder/termux-packages/src.irssi.git TERMUX_PKG_SRCURL=git+file:///home/builder/termux-packages/src.irssi.git
TERMUX_PKG_AUTO_UPDATE=true TERMUX_PKG_AUTO_UPDATE=true
TERMUX_PKG_DEPENDS="glib, libandroid-glob, libiconv, libotr, ncurses, openssl, perl, utf8proc" TERMUX_PKG_DEPENDS="glib, libandroid-glob, libiconv, libotr, ncurses, openssl, perl, utf8proc"
TERMUX_PKG_BREAKS="irssi" TERMUX_PKG_BREAKS="irssi"
TERMUX_PKG_REPLACES="irssi" TERMUX_PKG_REPLACES="irssi"
TERMUX_MESON_PERL_CROSS_FILE=$TERMUX_PKG_TMPDIR/meson-miniperl-cross-$TERMUX_ARCH.txt TERMUX_MESON_PERL_CROSS_FILE=$TERMUX_PKG_TMPDIR/meson-perl-cross-$TERMUX_ARCH.txt
TERMUX_PKG_EXTRA_CONFIGURE_ARGS=" TERMUX_PKG_EXTRA_CONFIGURE_ARGS="
-Dfhs-prefix=$TERMUX_PREFIX -Dfhs-prefix=$TERMUX_PREFIX
--cross-file $TERMUX_MESON_PERL_CROSS_FILE --cross-file $TERMUX_MESON_PERL_CROSS_FILE
" "
termux_step_post_configure() {
# Make build log less noisy.
sed -i "s:-I$TERMUX_PREFIX/:-isystem$TERMUX_PREFIX/:g" $TERMUX_PKG_BUILDDIR/build.ninja
}
termux_step_pre_configure() { termux_step_pre_configure() {
LDFLAGS+=" -landroid-glob" LDFLAGS+=" -landroid-glob"
# Make build log less noisy. # Make build log less noisy.
CFLAGS+=" -Wno-compound-token-split-by-macro" CFLAGS+=" -Wno-compound-token-split-by-macro"
# Make sure that perl stuff is reinstalled.
rm -rf $TERMUX_PREFIX/lib/irssi/perl
local perl_version=$(. $TERMUX_SCRIPTDIR/packages/perl/build.sh; echo $TERMUX_PKG_VERSION) local perl_version=$(. $TERMUX_SCRIPTDIR/packages/perl/build.sh; echo $TERMUX_PKG_VERSION)
local perl_srcdir=$TERMUX_TOPDIR/perl/src
cat <<MESON_PERL_CROSS >$TERMUX_MESON_PERL_CROSS_FILE cat << MESON_PERL_CROSS >$TERMUX_MESON_PERL_CROSS_FILE
[binaries] [properties]
perl = ['$perl_srcdir/miniperl', '-I$TERMUX_PREFIX/lib/perl5/$perl_version/${TERMUX_ARCH}-android', '-I$TERMUX_PREFIX/lib/perl5/$perl_version'] perl_version = '$perl_version'
perl_ccopts = ['-I$TERMUX_PREFIX/include', '-D_LARGEFILE_SOURCE', '-D_FILE_OFFSET_BITS=64', '-I$TERMUX_PREFIX/lib/perl5/$perl_version/${TERMUX_ARCH}-android/CORE']
perl_ldopts = ['-Wl,-E', '-I$TERMUX_PREFIX/include', '-L$TERMUX_PREFIX/lib/perl5/$perl_version/${TERMUX_ARCH}-android/CORE', '-lperl', '-lm', '-ldl']
perl_archname = '${TERMUX_ARCH}-android'
perl_installsitearch = '$TERMUX_PREFIX/lib/perl5/site_perl/$perl_version/${TERMUX_ARCH}-android'
perl_installvendorarch = ''
perl_inc = ['$TERMUX_PREFIX/lib/perl5/site_perl/$perl_version/${TERMUX_ARCH}-android', '$TERMUX_PREFIX/lib/perl5/site_perl/$perl_version', '$TERMUX_PREFIX/lib/perl5/$perl_version/${TERMUX_ARCH}-android', '$TERMUX_PREFIX/lib/perl5/$perl_version']
MESON_PERL_CROSS MESON_PERL_CROSS
} }
@ -73,10 +67,13 @@ jobs:
-e "s:@REVISION@:$GITHUB_RUN_NUMBER:" \ -e "s:@REVISION@:$GITHUB_RUN_NUMBER:" \
packages/irssi-an/build.sh packages/irssi-an/build.sh
git -C src.irssi.git tag v$version git -C src.irssi.git tag v$version
- name: prepare output folder
run: |
install -m a+rwx -d output
- name: build irssi package - name: build irssi package
run: | run: |
./scripts/run-docker.sh ./build-package.sh -I irssi-an sudo ./scripts/run-docker.sh ./build-package.sh -I irssi-an
- uses: actions/upload-artifact@v2 - uses: actions/upload-artifact@v4
with: with:
name: irssi-termux-pkg name: irssi-termux-pkg
path: output/irssi-an*.deb path: output/irssi-an*.deb

20
.github/workflows/trigger-pages.yml vendored Normal file
View file

@ -0,0 +1,20 @@
on:
push:
branches:
- master
jobs:
rebuild-pages:
if: github.repository == 'irssi/irssi'
runs-on: ubuntu-latest
steps:
- uses: actions/github-script@v6
with:
github-token: ${{ secrets.PAT_TOKEN }}
script: |
await github.rest.actions.createWorkflowDispatch({
owner: context.repo.owner,
repo: 'irssi.github.io',
workflow_id: 'pages.yml',
ref: 'main'
})

75
.github/workflows/voiddocker.yml vendored Normal file
View file

@ -0,0 +1,75 @@
on:
push:
branches:
- master
pull_request:
workflow_dispatch:
name: Check Irssi on Void Linux glibc
jobs:
dist:
runs-on: ubuntu-latest
container: ghcr.io/void-linux/void-glibc:latest
steps:
- name: prepare required software
run: |
xbps-install -Syu xbps || :
xbps-install -Syu
xbps-install -Sy git findutils python3-setuptools tar xz gzip
- uses: actions/checkout@main
- name: make dist
run: |
git config --global --add safe.directory /__w/irssi/irssi
./utils/make-dist.sh
- uses: actions/upload-artifact@v4
with:
path: irssi-*.tar.gz
retention-days: 1
install:
runs-on: ubuntu-latest
container: ghcr.io/void-linux/void-glibc:latest
needs: dist
steps:
- name: prepare required software
run: |
xbps-install -Syu xbps || :
xbps-install -Syu
xbps-install -Sy meson base-devel libglib-devel libutf8proc-devel ncurses-devel ncurses-base openssl-devel libotr-devel libgcrypt-devel tar findutils curl
- name: fetch dist
uses: actions/download-artifact@v4
- name: Setup local annotations
uses: irssi-import/actions-irssi/problem-matchers@master
- name: Test on Void Linux glibc
run: |
set -ex
curl -SLf https://github.com/irssi-import/actions-irssi/raw/master/check-irssi/render.pl -o ~/render.pl && chmod +x ~/render.pl
tar xzf artifact/irssi-*.tar.gz
# ninja install
cd irssi-*/
meson Build -Dwith-proxy=yes -Dwith-bot=yes -Dwith-perl=yes --prefix=$HOME/irssi-build --buildtype debugoptimized
ninja -C Build
ninja -C Build install
# ninja test
ninja -C Build test
find -name testlog.txt -exec sed -i -e '/Inherited environment:.* GITHUB/d' {} + -exec cat {} +
export TERM=xterm
# automated irssi launch test
cd
mkdir irssi-test
echo 'echo automated irssi launch test
^set settings_autosave off
^set -clear log_close_string
^set -clear log_day_changed
^set -clear log_open_string
^set log_timestamp *
^window log on
load irc
load dcc
load flood
load notifylist
load perl
load otr
load proxy
^quit' > irssi-test/startup
export LC_CTYPE=C.utf8
irssi-build/bin/irssi --home irssi-test | perl -Mutf8 -C ~/render.pl
cat irc.log.*

14
.muon_fmt.ini Normal file
View file

@ -0,0 +1,14 @@
# Irssi configuration for muon fmt
max_line_len = 108
indent_style = space
indent_size = 2
#indent_by = ' '
space_array = true
kwargs_force_multiline = true
wide_colon = true
no_single_comma_function = true
insert_final_newline = true
sort_files = false
group_arg_value = true
sticky_parens = true
continuation_indent = true

14
INSTALL
View file

@ -5,10 +5,14 @@
To compile Irssi you need: To compile Irssi you need:
- meson-0.53 build system with ninja-1.8 or greater - meson-0.53 build system with ninja-1.8 or greater
- pkg-config (or compatible)
- glib-2.32 or greater - glib-2.32 or greater
- openssl (for ssl support) - openssl (for ssl support)
- perl-5.6 or greater (for Perl support) - perl-5.8 or greater (for building, and optionally Perl scripts)
(n.b a complete perl is needed, including ExtUtils::Embed and xsubpp)
- terminfo or ncurses (for text frontend) - terminfo or ncurses (for text frontend)
- utf8proc (optional, for additional char width calculation)
- libgcrypt (for OTR)
For most people, this should work just fine: For most people, this should work just fine:
@ -108,3 +112,11 @@ would call:
Getting perl scripting to work needs a few things: Getting perl scripting to work needs a few things:
- TODO - TODO
Apple MacOS / Darwin
At the time of writing, meson has an open issue with correctly linking
libraries on macos.
See docs/meson-macos-ar.txt for a workaround.

91
NEWS
View file

@ -1,6 +1,69 @@
v1.5-head-an 2022-xx-xx The Irssi team <staff@irssi.org> v1.5-head 202x-xx-xx The Irssi team <staff@irssi.org>
v1.4.1 2022-06-12 The Irssi team <staff@irssi.org> v1.4.5 2023-10-03 The Irssi team <staff@irssi.org>
+ Add workaround for Perl 5.38.0 bug that breaks the Irssi
locale and glyph rendering (scripts.irssi.org#857, #1498)
- Fix Perl scripts broken by Perl 5.38 (scripts.irssi.org#851,
#1474). With input from Leon Timmermans
- Document workaround to fix linker errors when building with
meson on Apple (#1435, #1492)
- Fix meson using wrong filenames on Apple, leading to broken
Perl support (#1483, #1493)
- Fix /upgrade not accepting `~' (#1460, #1462). By Lukas Mai
- Improve compatibility with Perl5-IDEA (#1465, #1467). By
Charlie Daffern
- Fix logic in how own actions are printed for other protocols
(codeberg!5, #1471). By Andrej Kacian
- Fix crash on old PowerPC Mac (#1482, #1484)
- Fix wrong prototype of library function used in terminal
handling (#1495). By Emil Engler
- Minor cleanups (#1488, #1497). Includes work by Emil Engler
- Minor help and documentation fixes (#1458, #1494, #1477,
#1478). Includes work by KindOne
v1.4.4 2023-03-31 The Irssi team <staff@irssi.org>
* Expose location of signals.txt via pkg-config (codeberg!1,
#1439, #1446, #1447). By Andrej Kacian
+ Levels can now be inverted using `^' prefix in the /WINDOW
(HIDE)LEVEL commands (#1428)
+ Support receiving monospace (#1370, #1442). By Linus
Heckemann
- Fix config broken by /WINDOW LOGFILE without parameter
(#1392, #1432)
- Fix broken /LASTLOG -window switch (#1418, #1424, regression
introduced in #1398)
- Fix logic in how actions are printed for other protocols
(codeberg!3, #1454). By Andrej Kacian
- Fix stale special collector use after free (#1456). Reported
by ednash
- Help and message fixes (#1421, #1429, #1431, #1434, #1438,
#1452, #1453, #1455). Includes work by Jimmie Tyrrell and
Sven Grewe
v1.4.3 2022-10-31 The Irssi team <staff@irssi.org>
- Fix freeze on Alt+arrows (#1416, #1417)
- Fix crash on /upgrade (#1399, #1419)
- Fix saving of -disallow_starttls (#1401, #1420)
- Fix libnv detection on FreeBSD (freebsd#265397, #1407). By
Guido Falsi and Kristof Provost
- Minor help and script fixes (#1380, #1393, #1411, #1413,
#1414, #1415)
v1.4.2 2022-07-17 The Irssi team <staff@irssi.org>
* Add irssimoduledir to irssi-1.pc in the Meson build (#1383,
#1378)
- Use -isystem includes, limiting warnings to Irssi
code. Fixes compilation with Perl 5.36 (#1381,
gentoo#851522, #1384)
- Fix missing lines when changing dynamic textbuffer contents
(#1382, #1387). Reported by externalserver15
- Fix Perl cross compilation with Meson 0.60.0 (#1377)
- Fix default channel prefix used for /JOIN to default to `#'
(#1385, #1388)
- Fix crash in /LASTLOG by getting line texts before printing
(#1367, #1398)
v1.4.1 2022-06-12 The Irssi team <staff@irssi.org>
! Note: botti no longer compiles; get in touch if you use it ! Note: botti no longer compiles; get in touch if you use it
* Format the output of /QUOTE HELP (#1371, an#82). By Val * Format the output of /QUOTE HELP (#1371, an#82). By Val
Lorentz. Add /SHELP as default alias (an#83) Lorentz. Add /SHELP as default alias (an#83)
@ -91,7 +154,7 @@ v1.4.1 2022-06-12 The Irssi team <staff@irssi.org>
* Channel sync requests (WHO, MODE) are now sent "later" than * Channel sync requests (WHO, MODE) are now sent "later" than
user commands. This should improve responsiveness to user user commands. This should improve responsiveness to user
commands in the autojoin phase (an#26, an#32, an#33) commands in the autojoin phase (#1300, an#26, an#32, an#33)
* Irssi is now using full paths in #include directives and * Irssi is now using full paths in #include directives and
consequently does not add all directories to the include consequently does not add all directories to the include
path anymore (#1040) path anymore (#1040)
@ -308,7 +371,7 @@ v1.4.1 2022-06-12 The Irssi team <staff@irssi.org>
- Run abidiff on pull requests (#1179, #1195) - Run abidiff on pull requests (#1179, #1195)
- Test CI-Fuzz (#1279, #1304, an#17) - 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)
- Fix wrong call to free. By Zero King (#1076) - Fix wrong call to free. By Zero King (#1076)
- Fix a colour reset in true colour themes when encountering - Fix a colour reset in true colour themes when encountering
@ -346,13 +409,13 @@ v1.2.3 2021-04-11 The Irssi team <staff@irssi.org>
- Fix memory leak when receiving bogus SASL authentication - Fix memory leak when receiving bogus SASL authentication
data. Found and fixed by Sergey Valentey (#1293) data. Found and fixed by Sergey Valentey (#1293)
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, GL!35) 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)
v1.2.1 2019-06-29 The Irssi team <staff@irssi.org> v1.2.1 2019-06-29 The Irssi team <staff@irssi.org>
! Contains all changes from 1.1.3 ! Contains all changes from 1.1.3
- Fix a test on big endian machines (#1014) - Fix a test on big endian machines (#1014)
- Fix the compile time conditionality of wcwidth - Fix the compile time conditionality of wcwidth
@ -363,17 +426,17 @@ v1.2.1 2019-06-29 The Irssi team <staff@irssi.org>
encoding) in the input prompt was broken (#1018, encoding) in the input prompt was broken (#1018,
#1057). Initial patch by Артём Курашов #1057). Initial patch by Артём Курашов
v1.1.3 2019-06-29 The Irssi team <staff@irssi.org> v1.1.3 2019-06-29 The Irssi team <staff@irssi.org>
! Contains all changes from 1.0.8 ! Contains all changes from 1.0.8
- Fix regression of #779 where autolog_ignore_targets would - Fix regression of #779 where autolog_ignore_targets would
not matching itemless windows anymore (#1012, #1013) not matching itemless windows anymore (#1012, #1013)
v1.0.8 2019-06-29 The Irssi team <staff@irssi.org> v1.0.8 2019-06-29 The Irssi team <staff@irssi.org>
- Fix a use after free issue when sending the SASL login on - Fix a use after free issue when sending the SASL login on
(automatic and manual) reconnects (#1055, #1058). Reported (automatic and manual) reconnects (#1055, #1058). Reported
by ilbelkyr by ilbelkyr
v1.2.0 2019-02-11 The Irssi team <staff@irssi.org> v1.2.0 2019-02-11 The Irssi team <staff@irssi.org>
! Contains all changes from 1.1.2 ! Contains all changes from 1.1.2
* Improved the /STATUSBAR commands (#858) * Improved the /STATUSBAR commands (#858)
* /SET no longer shows `=' between setting and value (#886) * /SET no longer shows `=' between setting and value (#886)
@ -461,7 +524,7 @@ v1.2.0 2019-02-11 The Irssi team <staff@irssi.org>
- Misc fixes (#840, #839, #843, #953, #962). Tests (#806, - Misc fixes (#840, #839, #843, #953, #962). Tests (#806,
#875, #905, #964, #1011). Fuzzing (#929). #875, #905, #964, #1011). Fuzzing (#929).
v1.1.2 2019-01-09 The Irssi team <staff@irssi.org> v1.1.2 2019-01-09 The Irssi team <staff@irssi.org>
- Fix the resetting of window hiddenlevel (#861) - Fix the resetting of window hiddenlevel (#861)
- Fix clearing of hidelevel in layout (#951) - Fix clearing of hidelevel in layout (#951)
- Fix accessing unallocated text when checking entry position - Fix accessing unallocated text when checking entry position
@ -480,14 +543,14 @@ v1.1.2 2019-01-09 The Irssi team <staff@irssi.org>
- Fix Perl detection on MacOS. By Dominyk Tiller (#927) - Fix Perl detection on MacOS. By Dominyk Tiller (#927)
- Misc fixes. By Jaroslav Škarvada (#981, #982) - Misc fixes. By Jaroslav Škarvada (#981, #982)
v1.1.1 2018-02-15 The Irssi team <staff@irssi.org> v1.1.1 2018-02-15 The Irssi team <staff@irssi.org>
! Contains all changes from 1.0.7 ! Contains all changes from 1.0.7
- Restore compatibility with OpenSSL < 1.0.2 (#820, #831) - Restore compatibility with OpenSSL < 1.0.2 (#820, #831)
- Fix test compilation on some platforms (#815, #816) - Fix test compilation on some platforms (#815, #816)
- Fix portability and backwards compatibility of test runner - Fix portability and backwards compatibility of test runner
(#818, #845) (#818, #845)
v1.0.7 2018-02-15 The Irssi team <staff@irssi.org> v1.0.7 2018-02-15 The Irssi team <staff@irssi.org>
- Prevent use after free error during the execution of some - Prevent use after free error during the execution of some
commands. Found by Joseph Bisch (GL#17, GL!24). commands. Found by Joseph Bisch (GL#17, GL!24).
- Revert netsplit print optimisation due to crashes (#465, #809, - Revert netsplit print optimisation due to crashes (#465, #809,
@ -506,7 +569,7 @@ v1.0.7 2018-02-15 The Irssi team <staff@irssi.org>
resize (GL#25, GL#29, #836). resize (GL#25, GL#29, #836).
- Minor help correction. By William Jackson (#834). - Minor help correction. By William Jackson (#834).
v1.1.0 2018-01-15 The Irssi team <staff@irssi.org> v1.1.0 2018-01-15 The Irssi team <staff@irssi.org>
! Warning. Irssi is broken and will crash with OpenSSL < 1.0.2 ! Warning. Irssi is broken and will crash with OpenSSL < 1.0.2
due to openssl/openssl commit due to openssl/openssl commit
5b4b9ce976fce09a7a92e2f25b91a1635cb840fe 5b4b9ce976fce09a7a92e2f25b91a1635cb840fe
@ -588,7 +651,7 @@ v1.1.0 2018-01-15 The Irssi team <staff@irssi.org>
#738) #738)
- Fix space issue in glib-2.0.m4 (#621) - Fix space issue in glib-2.0.m4 (#621)
v1.0.6 2018-01-07 The Irssi team <staff@irssi.org> v1.0.6 2018-01-07 The Irssi team <staff@irssi.org>
! Note: Code and aliases using `$($'-like constructs are no ! Note: Code and aliases using `$($'-like constructs are no
longer supported due to issue GL#18. Sorry about the longer supported due to issue GL#18. Sorry about the
inconvenience. inconvenience.

View file

@ -1,10 +1,10 @@
# Neırssi # [Irssi](https://irssi.org)
![Build Status](https://github.com/ailin-nemui/irssi/workflows/Check%20Irssi/badge.svg?branch=master) ![Build Status](https://github.com/irssi/irssi/workflows/Check%20Irssi/badge.svg?branch=master)
Neırssi is a modular text mode chat client mostly compatible with Irssi is a modular text mode chat client. It comes with IRC support
[Irssi](https://irssi.org). It comes with IRC support built in, and built in, and there are third party
there are third party [ICB](https://github.com/jperkin/irssi-icb), [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
@ -13,14 +13,14 @@ available.
![irssi](https://user-images.githubusercontent.com/5665186/32180643-cf127f60-bd92-11e7-8aa2-882313ce1d8e.png) ![irssi](https://user-images.githubusercontent.com/5665186/32180643-cf127f60-bd92-11e7-8aa2-882313ce1d8e.png)
## [Download information](https://ailin-nemui.github.io/irssi/Getting.html) ## [Download information](https://irssi.org/download/)
#### Development source installation #### Development source installation
[Ninja](https://ninja-build.org/) 1.8 and [Meson](https://mesonbuild.com/) 0.53 [Ninja](https://ninja-build.org/) 1.8 and [Meson](https://mesonbuild.com/) 0.53
``` ```
git clone https://github.com/ailin-nemui/irssi git clone https://github.com/irssi/irssi
cd irssi cd irssi
meson Build meson Build
ninja -C Build && sudo ninja -C Build install ninja -C Build && sudo ninja -C Build install
@ -28,7 +28,7 @@ ninja -C Build && sudo ninja -C Build install
#### Release source installation #### Release source installation
* Download [release](https://github.com/ailin-nemui/irssi/releases) * Download [release](https://github.com/irssi/irssi/releases)
* Verify signature * Verify signature
``` ```
tar xJf irssi-*.tar.xz tar xJf irssi-*.tar.xz
@ -41,22 +41,22 @@ ninja -C Build && sudo ninja -C Build install
- [glib-2.32](https://wiki.gnome.org/Projects/GLib) or greater - [glib-2.32](https://wiki.gnome.org/Projects/GLib) or greater
- [openssl](https://www.openssl.org/) - [openssl](https://www.openssl.org/)
- [perl-5.6](https://www.perl.org/) or greater (for perl support) - [perl-5.8](https://www.perl.org/) or greater (for perl support)
- terminfo or ncurses (for text frontend) - terminfo or ncurses (for text frontend)
#### See the [INSTALL](INSTALL) file for details #### See the [INSTALL](INSTALL) file for details
## Documentation ## [Documentation](https://irssi.org/documentation/)
* [New users guide](https://ailin-nemui.github.io/irssi/New-users.html) * [New users guide](https://irssi.org/New-users/)
* [Questions and Answers](https://irssi.org/documentation/qna/)
* Check the built-in `/HELP`, it has all the details on command syntax * Check the built-in `/HELP`, it has all the details on command syntax
* Other random Irssi documentation on https://irssi.org/documentation/
## [Themes](https://irssi-import.github.io/themes/) ## [Themes](https://irssi-import.github.io/themes/)
## [Scripts](https://scripts.irssi.org/) ## [Scripts](https://scripts.irssi.org/)
## [Modules](https://ailin-nemui.github.io/irssi/Modules.html) ## [Modules](https://irssi.org/modules/)
## [Security information](https://irssi.org/security/) ## [Security information](https://irssi.org/security/)

110
docs/New-users.html Normal file
View file

@ -0,0 +1,110 @@
<base href='https://irssi.org/New-users/'>
<h1>New users guide</h1>
<section id="new-to-irc">
<h2>New to IRC</h2>
<p>Internet Relay Chat was created in 1988 and has hardly changed. It can be used to exchange text messages (one message = single line) with other people, either privately (called query, PM, private message, MSG) or in a room (channel). Pictures are shared by uploading them to a temporary host like <a class="reference external" href="https://pomf.lain.la/">https://pomf.lain.la/</a> and then pasting the HTTP links. Code snippets or longer texts are shared by pasting them to a Pastebin like <a class="reference external" href="https://paste.opensuse.org/">https://paste.opensuse.org/</a> and then sharing the HTTP link.</p>
<p>IRC does not have message history. You can only receive replies while your computer is turned on and connected to the channel you want to follow. Some people run their IRC programs on remote servers for that reason.</p>
<p>IRC is organised into networks. Each network consists of many servers. It (mostly) does not matter which server you connect to as long as it belongs to the network you want to use. Irssi supports connections to many networks at the same time.</p>
<p>Each network contains many channels, rooms that are often dedicated to discussing a specific topic. You can find many channels on <a class="reference external" href="https://netsplit.de/">https://netsplit.de/</a> or using a search engine with the keyword “IRC”. Irssi supports joining many channels at the same time.</p>
<p>There is a rather large IRC network catering to free and open-source software and peer directed projects at <a class="reference external" href="https://libera.chat/">https://libera.chat/</a> and a smaller one at <a class="reference external" href="https://www.oftc.net/">https://www.oftc.net/</a> many free software projects still have support channels on these IRC networks (although some have moved to Matrix or proprietary platforms like Discord).</p>
</section>
<section id="first-start">
<h2>First start</h2>
<p>After (compiling and) installing Irssi, to start it, open a shell (Terminal) and type:</p>
<div class="highlight-default notranslate"><div><pre>irssi
</pre></div>
</div>
<p>You should be greeted by a blinking cursor behind <code class="docutils literal notranslate">[(status)]</code>. You are now in the status window of Irssi. Window is the Irssi name for what you might nowadays call a “Web browser tab”.</p>
<p>If youre confused about what you are seeing on the Irssi screen, you can find an annotated screenshot of it at <a class="reference internal" href="../User-interface/">User interface</a>.</p>
<p>If you want, you can pick a nick name (handle) that will be shown to others reading your messages now, by typing</p>
<div class="highlight-default notranslate"><div><pre>/set nick whatyouwant
</pre></div>
</div>
<p>Each command or message can be sent by pressing Enter. Commands in Irssi start with a <code class="docutils literal notranslate">/</code>. If there is no <code class="docutils literal notranslate">/</code>, then the line that you wrote will be sent as a message to the channel that you have open, for everyone to see.</p>
<section id="leaving">
<h3>Leaving</h3>
<p>Type <code class="docutils literal notranslate">/quit</code> to get out of Irssi.</p>
</section>
</section>
<section id="connecting-to-a-network">
<h2>Connecting to a network</h2>
<p>Irssi comes with some predefined networks. You can see the current list of networks by typing</p>
<div class="highlight-default notranslate"><div><pre>/network
</pre></div>
</div>
<p>(the list will be shown in your status window)</p>
<p>To connect to one of the networks in the list, type <code class="docutils literal notranslate">/connect networkname</code>, for example:</p>
<div class="highlight-default notranslate"><div><pre>/connect liberachat
</pre></div>
</div>
<p>You should see several messages scroll by. After a while, you should be connected to the Libera Chat network.</p>
<div class="admonition attention">
<p class="admonition-title">Attention</p>
<p>Irssi version 1.2 or older may be lacking the liberachat network entry. See <a class="reference external" href="https://github.com/shabble/irssi-docs/wiki/liberachat">https://github.com/shabble/irssi-docs/wiki/liberachat</a> for how to add it.</p>
</div>
<section id="nickname-registration">
<h3>Nickname registration</h3>
<p>Many IRC networks (but not all) offer a way to register a user account. Sometimes (but not on all networks) the account registration also includes reserving a nick for you. <em>How</em> to register also differs by network. Some <em>channels</em> only allow users with registered accounts to join them, so it may be very important for you to register a user account.</p>
<p>User accounts are always specific to a network.</p>
<p>For the Libera Chat network, you can find instructions how to register and set up your account with Irssi on <a class="reference external" href="https://github.com/shabble/irssi-docs/wiki/liberachat#configure-sasl-automated-log-in">https://github.com/shabble/irssi-docs/wiki/liberachat#configure-sasl-automated-log-in</a></p>
</section>
</section>
<section id="joining-a-channel">
<h2>Joining a channel</h2>
<p>Once you are connected to a network, you can join channels by typing <code class="docutils literal notranslate">/join #channelname</code>, for example:</p>
<div class="highlight-default notranslate"><div><pre>/join #irssi
</pre></div>
</div>
<p>Now, a new window will open and you can send messages to the channel.</p>
<section id="changing-windows">
<h3>Changing windows</h3>
<p>You can change between windows using the <code class="docutils literal notranslate">Ctrl</code>+<code class="docutils literal notranslate">n</code> or <code class="docutils literal notranslate">Ctrl</code>+<code class="docutils literal notranslate">p</code> keys, orif your terminal is configured properlyusing <code class="docutils literal notranslate">Alt</code>+<code class="docutils literal notranslate">1</code>, <code class="docutils literal notranslate">Alt</code>+<code class="docutils literal notranslate">2</code>, … See <a class="reference internal" href="../documentation/help/bind_-list/">bind -list</a> for a list of all default key bindings.</p>
</section>
<section id="removing-clutter">
<h3>Removing clutter</h3>
<p>By default, Irssi shows when someone joins or leaves a channel. These messages can waste a lot of lines and obscure the actual chat. To hide them, type</p>
<div class="highlight-default notranslate"><div><pre>/window hidelevel +joins +parts +quits
</pre></div>
</div>
<p>To get them back</p>
<div class="highlight-default notranslate"><div><pre>/window hidelevel -joins -parts -quits
</pre></div>
</div>
<p>If you want to hide them by default, <code class="docutils literal notranslate">/set window_default_hidelevel hidden joins parts quits</code></p>
</section>
</section>
<section id="adding-a-new-network">
<h2>Adding a new network</h2>
<p>If you want to join a network that is not there, you first need to find at least one server of that network. Lets say you have found the room <a class="reference external" href="https://netsplit.de/channels/details.php?room=%23hackint&amp;net=hackint">#hackint</a> on netsplit.de and want to join it. Then you can find that the <a class="reference external" href="https://netsplit.de/servers/?net=hackint">server</a> is irc.hackint.org, port 6697, SSL (TLS) on. To add it to Irssi, use the commands:</p>
<div class="highlight-default notranslate"><div><pre>/network add hackint
/server add -tls -network hackint irc.hackint.org 6697
</pre></div>
</div>
<p>Then, you can connect to the newly added network with</p>
<div class="highlight-default notranslate"><div><pre>/connect hackint
</pre></div>
</div>
<section id="multiple-networks">
<h3>Multiple networks</h3>
<p>If you are connected to multiple networks, you can change which one you are “talking” to (which one to send commands) by using the <code class="docutils literal notranslate">Ctrl</code>+<code class="docutils literal notranslate">x</code> key in the status window.</p>
</section>
</section>
<section id="on-line-help">
<h2>On-line help</h2>
<p>Most /commands have a help page, you can read it with</p>
<div class="highlight-default notranslate"><div><pre>/help commandname
</pre></div>
</div>
<p>or <a class="reference internal" href="../documentation/help/">on-line</a>.</p>
<p>The settings that can be changed with /SET are described on <a class="reference internal" href="../documentation/settings/">Settings Documentation</a> the settingshelp <a class="reference internal" href="#about-scripts">script</a> can be used to read it from within <code class="docutils literal notranslate">/help</code></p>
</section>
<section id="about-scripts">
<h2>About Scripts</h2>
<p>You can enhance your Irssi by installing scripts. Many Perl scripts written by other Irssi users can be found on <a class="reference external" href="https://scripts.irssi.org/">https://scripts.irssi.org/</a></p>
<p>Most of them should be compatible with Irssi 1.4 (but some may not, also see the Full Change log for some incompatible ones)</p>
</section>
<section id="about-themes">
<h2>About Themes</h2>
<p>Irssis look can be thoroughly changed with themes. Many themes created by other Irssi users can be found on <a class="reference external" href="https://themes.irssi.org/">https://themes.irssi.org/</a></p>
<p>If you want to modify the look of Irssi yourself, the <em>default</em> theme which can be found in your <code class="docutils literal notranslate">~/.irssi</code> folder is a good starting point. It also has a few comments explaining what some of the abstracts are used for</p>
</section>

193
docs/New-users.txt Normal file
View file

@ -0,0 +1,193 @@
# New users guide #
## New to IRC ##
Internet Relay Chat was created in 1988 and has hardly changed. It can be used
to exchange text messages (one message = single line) with other people, either
privately (called query, PM, private message, MSG) or in a room (channel).
Pictures are shared by uploading them to a temporary host like [1]https://
pomf.lain.la/ and then pasting the HTTP links. Code snippets or longer texts
are shared by pasting them to a Pastebin like [2]https://paste.opensuse.org/
and then sharing the HTTP link.
IRC does not have message history. You can only receive replies while your
computer is turned on and connected to the channel you want to follow. Some
people run their IRC programs on remote servers for that reason.
IRC is organised into networks. Each network consists of many servers. It
(mostly) does not matter which server you connect to as long as it belongs to
the network you want to use. Irssi supports connections to many networks at the
same time.
Each network contains many channels, rooms that are often dedicated to
discussing a specific topic. You can find many channels on [3]https://
netsplit.de/ or using a search engine with the keyword “IRC”. Irssi supports
joining many channels at the same time.
There is a rather large IRC network catering to free and open-source software
and peer directed projects at [4]https://libera.chat/ and a smaller one at [5]
https://www.oftc.net/ many free software projects still have support channels
on these IRC networks (although some have moved to Matrix or proprietary
platforms like Discord).
## First start ##
After (compiling and) installing Irssi, to start it, open a shell (Terminal)
and type:
irssi
You should be greeted by a blinking cursor behind [(status)]. You are now in
the status window of Irssi. Window is the Irssi name for what you might
nowadays call a “Web browser tab”.
If youre confused about what you are seeing on the Irssi screen, you can find
an annotated screenshot of it at [6]User interface.
If you want, you can pick a nick name (handle) that will be shown to others
reading your messages now, by typing
/set nick whatyouwant
Each command or message can be sent by pressing Enter. Commands in Irssi start
with a /. If there is no /, then the line that you wrote will be sent as a
message to the channel that you have open, for everyone to see.
### Leaving ###
Type /quit to get out of Irssi.
## Connecting to a network ##
Irssi comes with some predefined networks. You can see the current list of
networks by typing
/network
(the list will be shown in your status window)
To connect to one of the networks in the list, type /connect networkname, for
example:
/connect liberachat
You should see several messages scroll by. After a while, you should be
connected to the Libera Chat network.
Attention
Irssi version 1.2 or older may be lacking the liberachat network entry. See [7]
https://github.com/shabble/irssi-docs/wiki/liberachat for how to add it.
### Nickname registration ###
Many IRC networks (but not all) offer a way to register a user account.
Sometimes (but not on all networks) the account registration also includes
reserving a nick for you. How to register also differs by network. Some
channels only allow users with registered accounts to join them, so it may be
very important for you to register a user account.
User accounts are always specific to a network.
For the Libera Chat network, you can find instructions how to register and set
up your account with Irssi on [8]https://github.com/shabble/irssi-docs/wiki/
liberachat#configure-sasl-automated-log-in
## Joining a channel ##
Once you are connected to a network, you can join channels by typing /join #
channelname, for example:
/join #irssi
Now, a new window will open and you can send messages to the channel.
### Changing windows ###
You can change between windows using the Ctrl+n or Ctrl+p keys, orif your
terminal is configured properlyusing Alt+1, Alt+2, … See [9]bind -list for a
list of all default key bindings.
### Removing clutter ###
By default, Irssi shows when someone joins or leaves a channel. These messages
can waste a lot of lines and obscure the actual chat. To hide them, type
/window hidelevel +joins +parts +quits
To get them back
/window hidelevel -joins -parts -quits
If you want to hide them by default, /set window_default_hidelevel hidden joins
parts quits
## Adding a new network ##
If you want to join a network that is not there, you first need to find at
least one server of that network. Lets say you have found the room [10]#
hackint on netsplit.de and want to join it. Then you can find that the [11]
server is irc.hackint.org, port 6697, SSL (TLS) on. To add it to Irssi, use the
commands:
/network add hackint
/server add -tls -network hackint irc.hackint.org 6697
Then, you can connect to the newly added network with
/connect hackint
### Multiple networks ###
If you are connected to multiple networks, you can change which one you are
“talking” to (which one to send commands) by using the Ctrl+x key in the status
window.
## On-line help ##
Most /commands have a help page, you can read it with
/help commandname
or [12]on-line.
The settings that can be changed with /SET are described on [13]Settings
Documentation the settingshelp [14]script can be used to read it from within
/help
## About Scripts ##
You can enhance your Irssi by installing scripts. Many Perl scripts written by
other Irssi users can be found on [15]https://scripts.irssi.org/
Most of them should be compatible with Irssi 1.4 (but some may not, also see
the Full Change log for some incompatible ones)
## About Themes ##
Irssis look can be thoroughly changed with themes. Many themes created by
other Irssi users can be found on [16]https://themes.irssi.org/
If you want to modify the look of Irssi yourself, the default theme which can
be found in your ~/.irssi folder is a good starting point. It also has a few
comments explaining what some of the abstracts are used for
References:
[1] https://pomf.lain.la/
[2] https://paste.opensuse.org/
[3] https://netsplit.de/
[4] https://libera.chat/
[5] https://www.oftc.net/
[6] https://irssi.org/User-interface/
[7] https://github.com/shabble/irssi-docs/wiki/liberachat
[8] https://github.com/shabble/irssi-docs/wiki/liberachat#configure-sasl-automated-log-in
[9] https://irssi.org/documentation/help/bind_-list/
[10] https://netsplit.de/channels/details.php?room=%23hackint&net=hackint
[11] https://netsplit.de/servers/?net=hackint
[12] https://irssi.org/documentation/help/
[13] https://irssi.org/documentation/settings/
[14] https://irssi.org/New-users/#about-scripts
[15] https://scripts.irssi.org/
[16] https://themes.irssi.org/

View file

@ -9,13 +9,13 @@ To make Irssi enter capability mode on startup, add
capsicum = "yes"; capsicum = "yes";
awaylog_file = "~/irclogs/away.log"; awaylog_file = "~/irclogs/away.log";
to your ~/.irssi/config and restart the client. Alternatively you can to your ~/.irssi/config in the settings/core section, and restart the
enter it "by hand", using the "/capsicum enter" command. From the security client. Alternatively you can enter it "by hand", using the
point of view it's strongly preferable to use the former method, to avoid "/capsicum enter" command. From the security point of view it's strongly
establishing connections without the sandbox protection; the "/capsicum" preferable to use the former method, to avoid establishing connections
command is only intended for experimentation, and in cases where you need without the sandbox protection; the "/capsicum" command is only intended
to do something that's not possible in capability mode - run scripts, for experimentation, and in cases where you need to do something that's not
for example - before continuing. possible in capability mode - run scripts, for example - before continuing.
There is no way to leave the capability mode, apart from exiting Irssi. There is no way to leave the capability mode, apart from exiting Irssi.
When running in capability mode, there are certain restrictions - Irssi When running in capability mode, there are certain restrictions - Irssi

View file

@ -17,13 +17,15 @@ Details:
Adds or removes a binding; the binding itself is case-sensitive and may Adds or removes a binding; the binding itself is case-sensitive and may
contain as many characters as you want. contain as many characters as you want.
Uppercase characters usually indicate that you need to keep the shift-key Key bindings are case sensitive so uppercase letters mean you also have
pressed to use the binding. to use the shift key, except for ctrl which does not support shift but
the keys must always be typed in uppercase.
%9Examples:%9 %9Examples:%9
/BIND /BIND
/BIND meta-c /CLEAR /BIND meta-c /CLEAR
/BIND meta-C /CYCLE
/BIND meta-q change_window 16 /BIND meta-q change_window 16
/BIND -delete meta-y /BIND -delete meta-y
/BIND ^W^C /WINDOW NEW HIDE /BIND ^W^C /WINDOW NEW HIDE

View file

@ -17,6 +17,7 @@
-tls_ciphers: TLS cipher suite preference lists. -tls_ciphers: TLS cipher suite preference lists.
-tls_pinned_cert: Pinned x509 certificate fingerprint. -tls_pinned_cert: Pinned x509 certificate fingerprint.
-tls_pinned_pubkey: Pinned public key fingerprint. -tls_pinned_pubkey: Pinned public key fingerprint.
-nocap: Disable CAPREQ during connect
-noproxy: Ignores the global proxy configuration. -noproxy: Ignores the global proxy configuration.
-network: The network this connection belongs to. -network: The network this connection belongs to.
-host: The hostname you would like to connect from. -host: The hostname you would like to connect from.

View file

@ -10,18 +10,22 @@
%9Description:%9 %9Description:%9
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 If the command contains a string with `$', `\' or `;' those characters
need to be escaped: need to be escaped:
'$' -> '$$'
'\' -> '\\' (or even '\\\\', depending on where they are used) `$' -> `$$'
';' -> '\;' `\' -> `\\' (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
to print `1;2$3\4':
/EVAL echo 1\;2$$3\\4
%9References:%9 %9References:%9

View file

@ -29,6 +29,8 @@
because it is allowed in addition to other ignores for the same target. because it is allowed in addition to other ignores for the same target.
The special level 'HIDDEN' can be used to hide matching messages that can The special level 'HIDDEN' can be used to hide matching messages that can
later be revealed using /WINDOW HIDELEVEL -HIDDEN later be revealed using /WINDOW HIDELEVEL -HIDDEN
The special level 'NOHILIGHT' can be used to suppress hilights without actually
ignoring the message.
%9Examples:%9 %9Examples:%9

View file

@ -36,6 +36,7 @@
HIDDEN Hides the message when window HIDELEVEL includes HIDDEN. HIDDEN Hides the message when window HIDELEVEL includes HIDDEN.
NO_ACT Doesn't trigger any activity in the statusbar. NO_ACT Doesn't trigger any activity in the statusbar.
NOHILIGHT The text is not highlighted. NOHILIGHT The text is not highlighted.
Suppresses hilights when used with /ignore.
When using levels from Irssi scripts, you need to prepend the level with When using levels from Irssi scripts, you need to prepend the level with
'MSGLEVEL_'; for example 'CRAP' becomes 'MSGLEVEL_CRAP'. 'MSGLEVEL_'; for example 'CRAP' becomes 'MSGLEVEL_CRAP'.

View file

@ -5,7 +5,7 @@
%9Parameters:%9 %9Parameters:%9
The server to search on and the remote sever to search on; if no arguments The server to search on and the remote server to search on; if no arguments
are given, the active server will be used. are given, the active server will be used.
%9Description:%9 %9Description:%9

View file

@ -36,8 +36,8 @@
-cmdmax: Specifies the maximum number of commands to perform before -cmdmax: Specifies the maximum number of commands to perform before
starting the internal flood protection. starting the internal flood protection.
-sasl_mechanism Specifies the mechanism to use for the SASL authentication. -sasl_mechanism Specifies the mechanism to use for the SASL authentication.
At the moment irssi only supports the 'plain' and the Irssi supports: PLAIN, EXTERNAL, SCRAM-SHA-1, SCRAM-SHA-256
'external' mechanisms. and SCRAM-SHA-512
Use '' to disable the authentication. Use '' to disable the authentication.
-sasl_username Specifies the username to use during the SASL authentication. -sasl_username Specifies the username to use during the SASL authentication.
-sasl_password Specifies the password to use during the SASL authentication. -sasl_password Specifies the password to use during the SASL authentication.

View file

@ -20,10 +20,10 @@
%9Description:%9 %9Description:%9
Manipulate the text in the window to go to a to the given line number, or Manipulate the text in the window to go to the given line number, or
clear the buffers. clear the buffers.
The timestamp format is format is '[dd[.mm] | -<days ago>] hh:mi[:ss]'. The timestamp format is '[dd[.mm] | -<days ago>] hh:mi[:ss]'.
%9Examples:%9 %9Examples:%9

View file

@ -16,11 +16,13 @@
-4: Connects using IPv4. -4: Connects using IPv4.
-6: Connects using IPv6. -6: Connects using IPv6.
-tls: Connects using TLS encryption. -tls: Connects using TLS encryption.
-notls: Connect without TLS encrption.
-tls_cert: The TLS client certificate file. -tls_cert: The TLS client certificate file.
-tls_pkey: The TLS client private key, if not included in the -tls_pkey: The TLS client private key, if not included in the
certificate file. certificate file.
-tls_pass: The password for the TLS client private key or certificate. -tls_pass: The password for the TLS client private key or certificate.
-tls_verify: Verifies the TLS certificate of the server. -tls_verify: Verifies the TLS certificate of the server.
-notls_verify: Doesn't verify the TLS certificate of the server.
-tls_cafile: The file with the list of CA certificates. -tls_cafile: The file with the list of CA certificates.
-tls_capath: The directory which contains the CA certificates. -tls_capath: The directory which contains the CA certificates.
-tls_ciphers: TLS cipher suite preference lists. -tls_ciphers: TLS cipher suite preference lists.
@ -28,6 +30,8 @@
-tls_pinned_pubkey: Pinned public key fingerprint. -tls_pinned_pubkey: Pinned public key fingerprint.
-auto: Automatically connects to the server on startup. -auto: Automatically connects to the server on startup.
-noauto: Doesn't connect to the server on startup. -noauto: Doesn't connect to the server on startup.
-cap: Enable CAPREQ for server.
-nocap: Disable CAPREQ for server.
-network: The network the server belongs to. -network: The network the server belongs to.
-host: The hostname you would like to connect from. -host: The hostname you would like to connect from.
-cmdspeed: Specifies the minimum amount of time, expressed in -cmdspeed: Specifies the minimum amount of time, expressed in

View file

@ -10,7 +10,7 @@
RESET: Restores the default statusbar configuration. RESET: Restores the default statusbar configuration.
ADDITEM: Adds an item to the specified statusbar. It can be set to ADDITEM: Adds an item to the specified statusbar. It can be set to
appear before/after another item and left/right aligned appear before/after another item and left/right aligned
to a specified position on the screen. on the screen.
MODIFYITEM: Changes an item position inside a bar. MODIFYITEM: Changes an item position inside a bar.
REMOVEITEM: Removes an item from the specified statusbar. REMOVEITEM: Removes an item from the specified statusbar.
INFO: List the current details and items of the specified INFO: List the current details and items of the specified
@ -18,15 +18,16 @@
-disable: Removes a statusbar from the list. -disable: Removes a statusbar from the list.
-type: Sets the type of statusbar, for each split window or only -type: Sets the type of statusbar, for each split window or only
for the current root screen. once at the root (very top or bottom) of the screen.
-placement: Sets the placement of the statusbar, either at the top or -placement: Sets the placement of the statusbar, either at the top or
the bottom of the screen. the bottom of the screen or split window.
-position: Sets the position of the statusbar. Represented as a -position: Sets the position of the statusbar. Represented as a
number, with 0 implying the first position. number, with smaller numbers implying a position further
-visible: Sets the visibility of the statusbar or item. If set to to the top.
always it is visible on all screens, otherwise if set to -visible: Sets the visibility of the statusbar. If set to always,
inactive or active then it is only visible on inactive it is visible on all split windows, otherwise if set to
or active screens, respectively. inactive or active then it is only visible on inactive or
active split windows, respectively.
-before: This item is added before the other item. -before: This item is added before the other item.
-after: This item is added after the other item. -after: This item is added after the other item.
-priority: When the statusbar items overflow, the item with the -priority: When the statusbar items overflow, the item with the
@ -35,8 +36,10 @@
quoted (e.g. -priority "-1") quoted (e.g. -priority "-1")
-alignment: Display the item on the right side. -alignment: Display the item on the right side.
Where statusbar refers to the name of the statusbar; if no argument is Where statusbar refers to the name of the statusbar; if no
given, the entire list of statusbars will be displayed. argument is given, or `LIST` is given, the entire list of
statusbars along with a quick overview of their properties will be
displayed.
%9Description:%9 %9Description:%9

View file

@ -15,7 +15,6 @@
%9Examples:%9 %9Examples:%9
/TOGGLE resolve_prefer_ipv6
/TOGGLE channels_rejoin_unavailable ON /TOGGLE channels_rejoin_unavailable ON
%9See also:%9 SET %9See also:%9 SET

View file

@ -42,6 +42,7 @@
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.
HIDELEVEL: %|Changes the levels of text lines that should be hidden from view, or query the current hidden level.
MOVE LEFT: %|Move the window to the numerically previous location inside the current sticky group. MOVE LEFT: %|Move the window to the numerically previous location inside the current sticky group.
MOVE RIGHT: %|Move the window to the numerically next location inside the current sticky group. MOVE RIGHT: %|Move the window to the numerically next location inside the current sticky group.
MOVE UP: %|Move the current window to the sticky group of the previous split window. If no sticky group remains, the split window collapses. MOVE UP: %|Move the current window to the sticky group of the previous split window. If no sticky group remains, the split window collapses.
@ -52,6 +53,8 @@
%|Add the required arguments for the given command. Without arguments, the details (size, immortality, levels, server, name and sticky group) of the currently active window are displayed. If used with a number as argument, same as WINDOW REFNUM. %|Add the required arguments for the given command. Without arguments, the details (size, immortality, levels, server, name and sticky group) of the currently active window are displayed. If used with a number as argument, same as WINDOW REFNUM.
%|LEVEL and HIDELEVEL modify the currently set level. Without arguments, the current level is displayed. Levels listed starting with `+' are added to the current levels. Levels listed starting with `-' are removed from the current levels. To clear the levels, start the new level setting with `NONE'. Levels listed starting with `^' are either removed or added from the current setting, depending on whether they were previously set or not (since Irssi 1.4.4). Levels listed as is are also added to the current levels. Afterwards, the new level setting is displayed.
%9Description:%9 %9Description:%9
Manipulates the window layout and positioning attributes. Manipulates the window layout and positioning attributes.
@ -68,7 +71,8 @@
/WINDOW LOG OFF /WINDOW LOG OFF
/WINDOW LOG ON ~/logs/debug.log /WINDOW LOG ON ~/logs/debug.log
/WINDOW LEVEL -ALL +NOTICES /WINDOW LEVEL -ALL +NOTICES
/WINDOW HIDELEVEL ^JOINS ^PARTS ^QUITS
/WINDOW LOGFILE ~/logs/notices.log /WINDOW LOGFILE ~/logs/notices.log
%9See also:%9 JOIN, LEVELS, LOG, QUERY %9See also:%9 JOIN, LEVELS, LOG, QUERY, SET window_default_level, SET window_default_hidelevel

View file

@ -116,6 +116,7 @@ install_data(
'whowas', 'whowas',
'window', 'window',
), ),
install_dir : helpdir) install_dir : helpdir,
)
# subdir('in') # subdir('in')

View file

@ -18,16 +18,16 @@
9. Text highlighting 9. Text highlighting
10. Ignoring 10. Ignoring
11. Logging 11. Logging
12. Commands
14. Last log (currently text version only)
15. Word completion
16. Recode
18. Key bindings (text version)
19. Perl scripting
( not written yet: ) ( not written yet: )
12. Commands
13. Themes 13. Themes
14. Last log (currently text version only)
15. Nick and word completion
16. Recode
17. Windowing system (text version) 17. Windowing system (text version)
18. Keyboard (text version)
19. Perl scripting
@ -141,44 +141,7 @@
--hostname -h Specify what host name to use --hostname -h Specify what host name to use
2. Message levels 2. Message levels <https://irssi.org/documentation/help/levels/>
Message levels (or in short, levels) are used almost everywhere.
They describe what kind of messages we're dealing with. Here's a
list of them all:
CRAP - Can be almost anything
MSGS - Private messages
PUBLIC - Public messages in channel
NOTICES - Notices
SNOTES - Server notices
CTCPS - CTCP messages
ACTIONS - Actions (/me) - usually ORed with PUBLIC or MSGS
JOINS - Someone joins a channel
PARTS - Someone parts a channel
QUITS - Someone quits IRC
KICKS - Someone gets kicked from channel
MODES - Channel mode is changed
TOPICS - Channel topic is changed
WALLOPS - Wallop is received
INVITES - Invite is received
NICKS - Someone changes nick
DCC - DCC related messages
DCCMSGS - DCC chat messages
CLIENTNOTICES - Irssi's notices
CLIENTERRORS - Irssi's error messages
CLIENTCRAP - Some other messages from Irssi
And a few special ones that could be included with the
levels above:
HILIGHT - Text is highlighted
NOHILIGHT - Don't check highlighting for this message
NO_ACT - Don't trigger channel activity when printing
this message
NEVER - Never ignore or log this message
3. Flood protection 3. Flood protection
@ -252,47 +215,12 @@
Currently only messages, notices and ctcps are checked for Currently only messages, notices and ctcps are checked for
flooding. flooding.
/SET flood_max_msgs = <count>, default is 4 /SET flood_max_msgs <count>, default is 4
/SET flood_timecheck = <seconds>, default is 5 seconds /SET flood_timecheck <seconds>, default is 5 seconds
If either of these is 0, the flood checking is disabled. If either of these is 0, the flood checking is disabled.
4. Configuration 4. Configuration <https://irssi.org/documentation/manual/configuration/>
4.1 Configuration files
The configuration is saved to ~/.irssi/config file. You can edit
it with text editor if you want, you can also add comments to it
and they stay there even if /SAVE is used. Comments are the lines
starting with # character. Any errors in config file are displayed
at startup.
Irssi uses it's own config library for handling the config file.
The format is pretty much the same as in libPropList and should be
easily understandable.
You can reload the config file on the fly with /RELOAD command, you
can also read a different config file with /RELOAD <filename>.
If you change any settings, they aren't saved to file until you use
/SAVE. You can save the config file to different place with
/SAVE <filename>.
4.2 Settings
You can view or change the settings with /SET command.
/SET without any arguments displays all the settings.
/SET <key> displays settings which key (partly) matches <key>
/SET <key> <value> sets <key> to <value>
Boolean settings accepts only values ON, OFF and TOGGLE. You can
also use /TOGGLE command to change them, so /TOGGLE <key> behaves
like /SET <key> TOGGLE. /TOGGLE also accepts arguments ON and OFF
when /TOGGLE behaves exactly like /SET.
Remember that changes are not saved until you use /SAVE!
5. Servers 5. Servers
@ -367,11 +295,11 @@
you setup the server using /SERVER ADD (see next section). If the you setup the server using /SERVER ADD (see next section). If the
settings can't be found there either, Irssi will use the defaults: settings can't be found there either, Irssi will use the defaults:
/SET default_nick = <nick>, defaults to user_name /SET default_nick <nick>, defaults to user_name
/SET alternate_nick = <nick>, defaults to <default_nick>_ /SET alternate_nick <nick>, defaults to <default_nick>_
/SET user_name = <user>, defaults to your login name /SET user_name <user>, defaults to your login name
/SET real_name = <name>, taken from /etc/passwd by default /SET real_name <name>, taken from /etc/passwd by default
/SET hostname = <host>, what host name to use when connecting /SET hostname <host>, what host name to use when connecting
/SET skip_motd ON|OFF|TOGGLE - Don't show server's MOTD /SET skip_motd ON|OFF|TOGGLE - Don't show server's MOTD
NOTE: /CONNECT is also a command for IRC operators to connect IRC NOTE: /CONNECT is also a command for IRC operators to connect IRC
@ -445,9 +373,6 @@
After connected to server, Irssi can automatically change your user After connected to server, Irssi can automatically change your user
mode. You can set it with /SET usermode <mode>, default is +i. mode. You can set it with /SET usermode <mode>, default is +i.
/SET resolve_prefer_ipv6 - If ON, prefer IPv6 for hosts that
have both v4 and v6 addresses.
5.5 Automatic reconnecting 5.5 Automatic reconnecting
If you get disconnected from server, Irssi will try to reconnect If you get disconnected from server, Irssi will try to reconnect
@ -792,13 +717,7 @@
/SET massjoin_max_joins <count>. /SET massjoin_max_joins <count>.
7. IRC commands and features (FIXME) 7. IRC commands and features <https://irssi.org/documentation/help/>
7.x Basic commands
7.x IRC operator commands
7.x Away features
8. Notify list 8. Notify list
@ -846,9 +765,9 @@
/HILIGHT without any arguments displays list of the hilights. /HILIGHT without any arguments displays list of the hilights.
If <color> is a If <color> is a number, Irssi will treat it as a MIRC color
number, Irssi will treat it as a MIRC color code. You can also use code. You can also use bolds (^B), underlines (^_) etc. as
bolds (^B), underlines (^_) etc. as <color> if you like. <color> if you like.
10. Ignoring 10. Ignoring
@ -993,29 +912,24 @@ If <color> is a
You can disable this feature by setting awaylog_level to NONE. You can disable this feature by setting awaylog_level to NONE.
12. Commands 12. Commands <https://irssi.org/documentation/manual/commands/>
Any char in the `cmdchars' setting can begin a command. The 13. Themes
syntax for a command is the following:
<CMDCHAR>[<CMDCHAR>][^]<DATA> 14. Last log <https://irssi.org/documentation/help/lastlog/>
If <CMDCHAR> is repeated two times, alias expansion is 15. Word completion <https://irssi.org/documentation/help/completion/>
disabled, enabled otherwise. If `^' is present, command output
is disabled. If <DATA> begins with a space, command lookup is
inhibited and the data is sent to the active window item
(useful to send a line that begins with <CMDCHAR>).
16. Recode 16. Recode
irssi supports selective encoding of incoming/outgoing messages Irssi supports selective encoding of incoming/outgoing messages
through the recode system. All incoming/outgoing messages can be through the recode system. All incoming/outgoing messages can be
optionally converted to/from the charset specified by the optionally converted to/from the charset specified by the
`term_charset' variable (which defaults to the locale encoding and `term_charset' variable (which defaults to the locale encoding and
should _not_ be changed in most cases), by setting the `recode' should _not_ be changed in most cases), by setting the `recode'
variable to 'ON'. variable to 'ON'.
Since there is no way in IRC to know the encoding associated to a Since there is no way in IRC to know the encoding associated to a
message, for incoming messages irssi uses the following algorithm: message, for incoming messages Irssi uses the following algorithm:
if `recode_autodetect_utf8' is 'ON' and the message is valid UTF-8 the if `recode_autodetect_utf8' is 'ON' and the message is valid UTF-8 the
encoding is assumed to be UTF-8. encoding is assumed to be UTF-8.
@ -1032,5 +946,9 @@ If <color> is a
iconv specific extension to peform transliteration (locale dependent) iconv specific extension to peform transliteration (locale dependent)
when a character is not representable in the destination encoding. when a character is not representable in the destination encoding.
18. Key bindings <https://irssi.org/documentation/help/bind_-list/>
19. Scripting <https://irssi.org/documentation/scripting/>
.. no, the docs end here, I got bored of writing these after a few days and .. no, the docs end here, I got bored of writing these after a few days and
haven't touched these since then. haven't touched these since then.

6
docs/meson-macos-ar.txt Normal file
View file

@ -0,0 +1,6 @@
;; manual workaround for meson bug https://github.com/mesonbuild/meson/issues/11165
;; fixes compilation with meson on apple macos
;; usage: meson --native-file ./docs/meson-macos-ar.txt ...
[binaries]
ar = ['/bin/sh', '-c', 'ar=${AR:-ar}; ranlib=${RANLIB:-ranlib -c -}; case "x$1" in xcsr*) $ar "$@" && $ranlib "$2" || exit $?; ;; *) exec $ar "$@"; ;; esac;', 'ar']

View file

@ -13,6 +13,7 @@ install_data(
'startup-HOWTO.html', 'startup-HOWTO.html',
'startup-HOWTO.txt', 'startup-HOWTO.txt',
), ),
install_dir : docdir) install_dir : docdir,
)
subdir('help') subdir('help')

View file

@ -522,6 +522,8 @@ Connect->{}
address - Address where we connected (irc.blah.org) address - Address where we connected (irc.blah.org)
port - Port where we connected port - Port where we connected
chatnet - Chat network chatnet - Chat network
chosen_family - IP family chosen to connect to
ipaddr - IP address connected to
password - Password we used in connection. password - Password we used in connection.
wanted_nick - Nick which we would prefer to use wanted_nick - Nick which we would prefer to use

52
docs/qna.html Normal file
View file

@ -0,0 +1,52 @@
<base href='https://irssi.org/documentation/qna/multi/'>
<h1>Right-aligned nicks</h1>
<p>To create a “tabular” effect of the chat view, or to align nick names in a column, you can use Irssis theme/format system. The basic commands are the following:</p>
<div class="highlight-default notranslate"><div><pre>/format own_msg {ownmsgnick $2 {ownnick $[-9]0}}$1
/format own_msg_channel {ownmsgnick $3 {ownnick $[-9]0}{msgchannel $1}}$2
/format pubmsg_me {pubmsgmenick $2 {menick $[-9]0}}$1
/format pubmsg_me_channel {pubmsgmenick $3 {menick $[-9]0}{msgchannel $1}}$2
/format pubmsg_hilight {pubmsghinick $0 $3 $[-9]1}$2
/format pubmsg_hilight_channel {pubmsghinick $0 $4 $[-9]1{msgchannel $2}}$3
/format pubmsg {pubmsgnick $2 {pubnick $[-9]0}}$1
/format pubmsg_channel {pubmsgnick $3 {pubnick $[-9]0}{msgchannel $1}}$2
</pre></div>
</div>
<p>These are copied from the default themes default values, which are responsible for displaying your own messages sent to a channel (<code class="docutils literal notranslate">own_msg</code>) as well as received messages (<code class="docutils literal notranslate">pubmsg</code>) and the two basic highlightings (<code class="docutils literal notranslate">me</code> and <code class="docutils literal notranslate">hilight</code>).</p>
<p>Then, in front of the argument that contains the nick name (<code class="docutils literal notranslate">$0</code> in most cases, but <code class="docutils literal notranslate">$1</code> in <code class="docutils literal notranslate">pubmsg_hilight</code>), an alignment modifier (see <a class="reference internal" href="../../settings/#a-b">Appendix B: Special Variables and Expandos</a>) has been added: <code class="docutils literal notranslate">[-9]</code>. This means that the nicks will be right-aligned and truncated to 9 characters.</p>
<p><strong>Note</strong>: Modifiers <em>only</em> work in the <code class="docutils literal notranslate">/format</code> section of a theme (this may change in the future)</p>
<p>There are also some scripts that try to do the alignment for you, like: <code class="docutils literal notranslate">nm</code>, <code class="docutils literal notranslate">nm2</code>.</p>
<p>There are also some nice themes that extend the alignment to further formats, like: <a class="reference external" href="https://github.com/ronilaukkarinen/weed">weed</a>.</p>
<h1>Automatic log-in to NickServ</h1>
<p>Please check here =&gt; <a class="reference internal" href="../../manual/automation/#automatic-log-in-to-nickserv">Automatic log-in to NickServ</a></p>
<h1>CertFP Log-in</h1>
<p>CertFP, short for Certificate Finger Print, is another method to log you in to NickServ. Instead of a password, it uses a <a class="reference external" href="https://en.wikipedia.org/wiki/Client_certificate">Client Certificate</a>.</p>
<p>In order to use it, you</p>
<ul class="simple">
<li><p>first need a certificate,</p></li>
<li><p>then configure Irssi to use this certificate,</p></li>
<li><p>and finally register the certificate with NickServ.</p></li>
</ul>
<p>Irssi does not have built-in certificate management commands, so you need to use an external tool like <code class="docutils literal notranslate">openssl</code> to create the certificate.</p>
<p>A step-by-step guide for the Libera Chat network can be found here =&gt; <a class="reference external" href="https://github.com/shabble/irssi-docs/wiki/liberachat_certfp">https://github.com/shabble/irssi-docs/wiki/liberachat_certfp</a></p>
<p>It is necessary that the certificate be available as a file; PKCS#11 is not supported.</p>
<h1>Tor (The Onion Router)</h1>
<p><a class="reference external" href="https://www.torproject.org/">Tor</a> is an overlay network for anonymous communication. It operates a local <a class="reference external" href="https://en.wikipedia.org/wiki/SOCKS">SOCKS</a> proxy for applications to use.</p>
<p>Unfortunately, Irssi currently does not support SOCKS proxies natively. As a workaround, you can install the <a class="reference external" href="https://github.com/rofl0r/proxychains-ng">ProxyChains-NG</a> program (note, it must be the NG version).</p>
<p>Afterwards, you can launch Irssi like this:</p>
<div class="highlight-default notranslate"><div><pre>proxychains4 irssi
</pre></div>
</div>
<p>Now your connections will go through the Proxy configured in ProxyChains-NG (Tor by default).</p>
<p>IRC networks may have different requirements to be able to connect via Tor. For the Libera Chat network, you will first need to set up <a class="reference internal" href="../certfp/">CertFP Log-in</a> using a clearnet connection, and then connect to their <a class="reference external" href="https://libera.chat/guides/connect#accessing-liberachat-via-tor">Onion Service</a> <code class="docutils literal notranslate">palladium.libera.chat</code>. More detailed instructions can be found here =&gt; <a class="reference external" href="https://github.com/shabble/irssi-docs/wiki/liberator">https://github.com/shabble/irssi-docs/wiki/liberator</a></p>
<h1>The following signatures were invalid: EXPKEYSIG</h1>
<p>If you see such a message</p>
<div class="highlight-default notranslate"><div><pre>Err:4 home:/ailin_nemui:/irssi-an InRelease
The following signatures were invalid: EXPKEYSIG EDB7AED941EEDB57 home:ailin_nemui OBS Project &lt;home:ailin_nemui@build.opensuse.org&gt;
</pre></div>
</div>
<p>this means that the automatic signing key used by the Open Build Service expired. OBS renews the key periodically, but Debian does not support this.</p>
<section id="fix">
<h2>Fix</h2>
<p>Download the key again, following the regular OBS instructions. If it still does not work, verify if there is a second expired copy of the key in <code class="docutils literal notranslate">/etc/apt/trusted.gpg.d</code> or in <code class="docutils literal notranslate">apt-key list</code> and remove it as well.</p>
</section>

111
docs/qna.txt Normal file
View file

@ -0,0 +1,111 @@
# Right-aligned nicks #
To create a “tabular” effect of the chat view, or to align nick names in a
column, you can use Irssis theme/format system. The basic commands are the
following:
/format own_msg {ownmsgnick $2 {ownnick $[-9]0}}$1
/format own_msg_channel {ownmsgnick $3 {ownnick $[-9]0}{msgchannel $1}}$2
/format pubmsg_me {pubmsgmenick $2 {menick $[-9]0}}$1
/format pubmsg_me_channel {pubmsgmenick $3 {menick $[-9]0}{msgchannel $1}}$2
/format pubmsg_hilight {pubmsghinick $0 $3 $[-9]1}$2
/format pubmsg_hilight_channel {pubmsghinick $0 $4 $[-9]1{msgchannel $2}}$3
/format pubmsg {pubmsgnick $2 {pubnick $[-9]0}}$1
/format pubmsg_channel {pubmsgnick $3 {pubnick $[-9]0}{msgchannel $1}}$2
These are copied from the default themes default values, which are responsible
for displaying your own messages sent to a channel (own_msg) as well as
received messages (pubmsg) and the two basic highlightings (me and hilight).
Then, in front of the argument that contains the nick name ($0 in most cases,
but $1 in pubmsg_hilight), an alignment modifier (see [1]Appendix B: Special
Variables and Expandos) has been added: [-9]. This means that the nicks will be
right-aligned and truncated to 9 characters.
Note: Modifiers only work in the /format section of a theme (this may change in
the future)
There are also some scripts that try to do the alignment for you, like: nm,
nm2.
There are also some nice themes that extend the alignment to further formats,
like: [2]weed.
# Automatic log-in to NickServ #
Please check here => [3]Automatic log-in to NickServ
# CertFP Log-in #
CertFP, short for Certificate Finger Print, is another method to log you in to
NickServ. Instead of a password, it uses a [4]Client Certificate.
In order to use it, you
• first need a certificate,
• then configure Irssi to use this certificate,
• and finally register the certificate with NickServ.
Irssi does not have built-in certificate management commands, so you need to
use an external tool like openssl to create the certificate.
A step-by-step guide for the Libera Chat network can be found here => [5]https:
//github.com/shabble/irssi-docs/wiki/liberachat_certfp
It is necessary that the certificate be available as a file; PKCS#11 is not
supported.
# Tor (The Onion Router) #
[6]Tor is an overlay network for anonymous communication. It operates a local
[7]SOCKS proxy for applications to use.
Unfortunately, Irssi currently does not support SOCKS proxies natively. As a
workaround, you can install the [8]ProxyChains-NG program (note, it must be the
NG version).
Afterwards, you can launch Irssi like this:
proxychains4 irssi
Now your connections will go through the Proxy configured in ProxyChains-NG
(Tor by default).
IRC networks may have different requirements to be able to connect via Tor. For
the Libera Chat network, you will first need to set up [9]CertFP Log-in using a
clearnet connection, and then connect to their [10]Onion Service
palladium.libera.chat. More detailed instructions can be found here => [11]
https://github.com/shabble/irssi-docs/wiki/liberator
# The following signatures were invalid: EXPKEYSIG #
If you see such a message
Err:4 home:/ailin_nemui:/irssi-an InRelease
The following signatures were invalid: EXPKEYSIG EDB7AED941EEDB57 home:ailin_nemui OBS Project <home:ailin_nemui@build.opensuse.org>
this means that the automatic signing key used by the Open Build Service
expired. OBS renews the key periodically, but Debian does not support this.
## Fix ##
Download the key again, following the regular OBS instructions. If it still
does not work, verify if there is a second expired copy of the key in /etc/apt/
trusted.gpg.d or in apt-key list and remove it as well.
References:
[1] https://irssi.org/documentation/settings/#a-b
[2] https://github.com/ronilaukkarinen/weed
[3] https://irssi.org/documentation/manual/automation/#automatic-log-in-to-nickserv
[4] https://en.wikipedia.org/wiki/Client_certificate
[5] https://github.com/shabble/irssi-docs/wiki/liberachat_certfp
[6] https://www.torproject.org/
[7] https://en.wikipedia.org/wiki/SOCKS
[8] https://github.com/rofl0r/proxychains-ng
[9] https://irssi.org/documentation/qna/certfp/
[10] https://libera.chat/guides/connect#accessing-liberachat-via-tor
[11] https://github.com/shabble/irssi-docs/wiki/liberator

View file

@ -1,89 +1,137 @@
project('irssi', 'c', project(
'irssi',
'c',
version : '1.5-head', version : '1.5-head',
meson_version : '>=0.53', meson_version : '>=0.53',
default_options : ['warning_level=1']) default_options : [ 'warning_level=1' ],
)
############################ ############################
############################ ############################
glib_internal_version = 'glib-2.58.3' # keep this in sync with subprojects/glib.wrap glib_internal_version = 'glib-2.74.7' # keep this in sync with subprojects/glib.wrap
glib_pcre2_internal_version = 'pcre2-10.40'
glib_libffi_internal_version = 'libffi'
cc = meson.get_compiler('c') cc = meson.get_compiler('c')
rootinc = include_directories('.') rootinc = include_directories('.')
dep = [] dep = [ ]
textui_dep = [] textui_dep = [ ]
need_dl_cross_link = false need_dl_cross_link = false
need_dl_cross_link_main = false
dl_cross_irssi_main = [ ]
# The Android environment requires that all modules are linked to each other. # The Android environment requires that all modules are linked to each other.
# See https://github.com/android/ndk/issues/201 # See https://github.com/android/ndk/issues/201
if host_machine.system() == 'android' if host_machine.system() == 'android'
need_dl_cross_link = true need_dl_cross_link = true
elif host_machine.system() == 'cygwin'
need_dl_cross_link = true
need_dl_cross_link_main = true
endif endif
includedir = get_option('includedir') includedir = get_option('includedir')
incdir = 'irssi' incdir = 'irssi'
moduledir = get_option('libdir') / incdir / 'modules' moduledir = get_option('libdir') / incdir / 'modules'
helpdir = get_option('datadir') / incdir / 'help' helpdir = get_option('datadir') / incdir / 'help'
themedir = get_option('datadir') / incdir / 'themes' themedir = get_option('datadir') / incdir / 'themes'
scriptdir = get_option('datadir') / incdir / 'scripts' scriptdir = get_option('datadir') / incdir / 'scripts'
docdir = get_option('docdir') != '' ? get_option('docdir') : (get_option('datadir') / 'doc' / incdir) docdir = get_option('docdir') != '' ? get_option('docdir') : (get_option('datadir') / 'doc' / incdir)
want_textui = get_option('without-textui') != 'yes' want_textui = get_option('without-textui') != 'yes'
want_bot = get_option('with-bot') == 'yes' want_bot = get_option('with-bot') == 'yes'
want_fuzzer = get_option('with-fuzzer') == 'yes' want_fuzzer = get_option('with-fuzzer') == 'yes'
fuzzer_lib = get_option('with-fuzzer-lib') fuzzer_lib = get_option('with-fuzzer-lib')
fuzzer_link_language = get_option('fuzzer-link-language') fuzzer_link_language = get_option('fuzzer-link-language')
want_proxy = get_option('with-proxy') == 'yes' want_proxy = get_option('with-proxy') == 'yes'
require_capsicum = get_option('with-capsicum') == 'yes' require_capsicum = get_option('with-capsicum') == 'yes'
want_capsicum = get_option('with-capsicum') != 'no' want_capsicum = get_option('with-capsicum') != 'no'
require_libutf8proc = get_option('disable-utf8proc') == 'no' require_libutf8proc = get_option('disable-utf8proc') == 'no'
want_libutf8proc = get_option('disable-utf8proc') != 'yes' want_libutf8proc = get_option('disable-utf8proc') != 'yes'
require_perl = get_option('with-perl') == 'yes' require_perl = get_option('with-perl') == 'yes'
want_perl = get_option('with-perl') != 'no' want_perl = get_option('with-perl') != 'no'
with_perl_lib = get_option('with-perl-lib') with_perl_lib = get_option('with-perl-lib')
require_otr = get_option('with-otr') == 'yes' require_otr = get_option('with-otr') == 'yes'
want_otr = get_option('with-otr') != 'no' want_otr = get_option('with-otr') != 'no'
want_glib_internal = get_option('install-glib') != 'no' want_glib_internal = get_option('install-glib') != 'no'
require_glib_internal = get_option('install-glib') == 'force' 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() package_version = get_option('PACKAGE_VERSION') != '' ? get_option('PACKAGE_VERSION') : meson.project_version()
fs = import('fs') fs = import('fs')
if fs.exists('config.status') or fs.exists('irssi-version.h') or fs.exists('default-config.h') or fs.exists('default-theme.h') or fs.exists('src/perl/irssi-core.pl.h') or fs.exists('src/perl/perl-signals-list.h') or fs.exists('irssi-config.h') if fs.exists('config.status') or fs.exists('irssi-version.h') or fs.exists('default-config.h') or fs.exists('default-theme.h') or fs.exists('src/perl/irssi-core.pl.h') or fs.exists('src/perl/perl-signals-list.h') or fs.exists('irssi-config.h')
error('this tree has been configured with autotools, cannot proceed') error('this tree has been configured with autotools, cannot proceed')
endif endif
chat_modules = ['irc'] UNSET = '=INVALID='
UNSET_ARR = [ UNSET ]
run_command('mkdir', meson.current_build_dir() / incdir, check : false) chat_modules = [ 'irc' ]
run_command('ln', '-s', meson.current_source_dir() / 'src', meson.current_build_dir() / incdir, check : false)
run_command('ln', '-s', meson.current_build_dir() / 'irssi-config.h', meson.current_build_dir() / incdir, check : false)
run_command('ln', '-s', meson.current_build_dir() / 'irssi-version.h', meson.current_build_dir() / incdir, check : false)
def_moduledir = '-D' + 'MODULEDIR' + '="' + (get_option('prefix') / moduledir) + '"' run_command(
'mkdir',
meson.current_build_dir() / incdir,
check : false,
)
run_command(
'ln',
'-s', meson.current_source_dir() / 'src',
meson.current_build_dir() / incdir,
check : false,
)
run_command(
'ln',
'-s', meson.current_build_dir() / 'irssi-config.h',
meson.current_build_dir() / incdir,
check : false,
)
run_command(
'ln',
'-s', meson.current_build_dir() / 'irssi-version.h',
meson.current_build_dir() / incdir,
check : false,
)
def_moduledir = '-D' + 'MODULEDIR' + '="' + (get_option('prefix') / moduledir) + '"'
def_sysconfdir = '-D' + 'SYSCONFDIR' + '="' + (get_option('prefix') / get_option('sysconfdir')) + '"' def_sysconfdir = '-D' + 'SYSCONFDIR' + '="' + (get_option('prefix') / get_option('sysconfdir')) + '"'
def_helpdir = '-D' + 'HELPDIR' + '="' + (get_option('prefix') / helpdir) + '"' def_helpdir = '-D' + 'HELPDIR' + '="' + (get_option('prefix') / helpdir) + '"'
def_themesdir = '-D' + 'THEMESDIR' + '="' + (get_option('prefix') / themedir) + '"' def_themesdir = '-D' + 'THEMESDIR' + '="' + (get_option('prefix') / themedir) + '"'
def_scriptdir = '-D' + 'SCRIPTDIR' + '="' + (get_option('prefix') / scriptdir) + '"' def_scriptdir = '-D' + 'SCRIPTDIR' + '="' + (get_option('prefix') / scriptdir) + '"'
def_suppress_printf_fallback = '-D' + 'SUPPRESS_PRINTF_FALLBACK' def_suppress_printf_fallback = '-D' + 'SUPPRESS_PRINTF_FALLBACK'
module_suffix = [ ]
perl_module_suffix = [ ]
# Meson uses the wrong module extensions on Mac.
# https://gitlab.gnome.org/GNOME/glib/issues/520
if [ 'darwin', 'ios' ].contains(host_machine.system())
module_suffix = 'so'
perl_module_suffix = 'bundle'
endif
############## ##############
# Help files # # Help files #
############## ##############
build_perl = find_program('perl', native : true) build_perl = find_program(
'perl',
native : true,
)
if meson.is_cross_build() if meson.is_cross_build()
cross_perl = find_program('perl') cross_perl = find_program('perl')
else else
cross_perl = build_perl cross_perl = build_perl
endif endif
run_command(build_perl, files('utils/syntax.pl'), check : true) run_command(
build_perl,
files('utils/syntax.pl'),
check : true,
)
################### ###################
# irssi-version.h # # irssi-version.h #
@ -91,12 +139,12 @@ run_command(build_perl, files('utils/syntax.pl'), check : true)
env = find_program('env') env = find_program('env')
irssi_version_sh = find_program('utils/irssi-version.sh') irssi_version_sh = find_program('utils/irssi-version.sh')
irssi_version_h = custom_target('irssi-version.h', irssi_version_h = custom_target(
'irssi-version.h',
build_by_default : true, build_by_default : true,
build_always_stale : true, build_always_stale : true,
capture : true, capture : true,
command : [env, 'VERSION=' + meson.project_version(), command : [ env, 'VERSION=' + meson.project_version(), irssi_version_sh, meson.current_source_dir() ],
irssi_version_sh, meson.current_source_dir()],
output : 'irssi-version.h', output : 'irssi-version.h',
install : true, install : true,
install_dir : includedir / incdir, install_dir : includedir / incdir,
@ -107,22 +155,24 @@ irssi_version_h = custom_target('irssi-version.h',
#################### ####################
file2header = find_program('utils/file2header.sh') file2header = find_program('utils/file2header.sh')
default_config_h = custom_target('default-config.h', default_config_h = custom_target(
'default-config.h',
input : files('irssi.conf'), input : files('irssi.conf'),
output : 'default-config.h', output : 'default-config.h',
capture : true, capture : true,
command : [file2header, '@INPUT@', 'default_config'], command : [ file2header, '@INPUT@', 'default_config' ],
) )
################### ###################
# default-theme.h # # default-theme.h #
################### ###################
default_theme_h = custom_target('default-theme.h', default_theme_h = custom_target(
'default-theme.h',
input : files('themes/default.theme'), input : files('themes/default.theme'),
output : 'default-theme.h', output : 'default-theme.h',
capture : true, capture : true,
command : [file2header, '@INPUT@', 'default_theme'], command : [ file2header, '@INPUT@', 'default_theme' ],
) )
################ ################
@ -131,12 +181,18 @@ default_theme_h = custom_target('default-theme.h',
#### inet_addr #### #### inet_addr ####
inet_addr_found = false inet_addr_found = false
foreach inet_addr_provider : ['', 'nsl'] foreach inet_addr_provider : [ '', 'nsl' ]
prov_lib = [] prov_lib = [ ]
if inet_addr_provider != '' if inet_addr_provider != ''
prov_lib += cc.find_library(inet_addr_provider, required : false) prov_lib += cc.find_library(
inet_addr_provider,
required : false,
)
endif endif
if (prov_lib.length() == 0 or prov_lib[0].found()) and cc.has_function('inet_addr', dependencies : prov_lib) if (prov_lib.length() == 0 or prov_lib[0].found()) and cc.has_function(
'inet_addr',
dependencies : prov_lib,
)
dep += prov_lib dep += prov_lib
inet_addr_found = true inet_addr_found = true
break break
@ -148,12 +204,18 @@ endif
#### socket #### #### socket ####
socket_found = false socket_found = false
foreach socket_provider : ['', 'socket', 'network'] foreach socket_provider : [ '', 'socket', 'network' ]
prov_lib = [] prov_lib = [ ]
if socket_provider != '' if socket_provider != ''
prov_lib += cc.find_library(socket_provider, required : false) prov_lib += cc.find_library(
socket_provider,
required : false,
)
endif endif
if (prov_lib.length() == 0 or prov_lib[0].found()) and cc.has_function('socket', dependencies : prov_lib) if (prov_lib.length() == 0 or prov_lib[0].found()) and cc.has_function(
'socket',
dependencies : prov_lib,
)
dep += prov_lib dep += prov_lib
socket_found = true socket_found = true
break break
@ -163,7 +225,7 @@ if not socket_found
error('socket not found') error('socket not found')
endif endif
built_src = [] built_src = [ ]
glib_internal = false glib_internal = false
message('*** If you don\'t have GLib, you can run meson ... -Dinstall-glib=yes') message('*** If you don\'t have GLib, you can run meson ... -Dinstall-glib=yes')
message('*** to download and build it automatically') message('*** to download and build it automatically')
@ -171,59 +233,82 @@ message('*** Or alternatively install your distribution\'s package')
message('*** On Debian: sudo apt-get install libglib2.0-dev') message('*** On Debian: sudo apt-get install libglib2.0-dev')
message('*** On Redhat: dnf install glib2-devel') message('*** On Redhat: dnf install glib2-devel')
if not require_glib_internal if not require_glib_internal
glib_dep = dependency('glib-2.0', version : '>=2.32', required : not want_glib_internal, static : want_static_dependency) glib_dep = dependency(
'glib-2.0',
version : '>=2.32',
required : not want_glib_internal,
static : want_static_dependency,
include_type : 'system',
)
else else
glib_dep = dependency('', required : false) glib_dep = dependency(
'',
required : false,
)
endif endif
if not glib_dep.found() if not glib_dep.found()
glib_internal = true glib_internal = true
meson_cmd = find_program('meson') meson_cmd = find_program('meson')
ninja = find_program('ninja') ninja = find_program('ninja')
glib_internal_download_t = custom_target('glib-internal-download', glib_internal_download_t = custom_target(
'glib-internal-download',
command : [ meson_cmd, 'subprojects', 'download', 'glib', '--sourcedir', meson.current_source_dir() ], command : [ meson_cmd, 'subprojects', 'download', 'glib', '--sourcedir', meson.current_source_dir() ],
console : true, console : true,
output : ['glib-internal-download'], output : [ 'glib-internal-download' ],
) )
glib_internal_dependencies = [ glib_internal_dependencies = [
dependency('threads'), dependency('threads'),
] ]
glib_internal_configure_args = [] glib_internal_configure_args = [ ]
glib_internal_usr_local = false glib_internal_usr_local = false
if not cc.has_function('iconv_open') if not cc.has_function('iconv_open')
prov_lib = cc.find_library('iconv', required : false) prov_lib = cc.find_library(
'iconv',
required : false,
)
if not prov_lib.found() if not prov_lib.found()
prov_lib = cc.find_library('iconv', dirs : '/usr/local/lib') prov_lib = cc.find_library(
'iconv',
dirs : '/usr/local/lib',
)
glib_internal_usr_local = true glib_internal_usr_local = true
endif endif
if cc.has_function('libiconv_open', dependencies : prov_lib)
glib_internal_configure_args += '-Diconv=gnu'
else
glib_internal_configure_args += '-Diconv=native'
endif
glib_internal_dependencies += prov_lib glib_internal_dependencies += prov_lib
endif endif
if not cc.has_function('ngettext') if not cc.has_function('ngettext')
prov_lib = cc.find_library('intl', required : false) prov_lib = cc.find_library(
'intl',
required : false,
)
if not prov_lib.found() if not prov_lib.found()
prov_lib = cc.find_library('intl', dirs : '/usr/local/lib') prov_lib = cc.find_library(
'intl',
dirs : '/usr/local/lib',
)
glib_internal_usr_local = true glib_internal_usr_local = true
endif endif
glib_internal_dependencies += prov_lib glib_internal_dependencies += prov_lib
endif endif
if glib_internal_usr_local if glib_internal_usr_local
glib_internal_configure_args += ['-Dc_args=-I/usr/local/include', '-Dc_link_args=-L/usr/local/lib'] glib_internal_configure_args += [ '-Dc_args=-I/usr/local/include', '-Dc_link_args=-L/usr/local/lib' ]
endif endif
if not cc.has_function('getxattr') or not cc.has_header('sys/xattr.h') if not cc.has_function('getxattr') or not cc.has_header('sys/xattr.h')
if cc.has_header_symbol('attr/xattr.h', 'getxattr') if cc.has_header_symbol('attr/xattr.h', 'getxattr')
prov_lib = cc.find_library('xattr', required : false) prov_lib = cc.find_library(
'xattr',
required : false,
)
else else
prov_lib = dependency('', required : false) prov_lib = dependency(
'',
required : false,
)
endif endif
if prov_lib.found() if prov_lib.found()
glib_internal_dependencies += prov_lib glib_internal_dependencies += prov_lib
@ -232,57 +317,127 @@ if not glib_dep.found()
endif endif
endif endif
glib_internal_configure_t = custom_target('glib-internal-configure', glib_internal_configure_t = custom_target(
command : [ meson_cmd, 'setup', '--prefix=/irssi-glib-internal', 'glib-internal-configure',
command : [
meson_cmd,
'setup',
'--prefix=/irssi-glib-internal',
'--buildtype=' + get_option('buildtype'), '--buildtype=' + get_option('buildtype'),
'-Dlibmount=false', '-Dselinux=false', '-Ddefault_library=static', '-Dinternal_pcre=true', '-Dlibmount=disabled',
'-Dselinux=disabled',
'-Ddefault_library=static',
'-Dforce_fallback_for=pcre2,libffi',
glib_internal_configure_args, glib_internal_configure_args,
(meson.current_build_dir() / 'build-subprojects' / 'glib'), (meson.current_build_dir() / 'build-subprojects' / 'glib'),
(meson.current_source_dir() / 'subprojects' / glib_internal_version) ], (meson.current_source_dir() / 'subprojects' / glib_internal_version),
],
console : true, console : true,
output : ['glib-internal-configure'], output : [ 'glib-internal-configure' ],
depends : glib_internal_download_t,) depends : glib_internal_download_t,
glib_internal_build_t = custom_target('glib-internal-build', )
command : [ ninja, '-C', meson.current_build_dir() / 'build-subprojects' / 'glib', glib_internal_build_t = custom_target(
'glib-internal-build',
command : [
ninja,
'-C', meson.current_build_dir() / 'build-subprojects' / 'glib',
'subprojects' / glib_libffi_internal_version / 'src' / 'libffi.a',
'subprojects' / glib_pcre2_internal_version / 'libpcre2-8.a',
'glib' / 'libglib-2.0.a', 'glib' / 'libglib-2.0.a',
'gmodule' / 'libgmodule-2.0.a'], 'gmodule' / 'libgmodule-2.0.a',
'gobject' / 'libgobject-2.0.a',
'gio' / 'libgio-2.0.a',
],
console : true, console : true,
output : ['glib-internal-build'], output : [ 'glib-internal-build' ],
depends : glib_internal_configure_t,) depends : glib_internal_configure_t,
)
glib_dep = declare_dependency( glib_dep = declare_dependency(
dependencies : glib_internal_dependencies, dependencies : glib_internal_dependencies,
sources : glib_internal_build_t, sources : glib_internal_build_t,
compile_args : [ compile_args : [
'-I' + (meson.current_source_dir() / 'subprojects' / glib_internal_version / 'glib'), '-isystem' + (meson.current_source_dir() / 'subprojects' / glib_internal_version / 'glib'),
'-I' + (meson.current_source_dir() / 'subprojects' / glib_internal_version), '-isystem' + (meson.current_source_dir() / 'subprojects' / glib_internal_version),
'-I' + (meson.current_build_dir() / 'build-subprojects' / 'glib' / 'glib'), '-isystem' + (meson.current_build_dir() / 'build-subprojects' / 'glib' / 'glib'),
],
link_args : [
meson.current_build_dir() / 'build-subprojects' / 'glib' / 'subprojects' / glib_pcre2_internal_version / 'libpcre2-8.a',
meson.current_build_dir() / 'build-subprojects' / 'glib' / 'glib' / 'libglib-2.0.a',
], ],
link_args : [ meson.current_build_dir() / 'build-subprojects' / 'glib' / 'glib' / 'libglib-2.0.a' ],
) )
built_src += glib_internal_build_t built_src += glib_internal_build_t
libdl_dep = [] libdl_dep = [ ]
prov_lib = cc.find_library('dl', required : false) prov_lib = cc.find_library(
if prov_lib.found() and cc.has_function('dlopen', dependencies : prov_lib) 'dl',
required : false,
)
if prov_lib.found() and cc.has_function(
'dlopen',
dependencies : prov_lib,
)
libdl_dep += prov_lib libdl_dep += prov_lib
endif endif
gmodule_dep = declare_dependency(sources : glib_internal_build_t, gmodule_dep = declare_dependency(
sources : glib_internal_build_t,
dependencies : libdl_dep, dependencies : libdl_dep,
compile_args : [ compile_args : [
'-I' + (meson.current_source_dir() / 'subprojects' / glib_internal_version / 'gmodule'), '-isystem' + (meson.current_source_dir() / 'subprojects' / glib_internal_version / 'gmodule'),
], ],
link_args : [ meson.current_build_dir() / 'build-subprojects' / 'glib' / 'gmodule' / 'libgmodule-2.0.a' ], link_args : [ meson.current_build_dir() / 'build-subprojects' / 'glib' / 'gmodule' / 'libgmodule-2.0.a' ],
) )
gobject_dep = declare_dependency(
sources : glib_internal_build_t,
compile_args : [
'-isystem' + (meson.current_build_dir() / 'build-subprojects' / 'glib'),
],
link_args : [
meson.current_build_dir() / 'build-subprojects' / 'glib' / 'subprojects' / glib_libffi_internal_version / 'src' / 'libffi.a',
meson.current_build_dir() / 'build-subprojects' / 'glib' / 'gobject' / 'libgobject-2.0.a',
],
)
gio_dep = declare_dependency(
sources : glib_internal_build_t,
dependencies : cc.find_library('z'),
compile_args : [
'-isystem' + (meson.current_source_dir() / 'subprojects' / glib_internal_version / 'gio'),
'-isystem' + (meson.current_build_dir() / 'build-subprojects' / 'glib'),
],
link_args : [ meson.current_build_dir() / 'build-subprojects' / 'glib' / 'gio' / 'libgio-2.0.a' ],
)
else else
gmodule_dep = dependency('gmodule-2.0', static : want_static_dependency) gmodule_dep = dependency(
'gmodule-2.0',
static : want_static_dependency,
include_type : 'system',
)
gobject_dep = dependency(
'gobject-2.0',
static : want_static_dependency,
include_type : 'system',
)
gio_dep = dependency(
'gio-2.0',
static : want_static_dependency,
include_type : 'system',
)
endif endif
dep += glib_dep dep += glib_dep
dep += gmodule_dep dep += gmodule_dep
dep += gobject_dep
dep += gio_dep
if glib_internal and want_static_dependency and want_fuzzer if glib_internal and want_static_dependency and want_fuzzer
openssl_proj = subproject('openssl', default_options : ['default_library=static', 'asm=disabled']) openssl_proj = subproject(
'openssl',
default_options : [ 'default_library=static', 'asm=disabled' ],
)
openssl_dep = openssl_proj.get_variable('openssl_dep') openssl_dep = openssl_proj.get_variable('openssl_dep')
else else
openssl_dep = dependency('openssl', static : want_static_dependency) openssl_dep = dependency(
'openssl',
static : want_static_dependency,
include_type : 'system',
)
endif endif
dep += openssl_dep dep += openssl_dep
@ -291,10 +446,16 @@ dep += openssl_dep
############ ############
have_libutf8proc = false have_libutf8proc = false
libutf8proc = [] libutf8proc = [ ]
if want_libutf8proc if want_libutf8proc
libutf8proc = cc.find_library('utf8proc', required : require_libutf8proc) libutf8proc = cc.find_library(
have_libutf8proc = cc.has_function('utf8proc_version', dependencies : libutf8proc) 'utf8proc',
required : require_libutf8proc,
)
have_libutf8proc = cc.has_function(
'utf8proc_version',
dependencies : libutf8proc,
)
if have_libutf8proc if have_libutf8proc
dep += libutf8proc dep += libutf8proc
endif endif
@ -309,9 +470,15 @@ endif
if want_textui if want_textui
setupterm_found = false setupterm_found = false
foreach setupterm_provider : ['tinfo', 'ncursesw', 'ncurses', 'terminfo'] foreach setupterm_provider : [ 'tinfo', 'ncursesw', 'ncurses', 'terminfo' ]
prov_lib = cc.find_library(setupterm_provider, required : false) prov_lib = cc.find_library(
if prov_lib.found() and cc.has_function('setupterm', dependencies : prov_lib) setupterm_provider,
required : false,
)
if prov_lib.found() and cc.has_function(
'setupterm',
dependencies : prov_lib,
)
textui_dep += prov_lib textui_dep += prov_lib
setupterm_found = true setupterm_found = true
break break
@ -328,19 +495,27 @@ endif
have_perl = false have_perl = false
if want_perl if want_perl
perl_cflags = [] perl_cflags = [ ]
perl_ldflags = [] perl_ldflags = [ ]
perl_rpath_flags = [] perl_rpath_flags = [ ]
perl_rpath = '' perl_rpath = ''
#### ccopts #### #### ccopts ####
perl_ccopts = meson.get_cross_property('perl_ccopts', false) perl_ccopts = meson.get_cross_property('perl_ccopts', UNSET_ARR)
if perl_ccopts == false if perl_ccopts == UNSET_ARR
res = run_command(cross_perl, '-MExtUtils::Embed', '-e', 'ccopts', check : true) res = run_command(
cross_perl,
'-MExtUtils::Embed',
'-e', 'ccopts',
check : true,
)
perl_ccopts = res.stdout().strip().split() perl_ccopts = res.stdout().strip().split()
endif endif
foreach fl : perl_ccopts foreach fl : perl_ccopts
if fl.startswith('-D') or fl.startswith('-U') or fl.startswith('-I') or fl.startswith('-i') or fl.startswith('-f') or fl.startswith('-m') if fl.startswith('-D') or fl.startswith('-U') or fl.startswith('-I') or fl.startswith('-i') or fl.startswith('-f') or fl.startswith('-m')
if fl.startswith('-I')
fl = '-isystem' + fl.split('-I')[1]
endif
perl_cflags += fl perl_cflags += fl
endif endif
endforeach endforeach
@ -348,12 +523,17 @@ if want_perl
perl_cflags += cc.get_supported_arguments('-fPIC') perl_cflags += cc.get_supported_arguments('-fPIC')
#### ldopts #### #### ldopts ####
perl_ldopts = meson.get_cross_property('perl_ldopts', false) perl_ldopts = meson.get_cross_property('perl_ldopts', UNSET_ARR)
if perl_ldopts == false if perl_ldopts == UNSET_ARR
res = run_command(cross_perl, '-MExtUtils::Embed', '-e', 'ldopts', check : true) res = run_command(
cross_perl,
'-MExtUtils::Embed',
'-e', 'ldopts',
check : true,
)
perl_ldopts = res.stdout().strip().split() perl_ldopts = res.stdout().strip().split()
endif endif
skip_libs = ['-ldb', '-ldbm', '-lndbm', '-lgdbm', '-lc', '-lposix', '-rdynamic'] skip_libs = [ '-ldb', '-ldbm', '-lndbm', '-lgdbm', '-lc', '-lposix', '-rdynamic' ]
foreach fl : perl_ldopts foreach fl : perl_ldopts
if not fl.startswith('-A') and not skip_libs.contains(fl) if not fl.startswith('-A') and not skip_libs.contains(fl)
if fl.startswith('-Wl,-rpath,') if fl.startswith('-Wl,-rpath,')
@ -365,15 +545,28 @@ if want_perl
endif endif
endforeach endforeach
perl_version = meson.get_cross_property('perl_version', false) perl_version = meson.get_cross_property('perl_version', UNSET)
if perl_version == false if perl_version == UNSET
perl_version = run_command(cross_perl, '-V::version:', check : true).stdout().split('\'')[1] perl_version = run_command(
cross_perl,
'-V::version:',
check : true,
).stdout().split('\'')[1]
endif endif
perl_dep = declare_dependency(compile_args : perl_cflags, link_args : perl_ldflags,
version : perl_version) # disable clang warning
if perl_version.version_compare('<5.35.2')
perl_cflags += cc.get_supported_arguments('-Wno-compound-token-split-by-macro')
endif
perl_dep = declare_dependency(
compile_args : perl_cflags,
link_args : perl_ldflags,
version : perl_version,
)
#### ####
if not cc.links(''' if not cc.links(
'''
#include <EXTERN.h> #include <EXTERN.h>
#include <perl.h> #include <perl.h>
int main() int main()
@ -381,19 +574,27 @@ int main()
perl_alloc(); perl_alloc();
return 0; return 0;
} }
''', args : perl_cflags + perl_ldflags + perl_rpath_flags, ''',
name : 'working Perl support') args : perl_cflags + perl_ldflags + perl_rpath_flags,
name : 'working Perl support',
)
if require_perl if require_perl
error('error linking with perl libraries') error('error linking with perl libraries')
else else
warning('error linking with perl libraries') warning('error linking with perl libraries')
endif endif
else else
xsubpp_file_c = meson.get_cross_property('perl_xsubpp', false) xsubpp_file_c = meson.get_cross_property('perl_xsubpp', UNSET)
if xsubpp_file_c == false if xsubpp_file_c == UNSET
xsubpp_file_c = run_command(build_perl, '-MExtUtils::ParseXS', '-Eprint $INC{"ExtUtils/ParseXS.pm"} =~ s{ParseXS\\.pm$}{xsubpp}r', check : true).stdout() xsubpp_file_c = run_command(
build_perl,
'-MExtUtils::ParseXS',
'-e($r = $INC{"ExtUtils/ParseXS.pm"}) =~ s{ParseXS\\.pm$}{xsubpp}; print $r',
check : true,
).stdout()
endif endif
xsubpp = generator(build_perl, xsubpp = generator(
build_perl,
output : '@BASENAME@.c', output : '@BASENAME@.c',
capture : true, capture : true,
arguments : [ xsubpp_file_c, '@EXTRA_ARGS@', '@INPUT@' ], arguments : [ xsubpp_file_c, '@EXTRA_ARGS@', '@INPUT@' ],
@ -401,31 +602,44 @@ int main()
xsubpp_file = files(xsubpp_file_c) xsubpp_file = files(xsubpp_file_c)
if with_perl_lib == 'module' if with_perl_lib == 'module'
perl_install_base = run_command(build_perl, '-MText::ParseWords=shellwords', '-e', 'grep { s/^INSTALL_BASE=// && print && exit } shellwords $ENV{PERL_MM_OPT}', check : true).stdout() perl_install_base = run_command(
build_perl,
'-MText::ParseWords=shellwords',
'-e', 'grep { s/^INSTALL_BASE=// && print && exit } shellwords $ENV{PERL_MM_OPT}',
check : true,
).stdout()
if perl_install_base == '' if perl_install_base == ''
with_perl_lib = '' with_perl_lib = ''
endif endif
endif endif
if with_perl_lib == '' if with_perl_lib == ''
if get_option('prefix') in ['/usr/local', 'C:/'] if get_option('prefix') in [ '/usr/local', 'C:/' ]
with_perl_lib = 'site' with_perl_lib = 'site'
elif get_option('prefix') in ['/usr'] elif get_option('prefix') in [ '/usr' ]
with_perl_lib = 'vendor' with_perl_lib = 'vendor'
endif endif
endif endif
perlmoddir = '' perlmoddir = ''
if with_perl_lib in ['site', 'vendor', 'module'] if with_perl_lib in [ 'site', 'vendor', 'module' ]
set_perl_use_lib = false set_perl_use_lib = false
perl_library_dir = with_perl_lib + ' default' perl_library_dir = with_perl_lib + ' default'
if with_perl_lib in ['site', 'vendor'] if with_perl_lib in [ 'site', 'vendor' ]
perlmoddir = meson.get_cross_property('perl_install' + with_perl_lib + 'arch', false) perlmoddir = meson.get_cross_property('perl_install' + with_perl_lib + 'arch', UNSET)
if perlmoddir == false if perlmoddir == UNSET
perlmoddir = run_command(cross_perl, '-V::install' + with_perl_lib + 'arch:', check : true).stdout().split('\'')[1] perlmoddir = run_command(
cross_perl,
'-V::install' + with_perl_lib + 'arch:',
check : true,
).stdout().split('\'')[1]
endif endif
elif with_perl_lib == 'module' elif with_perl_lib == 'module'
perl_archname = meson.get_cross_property('perl_archname', false) perl_archname = meson.get_cross_property('perl_archname', UNSET)
if perl_archname == false if perl_archname == UNSET
perl_archname = run_command(cross_perl, '-V::archname:', check : true).stdout().split('\'')[1] perl_archname = run_command(
cross_perl,
'-V::archname:',
check : true,
).stdout().split('\'')[1]
endif endif
perlmoddir = perl_install_base / 'lib' / 'perl5' / perl_archname perlmoddir = perl_install_base / 'lib' / 'perl5' / perl_archname
endif endif
@ -444,9 +658,14 @@ int main()
perl_use_lib = get_option('prefix') / perlmoddir perl_use_lib = get_option('prefix') / perlmoddir
if set_perl_use_lib if set_perl_use_lib
perl_inc = meson.get_cross_property('perl_inc', false) perl_inc = meson.get_cross_property('perl_inc', UNSET_ARR)
if perl_inc == false if perl_inc == UNSET_ARR
set_perl_use_lib = run_command(cross_perl, '-e', 'exit ! grep $_ eq $ARGV[0], grep /^\\//, @INC', perl_use_lib, check : false).returncode() != 0 set_perl_use_lib = run_command(
cross_perl,
'-e', 'exit ! grep $_ eq $ARGV[0], grep /^\\//, @INC',
perl_use_lib,
check : false,
).returncode() != 0
else else
set_perl_use_lib = not perl_inc.contains(perl_use_lib) set_perl_use_lib = not perl_inc.contains(perl_use_lib)
endif endif
@ -472,8 +691,20 @@ endif
have_otr = false have_otr = false
if want_otr if want_otr
libgcrypt = dependency('libgcrypt', version : '>=1.2.0', required : require_otr, static : want_static_dependency) libgcrypt = dependency(
libotr = dependency('libotr', version : '>=4.1.0', required : require_otr, static : want_static_dependency) 'libgcrypt',
version : '>=1.2.0',
required : require_otr,
static : want_static_dependency,
include_type : 'system',
)
libotr = dependency(
'libotr',
version : '>=4.1.0',
required : require_otr,
static : want_static_dependency,
include_type : 'system',
)
if libgcrypt.found() and libotr.found() if libgcrypt.found() and libotr.found()
dep += libgcrypt dep += libgcrypt
dep += libotr dep += libotr
@ -487,9 +718,19 @@ endif
have_capsicum = false have_capsicum = false
if want_capsicum if want_capsicum
if cc.has_function('cap_enter', dependencies : cc.find_library('c')) if cc.has_function(
libnv = cc.find_library('nv', required : require_capsicum) 'cap_enter',
nvlist_create_found = libnv.found() and cc.has_function('nvlist_create', dependencies : libnv) dependencies : cc.find_library('c'),
)
libnv = cc.find_library(
'nv',
required : require_capsicum,
)
nvlist_create_found = libnv.found() and cc.has_function(
'nvlist_create',
dependencies : libnv,
prefix : '#include <sys/nv.h>',
)
if nvlist_create_found if nvlist_create_found
dep += libnv dep += libnv
have_capsicum = true have_capsicum = true
@ -506,11 +747,14 @@ if want_capsicum
endif endif
# dependency helper sets # dependency helper sets
dep_cflagsonly = [] dep_cflagsonly = [ ]
foreach d : dep foreach d : dep
dep_cflagsonly += d.partial_dependency(includes : true, compile_args : true) dep_cflagsonly += d.partial_dependency(
includes : true,
compile_args : true,
)
endforeach endforeach
dl_cross_dep = [] dl_cross_dep = [ ]
if need_dl_cross_link if need_dl_cross_link
dl_cross_dep = dep dl_cross_dep = dep
endif endif
@ -521,11 +765,19 @@ endif
conf = configuration_data() conf = configuration_data()
conf.set('HAVE_CAPSICUM', have_capsicum, description : 'Build with Capsicum support') conf.set(
'HAVE_CAPSICUM',
have_capsicum,
description : 'Build with Capsicum support',
)
conf.set('HAVE_GMODULE', true) conf.set('HAVE_GMODULE', true)
conf.set('TERM_TRUECOLOR', true) conf.set('TERM_TRUECOLOR', true)
conf.set('USE_GREGEX', true) conf.set('USE_GREGEX', true)
conf.set10('_DARWIN_USE_64_BIT_INODE', true, description : 'Enable large inode numbers on Mac OS X 10.5.') conf.set10(
'_DARWIN_USE_64_BIT_INODE',
true,
description : 'Enable large inode numbers on Mac OS X 10.5.',
)
conf.set_quoted('FHS_PREFIX', get_option('fhs-prefix')) conf.set_quoted('FHS_PREFIX', get_option('fhs-prefix'))
headers = [ headers = [
@ -539,29 +791,110 @@ headers = [
] ]
foreach h : headers foreach h : headers
if cc.has_header(h) if cc.has_header(h)
conf.set('HAVE_' + h.underscorify().to_upper(), 1, description : 'Define to 1 if you have the <' + h + '> header file.') conf.set(
'HAVE_' + h.underscorify().to_upper(),
1,
description : 'Define to 1 if you have the <' + h + '> header file.',
)
endif endif
endforeach endforeach
if want_textui and conf.get('HAVE_TERM_H', 0) == 1
if cc.links(
'''
#include <stdio.h>
#include <term.h>
int main (void) {
return tputs("x", 1, putchar);
}
''',
args : '-pedantic-errors',
dependencies : textui_dep,
name : 'Curses working',
)
# ok
else
has_curses_h = cc.has_header('curses.h')
if has_curses_h and cc.links(
'''
#include <curses.h>
#include <term.h>
int main (void) {
return tputs("x", 1, putchar);
}
''',
args : '-pedantic-errors',
dependencies : textui_dep,
name : 'Curses working with curses.h',
)
conf.set(
'NEED_CURSES_H',
1,
description : 'tputs needs curses.h',
)
else
if has_curses_h and cc.links(
'''
#include <curses.h>
#include <term.h>
int char_putchar (char c) {
return putchar(c);
}
int main (void) {
return tputs("x", 1, char_putchar);
}
''',
args : '-pedantic-errors',
dependencies : textui_dep,
name : 'Curses with tputs third argument arg char',
)
conf.set(
'NEED_CURSES_H',
1,
description : 'tputs needs curses.h',
)
conf.set(
'TPUTS_SVR4',
1,
description : 'third argument of tputs has the type int (*)(char)',
)
else
error('could not link terminfo')
endif
endif
endif
endif
conf.set('HAVE_LIBUTF8PROC', have_libutf8proc) conf.set('HAVE_LIBUTF8PROC', have_libutf8proc)
conf.set_quoted('PACKAGE_VERSION', package_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',
configuration : conf, configuration : conf,
install_dir : includedir / incdir) install_dir : includedir / incdir,
)
########## ##########
# CFLAGS # # CFLAGS #
########## ##########
#### warnings #### #### warnings ####
add_project_arguments(cc.get_supported_arguments('-Werror=declaration-after-statement'), language : 'c') add_project_arguments(
cc.get_supported_arguments('-Werror=declaration-after-statement'),
language : 'c',
)
#### personality #### #### personality ####
add_project_arguments(cc.get_supported_arguments('-fno-strict-aliasing'), language : 'c') add_project_arguments(
cc.get_supported_arguments('-fno-strict-aliasing'),
language : 'c',
)
if get_option('buildtype').contains('debug') if get_option('buildtype').contains('debug')
add_project_arguments(cc.get_supported_arguments('-fno-omit-frame-pointer'), language : 'c') add_project_arguments(
cc.get_supported_arguments('-fno-omit-frame-pointer'),
language : 'c',
)
endif endif
if want_fuzzer if want_fuzzer
@ -569,7 +902,10 @@ if want_fuzzer
if not cc.has_argument('-fsanitize=fuzzer-no-link') if not cc.has_argument('-fsanitize=fuzzer-no-link')
error('compiler does not support -fsanitize=fuzzer-no-link, try clang?') error('compiler does not support -fsanitize=fuzzer-no-link, try clang?')
endif endif
add_project_arguments('-fsanitize=fuzzer-no-link', language : 'c') add_project_arguments(
'-fsanitize=fuzzer-no-link',
language : 'c',
)
endif endif
if fuzzer_link_language != 'c' if fuzzer_link_language != 'c'
add_languages(fuzzer_link_language) add_languages(fuzzer_link_language)
@ -581,15 +917,29 @@ endif
############## ##############
pc = import('pkgconfig') pc = import('pkgconfig')
pc_requires = [] 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', signalsfile = docdir / 'signals.txt'
if signalsfile.startswith('/')
signalsfile = signalsfile.split(get_option('prefix'))
if signalsfile[0] == ''
signalsfile = '${prefix}' + signalsfile[1]
else
signalsfile = signalsfile[0]
endif
else
signalsfile = '${prefix}' / signalsfile
endif
pc.generate(
filebase : 'irssi-1',
name : 'Irssi', name : 'Irssi',
description : 'Irssi chat client', description : 'Irssi chat client',
version : package_version, version : package_version,
requires : pc_requires) requires : pc_requires,
variables : [ 'irssimoduledir=${libdir}' / incdir / 'modules', 'signalsfile=' + signalsfile ],
)
########### ###########
# irssi.1 # # irssi.1 #

View file

@ -5,7 +5,7 @@ use Irssi;
use strict; use strict;
use vars qw($VERSION %IRSSI); use vars qw($VERSION %IRSSI);
$VERSION = "1.10"; $VERSION = "1.11";
%IRSSI = ( %IRSSI = (
authors => 'Timo Sirainen & Jostein Kjønigsen', authors => 'Timo Sirainen & Jostein Kjønigsen',
name => 'autoop', name => 'autoop',
@ -98,10 +98,11 @@ sub load_autoops {
%opnicks = (); %opnicks = ();
open(CONF, "<", "$file") or return; open(CONF, "<", "$file") or return;
while (my $line = <CONF>) { while (my $line = <CONF>) {
if ($line !=~ /^\s*$/) { chomp($line);
cmd_autoop($line); if ($line !~ /^\s*$/) {
$count++; cmd_autoop($line);
} $count++;
}
} }
close(CONF); close(CONF);

View file

@ -1,6 +1,6 @@
use strict; use strict;
use vars qw($VERSION %IRSSI); use vars qw($VERSION %IRSSI);
$VERSION = "2.92"; $VERSION = "2.93";
%IRSSI = ( %IRSSI = (
authors => "Timo Sirainen, Matti Hiljanen, Joost Vunderink, Bart Matthaei", authors => "Timo Sirainen, Matti Hiljanen, Joost Vunderink, Bart Matthaei",
contact => "tss\@iki.fi, matti\@hiljanen.com, joost\@carnique.nl, bart\@dreamflow.nl", contact => "tss\@iki.fi, matti\@hiljanen.com, joost\@carnique.nl, bart\@dreamflow.nl",
@ -63,8 +63,8 @@ sub cmd_print_help {
"/MAILBOX SHOW\n". "/MAILBOX SHOW\n".
" - Shows a list of the defined mailboxes.\n\n". " - Shows a list of the defined mailboxes.\n\n".
"Use the following commands to change the behaviour:\n\n". "Use the following commands to change the behaviour:\n\n".
"/SET MAILDIRMODE on|off\n". "/SET MAILDIR_MODE on|off\n".
" - If maildirmode is on, the mailboxes in the list are assumed to be ". " - If maildir_mode is on, the mailboxes in the list are assumed to be ".
"directories. Otherwise they are assumed to be spool files.\n". "directories. Otherwise they are assumed to be spool files.\n".
" Default: off.\n". " Default: off.\n".
"/SET MAIL_OLDNOTNEW on|off\n". "/SET MAIL_OLDNOTNEW on|off\n".

View file

@ -11,4 +11,5 @@ install_data(
'scriptassist.pl', 'scriptassist.pl',
'usercount.pl', 'usercount.pl',
), ),
install_dir : scriptdir) install_dir : scriptdir,
)

View file

@ -5,7 +5,7 @@
use strict; use strict;
our $VERSION = '2020042700'; our $VERSION = '2023111700';
our %IRSSI = ( our %IRSSI = (
authors => 'Stefan \'tommie\' Tomanek', authors => 'Stefan \'tommie\' Tomanek',
contact => 'stefan@pico.ruhr.de', contact => 'stefan@pico.ruhr.de',
@ -22,6 +22,8 @@ our ($forked, %remote_db, $have_gpg, @complist);
use Irssi 20020324; use Irssi 20020324;
use CPAN::Meta::YAML; use CPAN::Meta::YAML;
use LWP::UserAgent; use LWP::UserAgent;
use Hash::Util qw(lock_ref_keys);
use JSON::PP;
use POSIX; use POSIX;
use version; use version;
@ -30,7 +32,7 @@ $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); my $irssi_version = qv('v'.Irssi::parse_special('$J') =~ s/[^.\d].*//r);
sub show_help { sub show_help {
my $help = "scriptassist $VERSION my $help = "scriptassist $VERSION
@ -43,7 +45,7 @@ sub show_help {
/scriptassist info <scripts> /scriptassist info <scripts>
Display information about <scripts> Display information about <scripts>
/scriptassist ratings <scripts|all> /scriptassist ratings <scripts|all>
Retrieve the average ratings of the the scripts Retrieve the average ratings of 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>
@ -199,87 +201,163 @@ sub get_unknown {
} }
sub get_names { sub get_names {
my ($sname, $db) = shift; my ($sname, $db, $votes) = @_;
$sname =~ s/\s+$//; $sname =~ s/\s+$//;
$sname =~ s/\.pl$//; my $ext = 'pl'; # default extension
my $plname = "$sname.pl"; if ($sname =~ s/\.(\w{2,3})$//) {
$ext = $1;
}
my $plname = "$sname.$ext";
$sname =~ s/^.*\///; $sname =~ s/^.*\///;
my $xname = $sname; my $xname = $sname;
$xname =~ s/\W/_/g; $xname =~ s/\W/_/g;
my $pname = "${xname}::"; my $pname = "${xname}::";
if ($xname ne $sname || $sname =~ /_/) { if ($xname ne $sname || $sname =~ /_/) {
my $dir = Irssi::get_irssi_dir()."/scripts/"; my $dir = Irssi::get_irssi_dir()."/scripts/";
if ($db && exists $db->{"$sname.pl"}) { if ($db && exists $db->{$plname}) {
# $found = 1; # $found = 1;
} elsif (-e $dir.$plname || -e $dir."$sname.pl" || -e $dir."autorun/$sname.pl") { } elsif (-e $dir.$plname || -e $dir."autorun/".$plname) {
# $found = 1; # $found = 1;
} else { } else {
# not found # not found
my $pat = $xname; $pat =~ y/_/?/; my $pat = $xname; $pat =~ y/_/?/;
my $re = "\Q$xname"; $re =~ s/\Q_/./g; my $re = "\Q$xname"; $re =~ s/\Q_/./g;
if ($db) { if ($db) {
my ($cand) = grep /^$re\.pl$/, sort keys %$db; my ($cand) = grep /^$re\.\Q$ext\E$/, sort keys %$db;
if ($cand) { if ($cand) {
return get_names($cand, $db); return get_names($cand, $db, $votes);
} }
} }
my ($cand) = glob "'$dir$pat.pl' '${dir}autorun/$pat.pl'"; my ($cand) = glob "'$dir$pat.$ext' '${dir}autorun/$pat.$ext'";
if ($cand) { if ($cand) {
$cand =~ s/^.*\///; $cand =~ s/^.*\///;
return get_names($cand, $db); return get_names($cand, $db, $votes);
} }
} }
} }
($sname, $plname, $pname, $xname) my ($script_stash, $script_irssi, $script_db, $local_version);
$script_db = $db->{$plname} if $db && exists $db->{$plname};
if (lc $ext eq 'pl') {
$script_stash = $Irssi::Script::{$pname};
}
elsif (lc $ext eq 'py' && is_python_loaded()) {
my $filename;
capture_print_text_command(
'py list',
sub {
for my $line (@_[ 1 .. $#_ ]) {
my ($script, $fn) = split ' ', $line, 2;
if ($script eq $sname) {
$filename = $fn;
}
}
});
if (defined $filename) {
my $filename_quoted = $filename;
$filename_quoted =~ s/[\\']/\\$&/g;
capture_print_text_command(
# make sure the command line stays short
'py exec ' .
(join ';', split /\n/, <<PYTHON
import ast as A, types as _, json
i = 'IRSSI'
v = '__version__'
T = isinstance
f = '$filename_quoted'
a = lambda _: T(_, A.Assign)
n = lambda _: T(_, A.Name)
y = lambda _: _.id
t = lambda _: list(map(y, filter(n, _.targets)))
C = lambda e: lambda _: a(_) and t(_) == [e]
O = _.SimpleNamespace(value=A.Constant(None))
P = A.parse(open(f).read(), filename=f)
f = lambda e: A.literal_eval(next(filter(C(e), P.body), O).value)
print(json.dumps({ i: f(i), v: f(v) }))
PYTHON
),
sub {
eval {
my $doc = decode_json("@_");
$script_stash = { IRSSI => $doc->{IRSSI}, VERSION => \($doc->{__version__}) };
};
}
);
}
}
if (defined $script_stash) {
$script_irssi = $script_stash->{IRSSI};
$local_version = ${$script_stash->{VERSION}}
if $script_stash->{VERSION};
}
lock_ref_keys({
sname => $ext eq 'pl' ? $sname : $plname,
plname => $plname,
pname => $pname,
xname => $xname,
stash => $script_stash,
irssi => $script_irssi,
db => $script_db,
db_version => ($script_db ? $script_db->{version} : undef),
local_version => $local_version,
($votes ? (votes => $votes->{$plname}) : ()),
})
} }
sub script_info { sub script_info {
my ($scripts) = @_; my ($scripts) = @_;
my %result; my %result;
my $xml = get_scripts(); my $xml = get_scripts();
my $py = is_python_loaded();
foreach (@{$scripts}) { foreach (@{$scripts}) {
my ($sname, $plname, $pname) = get_names($_, $xml); my %r;
next unless (defined $xml->{$plname} || ( exists $Irssi::Script::{$pname} && exists $Irssi::Script::{$pname}{IRSSI} )); my $n = get_names($_, $xml);
$result{$sname}{version} = get_remote_version($sname, $xml); next unless (defined $n->{db} || defined $n->{irssi});
$r{version} = $n->{db_version};
my @headers = ('authors', 'contact', 'description', 'license', 'source'); my @headers = ('authors', 'contact', 'description', 'license', 'source');
foreach my $entry (@headers) { foreach my $entry (@headers) {
$result{$sname}{$entry} = $Irssi::Script::{$pname}{IRSSI}{$entry}; $r{$entry} = $n->{irssi}{$entry};
if (defined $xml->{$plname}{$entry}) { if ($n->{db} && defined $n->{db}{$entry}) {
$result{$sname}{$entry} = $xml->{$plname}{$entry}; $r{$entry} = $n->{db}{$entry};
} }
} }
if ($xml->{$plname}{signature_available}) { if ($n->{db} && $n->{db}{signature_available}) {
$result{$sname}{signature_available} = 1; $r{signature_available} = 1;
} }
if (defined $xml->{$plname}{modules}) { if ($n->{db} && defined $n->{db}{modules}) {
my $modules = $xml->{$plname}{modules}; my $modules = $n->{db}{modules};
foreach my $mod (split(/ /, $modules)) { foreach my $mod (split(/ /, $modules)) {
my $opt = ($mod =~ /\((.*)\)/)? 1 : 0; my $opt = ($mod =~ /\((.*)\)/)? 1 : 0;
$mod = $1 if $1; $mod = $1 if $1;
$result{$sname}{modules}{$mod}{optional} = $opt; $r{modules}{$mod}{optional} = $opt;
$result{$sname}{modules}{$mod}{installed} = module_exist($mod); $r{modules}{$mod}{installed} = module_exist($mod);
} }
} elsif (defined $Irssi::Script::{$pname}{IRSSI}{modules}) { } elsif ($n->{irssi} && defined $n->{irssi}{modules}) {
my $modules = $Irssi::Script::{$pname}{IRSSI}{modules}; my $modules = $n->{irssi}{modules};
foreach my $mod (split(/ /, $modules)) { foreach my $mod (split(/ /, $modules)) {
my $opt = ($mod =~ /\((.*)\)/)? 1 : 0; my $opt = ($mod =~ /\((.*)\)/)? 1 : 0;
$mod = $1 if $1; $mod = $1 if $1;
$result{$sname}{modules}{$mod}{optional} = $opt; $r{modules}{$mod}{optional} = $opt;
$result{$sname}{modules}{$mod}{installed} = module_exist($mod); $r{modules}{$mod}{installed} = module_exist($mod);
} }
} }
# if (defined $xml->{$plname}{depends}) { if (!$py && $n->{db} && $n->{db}{language} eq 'Python') { # py
# my $depends = $xml->{$plname}{depends}; $r{modules}{'irssi-python module'}{installed} = 0;
}
# if (defined $n->{db}{depends}) {
# my $depends = $n->{db}{depends};
# foreach my $dep (split(/ /, $depends)) { # foreach my $dep (split(/ /, $depends)) {
# $result{$sname}{depends}{$dep}{installed} = 1; #(defined ${ 'Irssi::Script::'.$dep }); # $r{depends}{$dep}{installed} = 1; #(defined ${ 'Irssi::Script::'.$dep });
# } # }
# } # }
$result{$n->{sname}} = \%r;
} }
return \%result; return \%result;
} }
sub get_rate_url { sub get_rate_url {
my ($src) = @_; my ($src) = @_;
if (ref $src) { ($src) = grep { $_ } map { $_->{source} } values %$src; }
die("No script source address found\n") unless $src;
my $ua = LWP::UserAgent->new(env_proxy=>1, keep_alive=>1, timeout=>30); my $ua = LWP::UserAgent->new(env_proxy=>1, keep_alive=>1, timeout=>30);
$ua->agent('ScriptAssist/'.$VERSION); $ua->agent('ScriptAssist/'.$VERSION);
my $request = HTTP::Request->new('GET', $src); my $request = HTTP::Request->new('GET', $src);
@ -288,6 +366,9 @@ sub get_rate_url {
my $error = join "\n", $response->status_line(), (grep / at .* line \d+/, split "\n", $response->content()), ''; my $error = join "\n", $response->status_line(), (grep / at .* line \d+/, split "\n", $response->content()), '';
die("Fetching ratings location failed: $error"); die("Fetching ratings location failed: $error");
} }
if (my $error = $response->header('X-Died')) {
die("$error\n");
}
my $votes_url; my $votes_url;
for my $tag ($response->content() =~ /<script([^>]*)>/g) { for my $tag ($response->content() =~ /<script([^>]*)>/g) {
my $attr = " $tag "; my $attr = " $tag ";
@ -299,7 +380,7 @@ sub get_rate_url {
} }
$request = HTTP::Request->new('GET', $votes_url); $request = HTTP::Request->new('GET', $votes_url);
$response = $ua->request($request); $response = $ua->request($request);
if (!$response->is_success) { if (!$response->is_success || $response->header('X-Died')) {
my $error = join "\n", $response->status_line(), (grep / at .* line \d+/, split "\n", $response->content()), ''; my $error = join "\n", $response->status_line(), (grep / at .* line \d+/, split "\n", $response->content()), '';
die("Fetching ratings failed: $error"); die("Fetching ratings failed: $error");
} }
@ -311,16 +392,16 @@ sub get_rate_url {
sub rate_script { sub rate_script {
my ($script, $stars) = @_; my ($script, $stars) = @_;
my $xml = get_scripts(); my $xml = get_scripts();
my $votes = get_rate_url(map { $_->{source} } values %$xml); my $votes = get_rate_url($xml);
my ($sname, $plname, $pname) = get_names($script, $xml); my $n = get_names($script, $xml, $votes);
die "Script $script not found\n" unless $votes->{$plname}; die "Script $script not found\n" unless $n->{votes};
return $votes->{$plname}{u} return $n->{votes}{u}
} }
sub get_ratings { sub get_ratings {
my ($scripts, $limit) = @_; my ($scripts, $limit) = @_;
my $xml = get_scripts(); my $xml = get_scripts();
my $votes = get_rate_url(map { $_->{source} } values %$xml); my $votes = get_rate_url($xml);
foreach (keys %{$votes}) { foreach (keys %{$votes}) {
if ($xml->{$_}) { if ($xml->{$_}) {
$xml->{$_}{votes} = $votes->{$_}{v}; $xml->{$_}{votes} = $votes->{$_}{v};
@ -329,9 +410,9 @@ sub get_ratings {
my %result; my %result;
if (@{$scripts}) { if (@{$scripts}) {
foreach (@{$scripts}) { foreach (@{$scripts}) {
my ($sname, $plname, $pname) = get_names($_, $xml); my $n = get_names($_, $xml);
next unless (defined $xml->{$plname} || ( exists $Irssi::Script::{$pname} && exists $Irssi::Script::{$pname}{IRSSI} )); next unless ($n->{db} || $n->{irssi});
$result{$plname} = [$xml->{$plname}{votes}]; $result{$n->{plname}} = [$n->{db}{votes}];
} }
} else { } else {
my @keys = sort { $xml->{$b}{votes} <=> $xml->{$a}{votes} my @keys = sort { $xml->{$b}{votes} <=> $xml->{$a}{votes}
@ -371,16 +452,22 @@ sub debug_scripts {
my ($scripts) = @_; my ($scripts) = @_;
my %result; my %result;
my $xml = get_scripts(); my $xml = get_scripts();
my $py = is_python_loaded();
foreach (@{$scripts}) { foreach (@{$scripts}) {
my ($sname, $plname) = get_names($_, $xml); my %r;
if (defined $xml->{$plname}{modules}) { my $n = get_names($_, $xml);
my $modules = $xml->{$plname}{modules}; if ($n->{db} && defined $n->{db}{modules}) {
my $modules = $n->{db}{modules};
foreach my $mod (split(/ /, $modules)) { foreach my $mod (split(/ /, $modules)) {
my $opt = ($mod =~ /\((.*)\)/)? 1 : 0; my $opt = ($mod =~ /\((.*)\)/)? 1 : 0;
$mod = $1 if $1; $mod = $1 if $1;
$result{$sname}{$mod}{optional} = $opt; $r{$mod}{optional} = $opt;
$result{$sname}{$mod}{installed} = module_exist($mod); $r{$mod}{installed} = module_exist($mod);
} }
$result{$n->{sname}} = \%r;
}
if (!$py && $n->{db} && $n->{db}{language} eq 'Python') { # py
$result{$n->{sname}}{'irssi-python module'}{installed} = 0;
} }
} }
return(\%result); return(\%result);
@ -391,11 +478,11 @@ sub install_scripts {
my %success; my %success;
my $dir = Irssi::get_irssi_dir()."/scripts/"; my $dir = Irssi::get_irssi_dir()."/scripts/";
foreach (@{$scripts}) { foreach (@{$scripts}) {
my ($sname, $plname, $pname) = get_names($_, $xml); my $n = get_names($_, $xml);
if (get_local_version($sname) && (-e $dir.$plname)) { if ($n->{stash} && (-e $dir.$n->{plname})) {
$success{$sname}{installed} = -2; $success{$n->{sname}}{installed} = -2;
} else { } else {
$success{$sname} = download_script($sname, $xml); $success{$n->{sname}} = download_script($n->{sname}, $xml);
} }
} }
return \%success; return \%success;
@ -406,24 +493,24 @@ sub update_scripts {
$list = loaded_scripts() if ($list->[0] eq "all" || scalar(@$list) == 0); $list = loaded_scripts() if ($list->[0] eq "all" || scalar(@$list) == 0);
my %status; my %status;
foreach (@{$list}) { foreach (@{$list}) {
my ($sname) = get_names($_, $database); my $n = get_names($_, $database);
my $local = get_local_version($sname); my $local = $n->{local_version};
my $remote = get_remote_version($sname, $database); my $remote = $n->{db_version};
next if $local eq '' || $remote eq ''; next if $local eq '' || $remote eq '';
if (compare_versions($local, $remote) eq "older") { if (compare_versions($local, $remote) eq "older") {
$status{$sname} = download_script($sname, $database); $status{$n->{sname}} = download_script($n->{sname}, $database);
} else { } else {
$status{$sname}{installed} = -2; $status{$n->{sname}}{installed} = -2;
} }
$status{$sname}{remote} = $remote; $status{$n->{sname}}{remote} = $remote;
$status{$sname}{local} = $local; $status{$n->{sname}}{local} = $local;
} }
return \%status; return \%status;
} }
sub search_scripts { sub search_scripts {
my ($query, $database) = @_; my ($query, $database) = @_;
$query =~ s/\.pl\Z//; $query =~ s/\.pl\Z//; # pl
my %result; my %result;
foreach (sort keys %{$database}) { foreach (sort keys %{$database}) {
my %entry = %{$database->{$_}}; my %entry = %{$database->{$_}};
@ -432,7 +519,7 @@ sub search_scripts {
$string .= $entry{description} if defined $entry{description}; $string .= $entry{description} if defined $entry{description};
if ($string =~ /$query/i) { if ($string =~ /$query/i) {
my $name = $_; my $name = $_;
$name =~ s/\.pl$//; $name =~ s/\.pl$//; # pl
if (defined $entry{description}) { if (defined $entry{description}) {
$result{$name}{desc} = $entry{description}; $result{$name}{desc} = $entry{description};
} else { } else {
@ -443,7 +530,7 @@ sub search_scripts {
} else { } else {
$result{$name}{authors} = ""; $result{$name}{authors} = "";
} }
if (get_local_version($name)) { if (get_names($name, $database)->{stash}) {
$result{$name}{installed} = 1; $result{$name}{installed} = 1;
} else { } else {
$result{$name}{installed} = 0; $result{$name}{installed} = 0;
@ -531,8 +618,8 @@ sub print_unknown {
my $text .= "The command '/".$cmd."' is provided by the script '".$data->{$cmd}{$_}{name}."'.\n"; my $text .= "The command '/".$cmd."' is provided by the script '".$data->{$cmd}{$_}{name}."'.\n";
$text .= "This script is currently not installed on your system.\n"; $text .= "This script is currently not installed on your system.\n";
$text .= "If you want to install the script, enter\n"; $text .= "If you want to install the script, enter\n";
my ($name) = get_names($_); my $n = get_names($_);
$text .= " %U/script install ".$name."%U "; $text .= " %U/script install ".$n->{sname}."%U ";
my $output = draw_box("ScriptAssist", $text, "'".$_."' missing", 1); my $output = draw_box("ScriptAssist", $text, "'".$_."' missing", 1);
print CLIENTCRAP $output; print CLIENTCRAP $output;
} }
@ -541,10 +628,10 @@ sub print_unknown {
sub check_autorun { sub check_autorun {
my ($script) = @_; my ($script) = @_;
my (undef, $plname) = get_names($script); my $n = get_names($script);
my $dir = Irssi::get_irssi_dir()."/scripts/"; my $dir = Irssi::get_irssi_dir()."/scripts/";
if (-e $dir."/autorun/".$plname) { if (-e $dir."/autorun/".$n->{plname}) {
if (readlink($dir."/autorun/".$plname) eq "../".$plname) { if (readlink($dir."/autorun/".$n->{plname}) eq "../".$n->{plname}) {
return 1; return 1;
} }
} }
@ -582,14 +669,15 @@ sub print_info {
my $line; my $line;
foreach my $script (sort keys(%data)) { foreach my $script (sort keys(%data)) {
my ($local, $autorun); my ($local, $autorun);
if (get_local_version($script)) { my $n = get_names($script);
if ($n->{stash}) {
$line .= "%go%n "; $line .= "%go%n ";
$local = get_local_version($script); $local = $n->{local_version};
} else { } else {
$line .= "%ro%n "; $line .= "%ro%n ";
$local = undef; $local = undef;
} }
if (defined $local || check_autorun($script)) { if ($n->{stash} || check_autorun($script)) {
$autorun = "no"; $autorun = "no";
$autorun = "yes" if check_autorun($script); $autorun = "yes" if check_autorun($script);
} else { } else {
@ -643,7 +731,7 @@ sub print_ratings {
my @table; my @table;
foreach my $script (sort {$data{$b}{rating}<=>$data{$a}{rating}} keys(%data)) { foreach my $script (sort {$data{$b}{rating}<=>$data{$a}{rating}} keys(%data)) {
my @line; my @line;
if (get_local_version($script)) { if (get_names($script)->{stash}) {
push @line, "%go%n"; push @line, "%go%n";
} else { } else {
push @line, "%yo%n"; push @line, "%yo%n";
@ -660,13 +748,13 @@ sub print_new {
my @table; my @table;
foreach (sort {$list->{$b}{modified} cmp $list->{$a}{modified}} keys %$list) { foreach (sort {$list->{$b}{modified} cmp $list->{$a}{modified}} keys %$list) {
my @line; my @line;
my ($name) = get_names($_); my $n = get_names($_);
if (get_local_version($name)) { if ($n->{stash}) {
push @line, "%go%n"; push @line, "%go%n";
} else { } else {
push @line, "%yo%n"; push @line, "%yo%n";
} }
push @line, "%9".$name."%9"; push @line, "%9".$n->{sname}."%9";
push @line, $list->{$_}{modified}; push @line, $list->{$_}{modified};
push @table, \@line; push @table, \@line;
} }
@ -678,14 +766,23 @@ sub print_debug {
my $line; my $line;
foreach my $script (sort keys %data) { foreach my $script (sort keys %data) {
$line .= "%ro%n %9".$script."%9 failed to load\n"; $line .= "%ro%n %9".$script."%9 failed to load\n";
$line .= " Make sure you have the following perl modules installed:\n"; my $py = $data{$script}{'irssi-python module'};
if ($py) { # py
$line .= " You are attempting to load a Python script!\n";
} else {
$line .= " Make sure you have the following perl modules installed:\n";
}
foreach (sort keys %{$data{$script}}) { foreach (sort keys %{$data{$script}}) {
if ( $data{$script}{$_}{installed} == 1 ) { if ( $data{$script}{$_}{installed} == 1 ) {
$line .= " %g->%n ".$_." (found)"; $line .= " %g->%n ".$_." (found)";
} else { } else {
$line .= " %r->%n ".$_." (not found)\n"; $line .= " %r->%n ".$_." (not found)\n";
$line .= " [This module is optional]\n" if $data{$script}{$_}{optional}; $line .= " [This module is optional]\n" if $data{$script}{$_}{optional};
$line .= " [Try /scriptassist cpan ".$_."]"; if ($py) { # py
$line .= " [If you have it installed, try: /load python]";
} else {
$line .= " [Try /scriptassist cpan ".$_."]";
}
} }
$line .= "\n"; $line .= "\n";
} }
@ -695,7 +792,13 @@ sub print_debug {
sub load_script { sub load_script {
my ($script) = @_; my ($script) = @_;
Irssi::command('script load '.$script); if ($script =~ s/\.py$//i) { # py
if (is_python_loaded()) {
Irssi::command('py load '.$script);
}
} else {
Irssi::command('script load '.$script); # pl
}
} }
sub print_install { sub print_install {
@ -715,7 +818,7 @@ sub print_install {
} else { } else {
load_script($script) unless (lc($script) eq lc($IRSSI{name})); load_script($script) unless (lc($script) eq lc($IRSSI{name}));
} }
if (get_local_version($script) && not lc($script) eq lc($IRSSI{name})) { if (get_names($script)->{stash} && not lc($script) eq lc($IRSSI{name})) {
$line .= "%go%n %9".$script."%9 installed\n"; $line .= "%go%n %9".$script."%9 installed\n";
push @installed, $script; push @installed, $script;
} elsif (lc($script) eq lc($IRSSI{name})) { } elsif (lc($script) eq lc($IRSSI{name})) {
@ -751,16 +854,14 @@ sub list_sbitems {
my ($scripts) = @_; my ($scripts) = @_;
my $text; my $text;
foreach (@$scripts) { foreach (@$scripts) {
next unless exists $Irssi::Script::{"${_}::"}; my $n = get_names($_);
next unless exists $Irssi::Script::{"${_}::"}{IRSSI}; next unless $n->{irssi}{sbitems};
my $header = $Irssi::Script::{"${_}::"}{IRSSI};
next unless $header->{sbitems};
$text .= '%9"'.$_.'"%9 provides the following statusbar item(s):'."\n"; $text .= '%9"'.$_.'"%9 provides the following statusbar item(s):'."\n";
$text .= ' ->'.$_."\n" foreach (split / /, $header->{sbitems}); $text .= ' ->'.$_."\n" foreach (split / /, $n->{irssi}{sbitems});
} }
return unless $text; return unless $text;
$text .= "\n"; $text .= "\n";
$text .= "Enter '/statusbar window add <item>' to add an item."; $text .= "Enter '/statusbar additem <item> window' to add an item.";
print CLIENTCRAP draw_box('ScriptAssist', $text, 'sbitems', 1); print CLIENTCRAP draw_box('ScriptAssist', $text, 'sbitems', 1);
} }
@ -838,14 +939,12 @@ sub print_update {
sub contact_author { sub contact_author {
my ($script) = @_; my ($script) = @_;
my ($sname, $plname, $pname) = get_names($script); my $n = get_names($script);
return unless exists $Irssi::Script::{$pname}; if ($n->{irssi} && defined $n->{irssi}{contact}) {
my $header = $Irssi::Script::{$pname}{IRSSI}; my @ads = split(/ |,/, $n->{irssi}{contact});
if ($header && defined $header->{contact}) {
my @ads = split(/ |,/, $header->{contact});
my $address = $ads[0]; my $address = $ads[0];
$address .= '?subject='.$script; $address .= '?subject='.$script;
$address .= '_'.get_local_version($script) if defined get_local_version($script); $address .= '_'.$n->{local_version} if $n->{local_version};
call_openurl($address) if $address =~ /[\@:]/; call_openurl($address) if $address =~ /[\@:]/;
} }
} }
@ -874,6 +973,10 @@ sub get_scripts {
$error = join "\n", $response->status_line(), (grep / at .* line \d+/, split "\n", $response->content()), ''; $error = join "\n", $response->status_line(), (grep / at .* line \d+/, split "\n", $response->content()), '';
next; next;
} }
if (my $died = $response->header('X-Died')) {
$error = $died;
next;
}
$fetched = 1; $fetched = 1;
my $data = $response->content(); my $data = $response->content();
my $src = $site; my $src = $site;
@ -929,20 +1032,6 @@ sub get_scripts {
return $remote_db{db}; return $remote_db{db};
} }
sub get_remote_version {
my ($script, $database) = @_;
my $plname = (get_names($script, $database))[1];
return $database->{$plname}{version};
}
sub get_local_version {
my ($script) = @_;
my $pname = (get_names($script))[2];
return unless exists $Irssi::Script::{$pname};
my $vref = $Irssi::Script::{$pname}{VERSION};
return $vref ? $$vref : undef;
}
sub compare_versions { sub compare_versions {
my ($ver1, $ver2) = @_; my ($ver1, $ver2) = @_;
for ($ver1, $ver2) { for ($ver1, $ver2) {
@ -959,11 +1048,42 @@ sub compare_versions {
return 'equal'; return 'equal';
} }
sub is_python_loaded {
!! grep { $_->{cmd} eq 'py' } Irssi::commands
}
my @print_text_capture;
sub capture_print_text {
my ($dest, $text, $plain) = @_;
push @print_text_capture, $plain;
Irssi::signal_stop;
}
sub capture_print_text_command {
my ($command, $sub) = @_;
Irssi::signal_add_first('print text', 'capture_print_text');
@print_text_capture = ();
Irssi::command($command);
my @capture = @print_text_capture;
Irssi::signal_remove('print text', 'capture_print_text');
@print_text_capture = ();
$sub->(@capture);
}
sub loaded_scripts { sub loaded_scripts {
my @modules; my @modules;
foreach (sort grep(s/::$//, keys %Irssi::Script::)) { foreach (sort grep(s/::$//, keys %Irssi::Script::)) { # pl
push @modules, $_; push @modules, $_;
} }
if (is_python_loaded()) {
capture_print_text_command(
'py list', sub {
for my $line (@_[ 1 .. $#_ ]) {
my ($script, $file) = split ' ', $line, 2;
push @modules, "$script.py";
}
});
}
return \@modules; return \@modules;
} }
@ -971,9 +1091,9 @@ sub check_scripts {
my ($data) = @_; my ($data) = @_;
my %versions; my %versions;
foreach (@{loaded_scripts()}) { foreach (@{loaded_scripts()}) {
my ($sname) = get_names($_, $data); my $n = get_names($_, $data);
my $remote = get_remote_version($sname, $data); my $remote = $n->{db_version};
my $local = get_local_version($sname); my $local = $n->{local_version};
my $state; my $state;
if ($local && $remote) { if ($local && $remote) {
$state = compare_versions($local, $remote); $state = compare_versions($local, $remote);
@ -986,9 +1106,9 @@ sub check_scripts {
$remote = '/'; $remote = '/';
} }
if ($state) { if ($state) {
$versions{$sname}{state} = $state; $versions{$n->{sname}}{state} = $state;
$versions{$sname}{remote} = $remote; $versions{$n->{sname}}{remote} = $remote;
$versions{$sname}{local} = $local; $versions{$n->{sname}}{local} = $local;
} }
} }
return \%versions; return \%versions;
@ -996,40 +1116,40 @@ sub check_scripts {
sub download_script { sub download_script {
my ($script, $xml) = @_; my ($script, $xml) = @_;
my ($sname, $plname) = get_names($script, $xml); my $n = get_names($script, $xml);
my $site = $n->{db}{source};
my %result; my %result;
my $site = $xml->{$plname}{source};
$result{installed} = 0; $result{installed} = 0;
$result{signed} = 0; $result{signed} = 0;
my $dir = Irssi::get_irssi_dir(); my $dir = Irssi::get_irssi_dir();
my $ua = LWP::UserAgent->new(env_proxy => 1,keep_alive => 1,timeout => 30); my $ua = LWP::UserAgent->new(env_proxy => 1, keep_alive => 1, timeout => 30);
$ua->agent('ScriptAssist/'.2003020803); $ua->agent('ScriptAssist/'.2003020803);
my $request = HTTP::Request->new('GET', $site.'/scripts/'.$script.'.pl'); my $request = HTTP::Request->new('GET', $site.'/scripts/'.$n->{plname});
my $response = $ua->request($request); my $response = $ua->request($request);
if ($response->is_success()) { if ($response->is_success() && !$response->header('X-Died')) {
my $file = $response->content(); my $file = $response->content();
mkdir $dir.'/scripts/' unless (-e $dir.'/scripts/'); mkdir $dir.'/scripts/' unless (-e $dir.'/scripts/');
open(my $F, '>', $dir.'/scripts/'.$plname.'.new'); open(my $f, '>', $dir.'/scripts/'.$n->{plname}.'.new');
print $F $file; print $f $file;
close($F); close($f);
if ($have_gpg && Irssi::settings_get_bool('scriptassist_use_gpg')) { if ($have_gpg && Irssi::settings_get_bool('scriptassist_use_gpg')) {
my $ua2 = LWP::UserAgent->new(env_proxy => 1,keep_alive => 1,timeout => 30); my $ua2 = LWP::UserAgent->new(env_proxy => 1,keep_alive => 1,timeout => 30);
$ua->agent('ScriptAssist/'.2003020803); $ua->agent('ScriptAssist/'.2003020803);
my $request2 = HTTP::Request->new('GET', $site.'/signatures/'.$plname.'.asc'); my $request2 = HTTP::Request->new('GET', $site.'/signatures/'.$n->{plname}.'.asc');
my $response2 = $ua->request($request2); my $response2 = $ua->request($request2);
if ($response2->is_success()) { if ($response2->is_success() && !$response->header('X-Died')) {
my $sig_dir = $dir.'/scripts/signatures/'; my $sig_dir = $dir.'/scripts/signatures/';
mkdir $sig_dir unless (-e $sig_dir); mkdir $sig_dir unless (-e $sig_dir);
open(my $S, '>', $sig_dir.$plname.'.asc'); open(my $s, '>', $sig_dir.$n->{plname}.'.asc');
my $file2 = $response2->content(); my $file2 = $response2->content();
print $S $file2; print $s $file2;
close($S); close($s);
my $sig; my $sig;
foreach (1..2) { foreach (1..2) {
# FIXME gpg needs two rounds to load the key # FIXME gpg needs two rounds to load the key
my $gpg = new GnuPG(); my $gpg = new GnuPG();
eval { eval {
$sig = $gpg->verify( file => $dir.'/scripts/'.$plname.'.new', signature => $sig_dir.$plname.'.asc' ); $sig = $gpg->verify( file => $dir.'/scripts/'.$n->{plname}.'.new', signature => $sig_dir.$n->{plname}.'.asc' );
}; };
} }
if (defined $sig->{user}) { if (defined $sig->{user}) {
@ -1055,8 +1175,8 @@ sub download_script {
if ($result{installed}) { if ($result{installed}) {
my $old_dir = "$dir/scripts/old/"; my $old_dir = "$dir/scripts/old/";
mkdir $old_dir unless (-e $old_dir); mkdir $old_dir unless (-e $old_dir);
rename "$dir/scripts/$plname", "$old_dir/$plname.old" if -e "$dir/scripts/$plname"; rename "$dir/scripts/".$n->{plname}, "$old_dir/".$n->{plname}.".old" if -e "$dir/scripts/".$n->{plname};
rename "$dir/scripts/$plname.new", "$dir/scripts/$plname"; rename "$dir/scripts/".$n->{plname}.".new", "$dir/scripts/".$n->{plname};
} }
return \%result; return \%result;
} }
@ -1083,23 +1203,23 @@ sub print_check {
sub toggle_autorun { sub toggle_autorun {
my ($script) = @_; my ($script) = @_;
my ($sname, $plname) = get_names($script); my $n = get_names($script);
my $dir = Irssi::get_irssi_dir()."/scripts/"; my $dir = Irssi::get_irssi_dir()."/scripts/";
mkdir $dir."autorun/" unless (-e $dir."autorun/"); mkdir $dir."autorun/" unless (-e $dir."autorun/");
return unless (-e $dir.$plname); return unless (-e $dir.$n->{plname});
if (-e $dir."/autorun/".$plname) { if (-e $dir."/autorun/".$n->{plname}) {
if (readlink($dir."/autorun/".$plname) eq "../".$plname) { if (readlink($dir."/autorun/".$n->{plname}) eq "../".$n->{plname}) {
if (unlink($dir."/autorun/".$plname)) { if (unlink($dir."/autorun/".$n->{plname})) {
print CLIENTCRAP "%R>>%n Autorun of ".$sname." disabled"; print CLIENTCRAP "%R>>%n Autorun of ".$n->{sname}." disabled";
} else { } else {
print CLIENTCRAP "%R>>%n Unable to delete link"; print CLIENTCRAP "%R>>%n Unable to delete link";
} }
} else { } else {
print CLIENTCRAP "%R>>%n ".$dir."/autorun/".$plname." is not a correct link"; print CLIENTCRAP "%R>>%n ".$dir."/autorun/".$n->{plname}." is not a correct link";
} }
} else { } else {
if (symlink("../".$plname, $dir."/autorun/".$plname)) { if (symlink("../".$n->{plname}, $dir."/autorun/".$n->{plname})) {
print CLIENTCRAP "%R>>%n Autorun of ".$sname." enabled"; print CLIENTCRAP "%R>>%n Autorun of ".$n->{sname}." enabled";
} else { } else {
print CLIENTCRAP "%R>>%n Unable to create autorun link"; print CLIENTCRAP "%R>>%n Unable to create autorun link";
} }
@ -1178,9 +1298,9 @@ sub cmd_help {
sub sig_command_script_load { sub sig_command_script_load {
my ($script, $server, $witem) = @_; my ($script, $server, $witem) = @_;
my ($sname, $plname, $pname, $xname) = get_names($script); my $n = get_names($script);
if ( exists $Irssi::Script::{$pname} ) { if ( $n->{stash} ) {
if (my $code = "Irssi::Script::${pname}"->can('pre_unload')) { if (my $code = ("Irssi::Script::".$n->{pname})->can('pre_unload')) {
print CLIENTCRAP "%R>>%n Triggering pre_unload function of $script..."; print CLIENTCRAP "%R>>%n Triggering pre_unload function of $script...";
$code->(); $code->();
} }

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 49 #define IRSSI_ABI_VERSION 58
#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
@ -38,6 +38,7 @@
#include <glib.h> #include <glib.h>
#include <gmodule.h> #include <gmodule.h>
#include <gio/gio.h>
typedef guint64 uoff_t; typedef guint64 uoff_t;
#define PRIuUOFF_T G_GUINT64_FORMAT #define PRIuUOFF_T G_GUINT64_FORMAT

View file

@ -30,6 +30,7 @@
#include <irssi/src/core/servers-setup.h> #include <irssi/src/core/servers-setup.h>
#include <irssi/src/core/servers-reconnect.h> #include <irssi/src/core/servers-reconnect.h>
#include <irssi/src/core/channels.h> #include <irssi/src/core/channels.h>
#include <irssi/src/core/chatnets.h>
#include <irssi/src/core/queries.h> #include <irssi/src/core/queries.h>
#include <irssi/src/core/window-item-def.h> #include <irssi/src/core/window-item-def.h>
#include <irssi/src/core/rawlog.h> #include <irssi/src/core/rawlog.h>
@ -91,7 +92,7 @@ static SERVER_CONNECT_REC *get_server_connect(const char *data, int *plus_addr,
return NULL; return NULL;
} }
if (strchr(addr, '/') != NULL) if (strchr(addr, '/') != NULL && chatnet_find(addr) == NULL)
conn->unix_socket = TRUE; conn->unix_socket = TRUE;
/* TLS options are handled in server_create_conn_opt ... -> server_setup_fill_optlist */ /* TLS options are handled in server_create_conn_opt ... -> server_setup_fill_optlist */
@ -100,10 +101,11 @@ static SERVER_CONNECT_REC *get_server_connect(const char *data, int *plus_addr,
host = g_hash_table_lookup(optlist, "host"); host = g_hash_table_lookup(optlist, "host");
if (host != NULL && *host != '\0') { if (host != NULL && *host != '\0') {
IPADDR ip4, ip6; IPADDR ip4 = { 0 };
IPADDR ip6 = { 0 };
if (net_gethostbyname(host, &ip4, &ip6) == 0) if (net_gethostbyname_first_ips(host, G_RESOLVER_NAME_LOOKUP_FLAGS_DEFAULT, &ip4,
server_connect_own_ip_save(conn, &ip4, &ip6); &ip6) == 0)
server_connect_own_ip_save(conn, &ip4, &ip6);
} }
cmd_params_free(free_arg); cmd_params_free(free_arg);
@ -114,8 +116,8 @@ static SERVER_CONNECT_REC *get_server_connect(const char *data, int *plus_addr,
[-tls_verify] [-tls_cafile <cafile>] [-tls_capath <capath>] [-tls_verify] [-tls_cafile <cafile>] [-tls_capath <capath>]
[-tls_ciphers <list>] [-tls_pinned_cert <fingerprint>] [-tls_ciphers <list>] [-tls_pinned_cert <fingerprint>]
[-tls_pinned_pubkey <fingerprint>] [-!] [-noautosendcmd] [-tls | -notls] [-tls_pinned_pubkey <fingerprint>] [-!] [-noautosendcmd] [-tls | -notls]
[-starttls | -disallow_starttls] [-noproxy] [-network <network>] [-nocap] [-starttls | -disallow_starttls] [-noproxy]
[-host <hostname>] [-rawlog <file>] [-network <network>] [-host <hostname>] [-rawlog <file>]
<address>|<chatnet> [<port> [<password> [<nick>]]] */ <address>|<chatnet> [<port> [<password> [<nick>]]] */
/* NOTE: -network replaces the old -ircnet flag. */ /* NOTE: -network replaces the old -ircnet flag. */
static void cmd_connect(const char *data) static void cmd_connect(const char *data)
@ -211,14 +213,14 @@ static void cmd_server(const char *data, SERVER_REC *server, WI_ITEM_REC *item)
command_runsub("server", data, server, item); command_runsub("server", data, server, item);
} }
/* SYNTAX: SERVER CONNECT [-4 | -6] [-tls] [-tls_cert <cert>] [-tls_pkey <pkey>] /* SYNTAX: SERVER CONNECT [-4 | -6] [-tls | -notls] [-tls_cert <cert>] [-tls_pkey <pkey>]
[-tls_pass <password>] [-tls_verify] [-tls_cafile <cafile>] [-tls_pass <password>] [-tls_verify | -notls_verify] [-tls_cafile <cafile>]
[-tls_capath <capath>] [-tls_capath <capath>] [-tls_ciphers <list>]
[-tls_ciphers <list>] [-tls_pinned_cert <fingerprint>] [-tls_pinned_pubkey <fingerprint>] [-tls_pinned_cert <fingerprint>] [-tls_pinned_pubkey <fingerprint>]
[-!] [-noautosendcmd] [-!] [-noautosendcmd] [-nocap]
[-noproxy] [-network <network>] [-host <hostname>] [-noproxy] [-network <network>] [-host <hostname>]
[-rawlog <file>] [-rawlog <file>]
[+]<address>|<chatnet> [<port> [<password> [<nick>]]] */ [+]<address>|<chatnet> [<port> [<password> [<nick>]]] */
/* NOTE: -network replaces the old -ircnet flag. */ /* NOTE: -network replaces the old -ircnet flag. */
static void cmd_server_connect(const char *data, SERVER_REC *server) static void cmd_server_connect(const char *data, SERVER_REC *server)
{ {

View file

@ -68,6 +68,7 @@ void wcwidth_wrapper_deinit(void);
int irssi_gui; int irssi_gui;
int irssi_init_finished; int irssi_init_finished;
int sighup_received; int sighup_received;
int sigterm_received;
time_t client_start_time; time_t client_start_time;
static char *irssi_dir, *irssi_config_file; static char *irssi_dir, *irssi_config_file;
@ -89,6 +90,11 @@ static void sig_hup(int signo)
sighup_received = TRUE; sighup_received = TRUE;
} }
static void sig_term(int signo)
{
sigterm_received = TRUE;
}
static void read_settings(void) static void read_settings(void)
{ {
static int signals[] = { static int signals[] = {
@ -113,8 +119,15 @@ static void read_settings(void)
sigaction(SIGHUP, &act, NULL); sigaction(SIGHUP, &act, NULL);
for (n = 0; n < sizeof(signals)/sizeof(signals[0]); n++) { for (n = 0; n < sizeof(signals)/sizeof(signals[0]); n++) {
act.sa_handler = find_substr(ignores, signames[n]) ? if (find_substr(ignores, signames[n])) {
SIG_IGN : SIG_DFL; act.sa_handler = SIG_IGN;
} else {
/* set default handlers */
if (signals[n] == SIGTERM)
act.sa_handler = sig_term;
else
act.sa_handler = SIG_DFL;
}
sigaction(signals[n], &act, NULL); sigaction(signals[n], &act, NULL);
} }

View file

@ -14,6 +14,7 @@
extern int irssi_gui; extern int irssi_gui;
extern int irssi_init_finished; /* TRUE after "irssi init finished" signal is sent */ extern int irssi_init_finished; /* TRUE after "irssi init finished" signal is sent */
extern int sighup_received; /* TRUE after received SIGHUP. */ extern int sighup_received; /* TRUE after received SIGHUP. */
extern int sigterm_received; /* TRUE after received SIGTERM. */
extern time_t client_start_time; extern time_t client_start_time;
void core_preinit(const char *path); void core_preinit(const char *path);

View file

@ -19,6 +19,7 @@
*/ */
#include "module.h" #include "module.h"
#include <irssi/src/core/misc.h>
#include <irssi/src/core/levels.h> #include <irssi/src/core/levels.h>
/* the order of these levels must match the bits in levels.h */ /* the order of these levels must match the bits in levels.h */
@ -169,8 +170,7 @@ char *bits2level(int bits)
if (str->len > 0) if (str->len > 0)
g_string_truncate(str, str->len-1); g_string_truncate(str, str->len-1);
ret = str->str; ret = g_string_free_and_steal(str);
g_string_free(str, FALSE);
return ret; return ret;
} }
@ -184,13 +184,15 @@ int combine_level(int dest, const char *src)
list = g_strsplit(src, " ", -1); list = g_strsplit(src, " ", -1);
for (item = list; *item != NULL; item++) { for (item = list; *item != NULL; item++) {
itemname = *item + (**item == '+' || **item == '-' ? 1 : 0); itemname = *item + (**item == '+' || **item == '-' || **item == '^' ? 1 : 0);
itemlevel = level_get(itemname); itemlevel = level_get(itemname);
if (g_strcmp0(itemname, "NONE") == 0) if (g_ascii_strcasecmp(itemname, "NONE") == 0)
dest = 0; dest = 0;
else if (**item == '-') else if (**item == '-')
dest &= ~(itemlevel); dest &= ~(itemlevel);
else if (**item == '^')
dest ^= itemlevel;
else else
dest |= itemlevel; dest |= itemlevel;
} }

View file

@ -3,10 +3,11 @@
if have_capsicum if have_capsicum
core_capsicum_source = files('capsicum.c') core_capsicum_source = files('capsicum.c')
else else
core_capsicum_source = [] core_capsicum_source = [ ]
endif endif
libcore_a = static_library('core', libcore_a = static_library(
'core',
files( files(
'args.c', 'args.c',
'channels-setup.c', 'channels-setup.c',
@ -63,7 +64,8 @@ libcore_a = static_library('core',
def_moduledir, def_moduledir,
def_sysconfdir, def_sysconfdir,
], ],
dependencies : dep) dependencies : dep,
)
install_headers( install_headers(
files( files(
@ -122,4 +124,5 @@ install_headers(
'window-item-def.h', 'window-item-def.h',
'write-buffer.h', 'write-buffer.h',
), ),
subdir : incdir / 'src' / 'core') subdir : incdir / 'src' / 'core',
)

View file

@ -135,6 +135,15 @@ GDateTime *g_date_time_new_from_iso8601(const gchar *iso_date, GTimeZone *defaul
} }
#endif #endif
#if GLIB_CHECK_VERSION(2, 76, 0)
/* nothing */
#else
gchar *g_string_free_and_steal(GString *string)
{
return g_string_free(string, FALSE);
}
#endif
int find_substr(const char *list, const char *item) int find_substr(const char *list, const char *item)
{ {
const char *ptr; const char *ptr;
@ -261,8 +270,7 @@ char *gslistptr_to_string(GSList *list, int offset, const char *delimiter)
list = list->next; list = list->next;
} }
ret = str->str; ret = g_string_free_and_steal(str);
g_string_free(str, FALSE);
return ret; return ret;
} }
@ -280,8 +288,7 @@ char *i_slist_to_string(GSList *list, const char *delimiter)
list = list->next; list = list->next;
} }
ret = str->str; ret = g_string_free_and_steal(str);
g_string_free(str, FALSE);
return ret; return ret;
} }

View file

@ -26,6 +26,12 @@ long get_timeval_diff(const GTimeVal *tv1, const GTimeVal *tv2) G_GNUC_DEPRECATE
GDateTime *g_date_time_new_from_iso8601(const gchar *iso_date, GTimeZone *default_tz); GDateTime *g_date_time_new_from_iso8601(const gchar *iso_date, GTimeZone *default_tz);
#endif #endif
#if GLIB_CHECK_VERSION(2, 76, 0)
/* nothing */
#else
gchar *g_string_free_and_steal(GString *string);
#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

@ -42,7 +42,7 @@ static char *module_get_name(const char *path, int *start, int *end)
if (name == NULL) if (name == NULL)
name = path; name = path;
if (strncmp(name, "lib", 3) == 0) if (strncmp(name, "lib", 3) == 0 || strncmp(name, "cyg", 3) == 0)
name += 3; name += 3;
module_name = g_strdup(name); module_name = g_strdup(name);
@ -102,10 +102,41 @@ static char *module_get_sub(const char *name, const char *root)
return g_strdup(name); return g_strdup(name);
} }
static GModule *module_open(const char *name, int *found) static GModule *module_open(const char *name)
{ {
struct stat statbuf;
GModule *module; GModule *module;
#if GLIB_CHECK_VERSION(2, 75, 0)
/* in this version of glib, g_module_open knows how to construct system-dependent module
file names, and g_module_build_path is deprecated. */
char *path;
if (g_path_is_absolute(name) || *name == '~' ||
(*name == '.' && name[1] == G_DIR_SEPARATOR))
path = g_strdup(name);
else {
/* first try from home dir */
path = g_strdup_printf("%s/modules/%s", get_irssi_dir(), name);
module = g_module_open(path, (GModuleFlags) 0);
g_free(path);
if (module != NULL) {
return module;
}
/* module not found from home dir, try global module dir */
path = g_strdup_printf("%s/%s", MODULEDIR, name);
}
module = g_module_open(path, (GModuleFlags) 0);
g_free(path);
return module;
#else /* GLib < 2.75.0 */
/* in this version of glib, we build the module path with g_module_build_path.
unfortunately, this is broken on Darwin when compiled with meson. */
struct stat statbuf;
char *path, *str; char *path, *str;
if (g_path_is_absolute(name) || *name == '~' || if (g_path_is_absolute(name) || *name == '~' ||
@ -120,7 +151,6 @@ static GModule *module_open(const char *name, int *found)
if (stat(path, &statbuf) == 0) { if (stat(path, &statbuf) == 0) {
module = g_module_open(path, (GModuleFlags) 0); module = g_module_open(path, (GModuleFlags) 0);
g_free(path); g_free(path);
*found = TRUE;
return module; return module;
} }
@ -129,10 +159,11 @@ static GModule *module_open(const char *name, int *found)
path = g_module_build_path(MODULEDIR, name); path = g_module_build_path(MODULEDIR, name);
} }
*found = stat(path, &statbuf) == 0;
module = g_module_open(path, (GModuleFlags) 0); module = g_module_open(path, (GModuleFlags) 0);
g_free(path); g_free(path);
return module; return module;
#endif
} }
static char *module_get_func(const char *rootmodule, const char *submodule, static char *module_get_func(const char *rootmodule, const char *submodule,
@ -151,8 +182,7 @@ static char *module_get_func(const char *rootmodule, const char *submodule,
signal_emit("module error", 4, GINT_TO_POINTER(error), text, \ signal_emit("module error", 4, GINT_TO_POINTER(error), text, \
rootmodule, submodule) rootmodule, submodule)
/* Returns 1 if ok, 0 if error in module and /* Returns 1 if ok, 0 if not */
-1 if module wasn't found */
static int module_load_name(const char *path, const char *rootmodule, static int module_load_name(const char *path, const char *rootmodule,
const char *submodule, int silent) const char *submodule, int silent)
{ {
@ -166,15 +196,15 @@ static int module_load_name(const char *path, const char *rootmodule,
gpointer value1, value2 = NULL; gpointer value1, value2 = NULL;
char *versionfunc, *initfunc, *deinitfunc; char *versionfunc, *initfunc, *deinitfunc;
int module_abi_version = 0; int module_abi_version = 0;
int found; int valid;
gmodule = module_open(path, &found); gmodule = module_open(path);
if (gmodule == NULL) { if (gmodule == NULL) {
if (!silent || found) { if (!silent) {
module_error(MODULE_ERROR_LOAD, g_module_error(), module_error(MODULE_ERROR_LOAD, g_module_error(),
rootmodule, submodule); rootmodule, submodule);
} }
return found ? 0 : -1; return 0;
} }
/* get the module's irssi abi version and bail out on mismatch */ /* get the module's irssi abi version and bail out on mismatch */
@ -201,12 +231,12 @@ static int module_load_name(const char *path, const char *rootmodule,
/* get the module's init() and deinit() functions */ /* get the module's init() and deinit() functions */
initfunc = module_get_func(rootmodule, submodule, "init"); initfunc = module_get_func(rootmodule, submodule, "init");
deinitfunc = module_get_func(rootmodule, submodule, "deinit"); deinitfunc = module_get_func(rootmodule, submodule, "deinit");
found = g_module_symbol(gmodule, initfunc, &value1) && valid = g_module_symbol(gmodule, initfunc, &value1) &&
g_module_symbol(gmodule, deinitfunc, &value2); g_module_symbol(gmodule, deinitfunc, &value2);
g_free(initfunc); g_free(initfunc);
g_free(deinitfunc); g_free(deinitfunc);
if (!found) { if (!valid) {
module_error(MODULE_ERROR_INVALID, NULL, module_error(MODULE_ERROR_INVALID, NULL,
rootmodule, submodule); rootmodule, submodule);
g_module_close(gmodule); g_module_close(gmodule);
@ -310,7 +340,7 @@ static int module_load_full(const char *path, const char *rootmodule,
/* check if the given module exists.. */ /* check if the given module exists.. */
try_prefixes = g_strcmp0(rootmodule, submodule) == 0; try_prefixes = g_strcmp0(rootmodule, submodule) == 0;
status = module_load_name(path, rootmodule, submodule, try_prefixes); status = module_load_name(path, rootmodule, submodule, try_prefixes);
if (status == -1 && try_prefixes) { if (status <= 0 && try_prefixes) {
/* nope, try loading the module_core, /* nope, try loading the module_core,
fe_module, etc. */ fe_module, etc. */
status = module_load_prefixes(path, rootmodule, status = module_load_prefixes(path, rootmodule,

View file

@ -21,6 +21,8 @@
#include "module.h" #include "module.h"
#include <irssi/src/core/network.h> #include <irssi/src/core/network.h>
#include <sys/select.h>
/* when quitting, wait for max. 5 seconds before forcing to close the socket */ /* when quitting, wait for max. 5 seconds before forcing to close the socket */
#define MAX_QUIT_CLOSE_WAIT 5 #define MAX_QUIT_CLOSE_WAIT 5

View file

@ -22,86 +22,94 @@
#include <signal.h> #include <signal.h>
#include <irssi/src/core/pidwait.h> #include <irssi/src/core/network.h>
#include <irssi/src/core/net-nonblock.h> #include <irssi/src/core/net-nonblock.h>
/* nonblocking gethostbyname(), ip (IPADDR) + error (int, 0 = not error) is typedef struct {
written to pipe when found PID of the resolver child is returned */ GResolverNameLookupFlags flags;
int net_gethostbyname_nonblock(const char *addr, GIOChannel *pipe, int reverse_lookup) NetGethostbynameContinuationFunc cont;
{ void *cont_data;
RESOLVED_IP_REC rec; } NET_GETHOSTBYNAME_CALLBACK_DATA;
const char *errorstr;
int pid;
(void) reverse_lookup; /* Kept for API backward compatibility */ static void net_gethostbyname_callback(GResolver *resolver, GAsyncResult *result,
NET_GETHOSTBYNAME_CALLBACK_DATA *data)
{
/* GList<GInetAddress> */
GList *ailist;
GError *error;
RESOLVED_IP_REC *iprec;
error = NULL;
#if GLIB_CHECK_VERSION(2, 59, 0)
ailist = g_resolver_lookup_by_name_with_flags_finish(resolver, result, &error);
#else
/* compatibility code for old GLib */
ailist = g_resolver_lookup_by_name_finish(resolver, result, &error);
if (error == NULL && data->flags) {
GList *ll, *lll;
for (ll = ailist; ll != NULL; ll = lll) {
GInetAddress *address;
GSocketFamily family;
address = G_INET_ADDRESS(ll->data);
family = g_inet_address_get_family(address);
lll = ll->next;
if ((data->flags == G_RESOLVER_NAME_LOOKUP_FLAGS_IPV4_ONLY &&
family == G_SOCKET_FAMILY_IPV6) ||
(data->flags == G_RESOLVER_NAME_LOOKUP_FLAGS_IPV6_ONLY &&
family == G_SOCKET_FAMILY_IPV4)) {
g_object_unref(address);
ailist = g_list_delete_link(ailist, ll);
}
}
if (ailist == NULL) {
g_set_error(&error, G_RESOLVER_ERROR, G_RESOLVER_ERROR_NOT_FOUND,
data->flags == G_RESOLVER_NAME_LOOKUP_FLAGS_IPV4_ONLY ?
"IPv4 address not found for host" :
"IPv6 address not found for host");
}
}
#endif
iprec = g_new0(RESOLVED_IP_REC, 1);
if (error != NULL) {
iprec->error = error;
} else {
iprec->ailist = ailist;
}
g_object_unref(resolver);
resolved_ip_ref(iprec);
data->cont(iprec, data->cont_data);
g_free(data);
}
/* nonblocking gethostbyname() */
GCancellable *net_gethostbyname_nonblock(const char *addr, GResolverNameLookupFlags flags,
NetGethostbynameContinuationFunc cont, void *cont_data)
{
GResolver *resolver;
GCancellable *cancellable;
NET_GETHOSTBYNAME_CALLBACK_DATA *data;
g_return_val_if_fail(addr != NULL, FALSE); g_return_val_if_fail(addr != NULL, FALSE);
pid = fork(); resolver = g_resolver_get_default();
if (pid > 0) { cancellable = g_cancellable_new();
/* parent */ data = g_new0(NET_GETHOSTBYNAME_CALLBACK_DATA, 1);
pidwait_add(pid); data->flags = flags;
return pid; data->cont = cont;
} data->cont_data = cont_data;
#if GLIB_CHECK_VERSION(2, 59, 0)
if (pid != 0) { g_resolver_lookup_by_name_with_flags_async(resolver, addr, flags, cancellable,
/* failed! */ (GAsyncReadyCallback) net_gethostbyname_callback,
g_warning("net_connect_thread(): fork() failed! " data);
"Using blocking resolving"); #else
} /* compatibility code for old GLib */
g_resolver_lookup_by_name_async(resolver, addr, cancellable,
/* child */ (GAsyncReadyCallback) net_gethostbyname_callback, data);
srand(time(NULL)); #endif
return cancellable;
memset(&rec, 0, sizeof(rec));
rec.error = net_gethostbyname(addr, &rec.ip4, &rec.ip6);
if (rec.error == 0) {
errorstr = NULL;
} else {
errorstr = net_gethosterror(rec.error);
rec.errlen = errorstr == NULL ? 0 : strlen(errorstr)+1;
}
i_io_channel_write_block(pipe, &rec, sizeof(rec));
if (rec.errlen != 0)
i_io_channel_write_block(pipe, (void *) errorstr, rec.errlen);
if (pid == 0)
_exit(99);
/* we used blocking lookup */
return 0;
}
/* get the resolved IP address */
int net_gethostbyname_return(GIOChannel *pipe, RESOLVED_IP_REC *rec)
{
rec->error = -1;
rec->errorstr = NULL;
fcntl(g_io_channel_unix_get_fd(pipe), F_SETFL, O_NONBLOCK);
/* get ip+error */
if (i_io_channel_read_block(pipe, rec, sizeof(*rec)) == -1) {
rec->errorstr = g_strdup_printf("Host name lookup: %s",
g_strerror(errno));
return -1;
}
if (rec->error) {
/* read error string, if we can't read everything for some
reason, just ignore it. */
rec->errorstr = g_malloc0(rec->errlen+1);
i_io_channel_read_block(pipe, rec->errorstr, rec->errlen);
}
return 0;
}
/* Kill the resolver child */
void net_disconnect_nonblock(int pid)
{
g_return_if_fail(pid > 0);
kill(pid, SIGKILL);
} }

View file

@ -3,20 +3,10 @@
#include <irssi/src/core/network.h> #include <irssi/src/core/network.h>
typedef struct { typedef void (*NetGethostbynameContinuationFunc)(RESOLVED_IP_REC *, void *);
IPADDR ip4, ip6; /* resolved ip addresses */
int error; /* error, 0 = no error, -1 = error: */
int errlen; /* error text length */
char *errorstr; /* error string - dynamically allocated, you'll
need to free() it yourself unless it's NULL */
} RESOLVED_IP_REC;
/* nonblocking gethostbyname(), PID of the resolver child is returned. */ /* nonblocking gethostbyname(), Cancellable of the resolver child is returned. */
int net_gethostbyname_nonblock(const char *addr, GIOChannel *pipe, int reverse_lookup); GCancellable *net_gethostbyname_nonblock(const char *addr, GResolverNameLookupFlags flags,
/* get the resolved IP address. returns -1 if some error occurred with read() */ NetGethostbynameContinuationFunc cont, void *cont_data);
int net_gethostbyname_return(GIOChannel *pipe, RESOLVED_IP_REC *rec);
/* Kill the resolver child */
void net_disconnect_nonblock(int pid);
#endif #endif

View file

@ -28,6 +28,7 @@
#include <irssi/src/core/tls.h> #include <irssi/src/core/tls.h>
#include <openssl/crypto.h> #include <openssl/crypto.h>
#include <openssl/objects.h>
#include <openssl/x509.h> #include <openssl/x509.h>
#include <openssl/x509v3.h> #include <openssl/x509v3.h>
#include <openssl/pem.h> #include <openssl/pem.h>
@ -751,44 +752,49 @@ static void set_server_temporary_key_info(TLS_REC *tls, SSL *ssl)
#ifdef SSL_get_server_tmp_key #ifdef SSL_get_server_tmp_key
/* Show ephemeral key information. */ /* Show ephemeral key information. */
EVP_PKEY *ephemeral_key = NULL; EVP_PKEY *ephemeral_key = NULL;
/* OPENSSL_NO_EC is for solaris 11.3 (2016), github ticket #598 */
#ifndef OPENSSL_NO_EC
EC_KEY *ec_key = NULL;
#endif
char *ephemeral_key_algorithm = NULL; char *ephemeral_key_algorithm = NULL;
char *cname = NULL;
int nid;
g_return_if_fail(tls != NULL); g_return_if_fail(tls != NULL);
g_return_if_fail(ssl != NULL); g_return_if_fail(ssl != NULL);
if (SSL_get_server_tmp_key(ssl, &ephemeral_key)) { if (SSL_get_server_tmp_key(ssl, &ephemeral_key)) {
switch (EVP_PKEY_id(ephemeral_key)) { int keytype = EVP_PKEY_id(ephemeral_key);
case EVP_PKEY_DH: switch (keytype) {
tls_rec_set_ephemeral_key_algorithm(tls, "DH"); case EVP_PKEY_DH:
tls_rec_set_ephemeral_key_size(tls, EVP_PKEY_bits(ephemeral_key)); tls_rec_set_ephemeral_key_algorithm(tls, "DH");
break; tls_rec_set_ephemeral_key_size(tls, EVP_PKEY_bits(ephemeral_key));
break;
/* OPENSSL_NO_EC is for solaris 11.3 (2016), github ticket #598 */
#ifndef OPENSSL_NO_EC #ifndef OPENSSL_NO_EC
case EVP_PKEY_EC: case EVP_PKEY_EC: {
ec_key = EVP_PKEY_get1_EC_KEY(ephemeral_key); #if (OPENSSL_VERSION_NUMBER >= 0x30000000L)
nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec_key)); char cname[50];
EC_KEY_free(ec_key); EVP_PKEY_get_group_name(ephemeral_key, cname, sizeof(cname), NULL);
cname = (char *)OBJ_nid2sn(nid); #else
ephemeral_key_algorithm = g_strdup_printf("ECDH: %s", cname); EC_KEY *ec_key = NULL;
char *cname = NULL;
int nid;
tls_rec_set_ephemeral_key_algorithm(tls, ephemeral_key_algorithm); ec_key = EVP_PKEY_get1_EC_KEY(ephemeral_key);
tls_rec_set_ephemeral_key_size(tls, EVP_PKEY_bits(ephemeral_key)); nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec_key));
EC_KEY_free(ec_key);
cname = (char *) OBJ_nid2sn(nid);
#endif
ephemeral_key_algorithm = g_strdup_printf("ECDH: %s", cname);
g_free_and_null(ephemeral_key_algorithm); tls_rec_set_ephemeral_key_algorithm(tls, ephemeral_key_algorithm);
break; tls_rec_set_ephemeral_key_size(tls, EVP_PKEY_bits(ephemeral_key));
g_free_and_null(ephemeral_key_algorithm);
break;
}
#endif #endif
default: default:
tls_rec_set_ephemeral_key_algorithm(tls, "Unknown"); tls_rec_set_ephemeral_key_algorithm(tls, OBJ_nid2ln(keytype));
tls_rec_set_ephemeral_key_size(tls, EVP_PKEY_bits(ephemeral_key)); tls_rec_set_ephemeral_key_size(tls, EVP_PKEY_bits(ephemeral_key));
break; break;
} }
EVP_PKEY_free(ephemeral_key); EVP_PKEY_free(ephemeral_key);

View file

@ -81,27 +81,14 @@ int i_io_channel_read_block(GIOChannel *channel, void *data, int len)
return received < len ? -1 : 0; return received < len ? -1 : 0;
} }
IPADDR ip4_any = { IPADDR ip4_any = { AF_INET,
AF_INET,
#if defined(IN6ADDR_ANY_INIT) #if defined(IN6ADDR_ANY_INIT)
IN6ADDR_ANY_INIT IN6ADDR_ANY_INIT
#else #else
{ INADDR_ANY } { INADDR_ANY }
#endif #endif
}; };
int net_ip_compare(IPADDR *ip1, IPADDR *ip2)
{
if (ip1->family != ip2->family)
return 0;
if (ip1->family == AF_INET6)
return memcmp(&ip1->ip, &ip2->ip, sizeof(ip1->ip)) == 0;
return memcmp(&ip1->ip, &ip2->ip, 4) == 0;
}
static void sin_set_ip(union sockaddr_union *so, const IPADDR *ip) static void sin_set_ip(union sockaddr_union *so, const IPADDR *ip)
{ {
if (ip == NULL) { if (ip == NULL) {
@ -392,95 +379,119 @@ int net_getsockname(GIOChannel *handle, IPADDR *addr, int *port)
return 0; return 0;
} }
/* Get IP addresses for host, both IPv4 and IPv6 if possible. void resolved_ip_ref(RESOLVED_IP_REC *iprec)
If ip->family is 0, the address wasn't found.
Returns 0 = ok, others = error code for net_gethosterror() */
int net_gethostbyname(const char *addr, IPADDR *ip4, IPADDR *ip6)
{ {
union sockaddr_union *so; iprec->refcount++;
struct addrinfo hints, *ai, *ailist; }
int ret, count_v4, count_v6, use_v4, use_v6;
int resolved_ip_unref(RESOLVED_IP_REC *iprec)
{
if (--iprec->refcount > 0) {
return TRUE;
}
g_resolver_free_addresses(iprec->ailist);
if (iprec->error != NULL) {
g_error_free(iprec->error);
}
g_free(iprec);
return FALSE;
}
/* Get IP addresses for host, both IPv4 and IPv6 if possible. */
static RESOLVED_IP_REC *net_gethostbyname(const char *addr, GResolverNameLookupFlags flags)
{
/* GList<GInetAddress> */
GList *ailist;
GError *error;
GResolver *resolver;
RESOLVED_IP_REC *iprec;
g_return_val_if_fail(addr != NULL, NULL);
error = NULL;
resolver = g_resolver_get_default();
#if GLIB_CHECK_VERSION(2, 59, 0)
ailist = g_resolver_lookup_by_name_with_flags(resolver, addr, flags, NULL, &error);
#else
/* compatibility code for old GLib */
ailist = g_resolver_lookup_by_name(resolver, addr, NULL, &error);
if (error == NULL && flags) {
GList *ll, *lll;
for (ll = ailist; ll != NULL; ll = lll) {
GInetAddress *address;
GSocketFamily family;
address = G_INET_ADDRESS(ll->data);
family = g_inet_address_get_family(address);
lll = ll->next;
if ((flags == G_RESOLVER_NAME_LOOKUP_FLAGS_IPV4_ONLY &&
family == G_SOCKET_FAMILY_IPV6) ||
(flags == G_RESOLVER_NAME_LOOKUP_FLAGS_IPV6_ONLY &&
family == G_SOCKET_FAMILY_IPV4)) {
g_object_unref(address);
ailist = g_list_delete_link(ailist, ll);
}
}
if (ailist == NULL) {
g_set_error(&error, G_RESOLVER_ERROR, G_RESOLVER_ERROR_NOT_FOUND,
flags == G_RESOLVER_NAME_LOOKUP_FLAGS_IPV4_ONLY ?
"IPv4 address not found for host" :
"IPv6 address not found for host");
}
}
#endif
iprec = g_new0(RESOLVED_IP_REC, 1);
if (error != NULL) {
iprec->error = error;
} else {
iprec->ailist = ailist;
}
g_object_unref(resolver);
resolved_ip_ref(iprec);
return iprec;
}
int net_gethostbyname_first_ips(const char *addr, GResolverNameLookupFlags flags, IPADDR *ip4,
IPADDR *ip6)
{
RESOLVED_IP_REC *iprec;
#ifdef HAVE_CAPSICUM #ifdef HAVE_CAPSICUM
if (capsicum_enabled()) if (capsicum_enabled())
return (capsicum_net_gethostbyname(addr, ip4, ip6)); return (capsicum_net_gethostbyname(addr, ip4, ip6));
#endif #endif
g_return_val_if_fail(addr != NULL, -1); iprec = net_gethostbyname(addr, flags);
if (iprec->error == NULL) {
GList *curr;
memset(ip4, 0, sizeof(IPADDR)); for (curr = iprec->ailist; curr; curr = curr->next) {
memset(ip6, 0, sizeof(IPADDR)); unsigned short family;
GInetAddress *addr;
memset(&hints, 0, sizeof(struct addrinfo)); addr = curr->data;
hints.ai_socktype = SOCK_STREAM; family = g_inet_address_get_family(addr);
hints.ai_flags = AI_ADDRCONFIG; if (ip4->family == 0 && family == AF_INET) {
ip4->family = AF_INET;
/* save error to host_error for later use */ memcpy(&ip4->ip, g_inet_address_to_bytes(addr), sizeof(ip4->ip));
ret = getaddrinfo(addr, NULL, &hints, &ailist); } else if (ip6->family == 0 && family == AF_INET6) {
if (ret != 0) ip6->family = AF_INET6;
return ret; memcpy(&ip6->ip, g_inet_address_to_bytes(addr), sizeof(ip6->ip));
}
/* count IPs */
count_v4 = count_v6 = 0;
for (ai = ailist; ai != NULL; ai = ai->ai_next) {
if (ai->ai_family == AF_INET)
count_v4++;
else if (ai->ai_family == AF_INET6)
count_v6++;
}
if (count_v4 == 0 && count_v6 == 0)
return HOST_NOT_FOUND; /* shouldn't happen? */
/* if there are multiple addresses, return random one */
use_v4 = count_v4 <= 1 ? 0 : rand() % count_v4;
use_v6 = count_v6 <= 1 ? 0 : rand() % count_v6;
count_v4 = count_v6 = 0;
for (ai = ailist; ai != NULL; ai = ai->ai_next) {
so = (union sockaddr_union *) ai->ai_addr;
if (ai->ai_family == AF_INET) {
if (use_v4 == count_v4)
sin_get_ip(so, ip4);
count_v4++;
} else if (ai->ai_family == AF_INET6) {
if (use_v6 == count_v6)
sin_get_ip(so, ip6);
count_v6++;
} }
resolved_ip_unref(iprec);
return 0;
} else {
resolved_ip_unref(iprec);
return -1;
} }
freeaddrinfo(ailist);
return 0;
}
/* Get name for host, *name should be g_free()'d unless it's NULL.
Return values are the same as with net_gethostbyname() */
int net_gethostbyaddr(IPADDR *ip, char **name)
{
union sockaddr_union so;
int host_error;
char hostname[NI_MAXHOST];
g_return_val_if_fail(ip != NULL, -1);
g_return_val_if_fail(name != NULL, -1);
*name = NULL;
memset(&so, 0, sizeof(so));
sin_set_ip(&so, ip);
/* save error to host_error for later use */
host_error = getnameinfo((struct sockaddr *)&so, sizeof(so),
hostname, sizeof(hostname),
NULL, 0,
NI_NAMEREQD);
if (host_error != 0)
return host_error;
*name = g_strdup(hostname);
return 0;
} }
int net_ip2host(IPADDR *ip, char *host) int net_ip2host(IPADDR *ip, char *host)
@ -491,8 +502,6 @@ int net_ip2host(IPADDR *ip, char *host)
int net_host2ip(const char *host, IPADDR *ip) int net_host2ip(const char *host, IPADDR *ip)
{ {
unsigned long addr;
if (strchr(host, ':') != NULL) { if (strchr(host, ':') != NULL) {
/* IPv6 */ /* IPv6 */
ip->family = AF_INET6; ip->family = AF_INET6;
@ -501,16 +510,8 @@ int net_host2ip(const char *host, IPADDR *ip)
} else { } else {
/* IPv4 */ /* IPv4 */
ip->family = AF_INET; ip->family = AF_INET;
#ifdef HAVE_INET_ATON if (inet_pton(AF_INET, host, &ip->ip) == 0)
if (inet_aton(host, &ip->ip.s_addr) == 0)
return -1; return -1;
#else
addr = inet_addr(host);
if (addr == INADDR_NONE)
return -1;
memcpy(&ip->ip, &addr, 4);
#endif
} }
return 0; return 0;
@ -529,29 +530,6 @@ int net_geterror(GIOChannel *handle)
return data; return data;
} }
/* get error of net_gethostname() */
const char *net_gethosterror(int error)
{
g_return_val_if_fail(error != 0, NULL);
if (error == EAI_SYSTEM) {
return strerror(errno);
} else {
return gai_strerror(error);
}
}
/* return TRUE if host lookup failed because it didn't exist (ie. not
some error with name server) */
int net_hosterror_notfound(int error)
{
#ifdef EAI_NODATA /* NODATA is deprecated */
return error != 1 && (error == EAI_NONAME || error == EAI_NODATA);
#else
return error != 1 && (error == EAI_NONAME);
#endif
}
/* Get name of TCP service */ /* Get name of TCP service */
char *net_getservbyport(int port) char *net_getservbyport(int port)
{ {

View file

@ -6,6 +6,7 @@
#include <netinet/in.h> #include <netinet/in.h>
#include <netdb.h> #include <netdb.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <irssi/src/common.h>
#ifndef AF_INET6 #ifndef AF_INET6
# ifdef PF_INET6 # ifdef PF_INET6
@ -15,11 +16,31 @@
# endif # endif
#endif #endif
#if GLIB_CHECK_VERSION(2, 59, 0)
/* nothing */
#else
/* compatibility code for old GLib */
typedef enum {
G_RESOLVER_NAME_LOOKUP_FLAGS_DEFAULT = 0,
G_RESOLVER_NAME_LOOKUP_FLAGS_IPV4_ONLY = 1 << 0,
G_RESOLVER_NAME_LOOKUP_FLAGS_IPV6_ONLY = 1 << 1,
} GResolverNameLookupFlags;
#endif
struct _IPADDR { struct _IPADDR {
unsigned short family; unsigned short family;
struct in6_addr ip; struct in6_addr ip;
}; };
typedef struct {
int refcount;
/* GList<GInetAddress> */
GList *ailist; /* needs to be freed */
GError *error; /* needs to be freed */
} RESOLVED_IP_REC;
/* maxmimum string length of IP address */ /* maxmimum string length of IP address */
#define MAX_IP_LEN INET6_ADDRSTRLEN #define MAX_IP_LEN INET6_ADDRSTRLEN
@ -29,9 +50,7 @@ extern IPADDR ip4_any;
GIOChannel *i_io_channel_new(int handle); GIOChannel *i_io_channel_new(int handle);
/* Returns 1 if IPADDRs are the same. */ /* OTR */
/* Deprecated since it is unused. It will be deleted in a later release. */
int net_ip_compare(IPADDR *ip1, IPADDR *ip2) G_GNUC_DEPRECATED;
int i_io_channel_write_block(GIOChannel *channel, void *data, int len); int i_io_channel_write_block(GIOChannel *channel, void *data, int len);
int i_io_channel_read_block(GIOChannel *channel, void *data, int len); int i_io_channel_read_block(GIOChannel *channel, void *data, int len);
@ -60,18 +79,9 @@ int net_receive(GIOChannel *handle, char *buf, int len);
/* Transmit data, return number of bytes sent, -1 = error */ /* Transmit data, return number of bytes sent, -1 = error */
int net_transmit(GIOChannel *handle, const char *data, int len); int net_transmit(GIOChannel *handle, const char *data, int len);
/* Get IP addresses for host, both IPv4 and IPv6 if possible. /* Get the first IP address for host, both IPv4 and IPv6 if possible. */
If ip->family is 0, the address wasn't found. int net_gethostbyname_first_ips(const char *addr, GResolverNameLookupFlags flags, IPADDR *ip4,
Returns 0 = ok, others = error code for net_gethosterror() */ IPADDR *ip6);
int net_gethostbyname(const char *addr, IPADDR *ip4, IPADDR *ip6);
/* Get name for host, *name should be g_free()'d unless it's NULL.
Return values are the same as with net_gethostbyname() */
int net_gethostbyaddr(IPADDR *ip, char **name);
/* get error of net_gethostname() */
const char *net_gethosterror(int error);
/* return TRUE if host lookup failed because it didn't exist (ie. not
some error with name server) */
int net_hosterror_notfound(int error);
/* Get socket address/port */ /* Get socket address/port */
int net_getsockname(GIOChannel *handle, IPADDR *addr, int *port); int net_getsockname(GIOChannel *handle, IPADDR *addr, int *port);
@ -90,4 +100,7 @@ char *net_getservbyport(int port);
int is_ipv4_address(const char *host); int is_ipv4_address(const char *host);
int is_ipv6_address(const char *host); int is_ipv6_address(const char *host);
void resolved_ip_ref(RESOLVED_IP_REC *iprec);
int resolved_ip_unref(RESOLVED_IP_REC *iprec);
#endif #endif

View file

@ -12,6 +12,7 @@ char *proxy_string, *proxy_string_after, *proxy_password;
unsigned short family; /* 0 = don't care, AF_INET or AF_INET6 */ unsigned short family; /* 0 = don't care, AF_INET or AF_INET6 */
unsigned short chosen_family; /* family actually chosen during name resolution */ unsigned short chosen_family; /* family actually chosen during name resolution */
char *ipaddr;
char *tag; /* try to keep this tag when connected to server */ char *tag; /* try to keep this tag when connected to server */
char *address; char *address;
int port; int port;
@ -44,6 +45,8 @@ unsigned int unix_socket:1; /* Connect using named unix socket */
unsigned int use_tls:1; /* this connection uses TLS */ unsigned int use_tls:1; /* this connection uses TLS */
unsigned int tls_verify:1; unsigned int tls_verify:1;
unsigned int no_connect:1; /* don't connect() at all, it's done by plugin */ unsigned int no_connect:1; /* don't connect() at all, it's done by plugin */
unsigned short last_failed_family; /* #641: if we failed to connect to ipv6, try ipv4 and vice versa */ int last_connected;
int last_failed;
RESOLVED_IP_REC *resolved_host;
char *channels; char *channels;
char *away_reason; char *away_reason;

View file

@ -21,10 +21,8 @@ unsigned int no_reconnect:1; /* Don't reconnect to server */
NET_SENDBUF_REC *handle; NET_SENDBUF_REC *handle;
int readtag; /* input tag */ int readtag; /* input tag */
/* for net_gethostbyname_return() */ GCancellable *connect_cancellable;
GIOChannel *connect_pipe[2];
int connect_tag; int connect_tag;
int connect_pid;
RAWLOG_REC *rawlog; RAWLOG_REC *rawlog;
GHashTable *module_data; GHashTable *module_data;

View file

@ -120,6 +120,10 @@ static int server_reconnect_timeout(void)
if (server->connect_tag != -1) { if (server->connect_tag != -1) {
g_source_remove(server->connect_tag); g_source_remove(server->connect_tag);
server->connect_tag = -1; server->connect_tag = -1;
} else if (server->connect_cancellable != NULL) {
g_cancellable_cancel(server->connect_cancellable);
g_object_unref(server->connect_cancellable);
server->connect_cancellable = NULL;
} }
server->connection_lost = TRUE; server->connection_lost = TRUE;
server_connect_failed(server, "Timeout"); server_connect_failed(server, "Timeout");
@ -168,7 +172,8 @@ server_connect_copy_skeleton(SERVER_CONNECT_REC *src, int connect_info)
server_connect_ref(dest); server_connect_ref(dest);
dest->type = module_get_uniq_id("SERVER CONNECT", 0); dest->type = module_get_uniq_id("SERVER CONNECT", 0);
dest->reconnection = src->reconnection; dest->reconnection = src->reconnection;
dest->last_failed_family = src->last_failed_family; dest->last_connected = src->last_connected;
dest->last_failed = src->last_failed;
dest->proxy = g_strdup(src->proxy); dest->proxy = g_strdup(src->proxy);
dest->proxy_port = src->proxy_port; dest->proxy_port = src->proxy_port;
dest->proxy_string = g_strdup(src->proxy_string); dest->proxy_string = g_strdup(src->proxy_string);
@ -207,6 +212,10 @@ server_connect_copy_skeleton(SERVER_CONNECT_REC *src, int connect_info)
dest->own_ip6 = g_new(IPADDR, 1); dest->own_ip6 = g_new(IPADDR, 1);
memcpy(dest->own_ip6, src->own_ip6, sizeof(IPADDR)); memcpy(dest->own_ip6, src->own_ip6, sizeof(IPADDR));
} }
dest->resolved_host = src->resolved_host;
if (dest->resolved_host != NULL) {
resolved_ip_ref(dest->resolved_host);
}
dest->channels = g_strdup(src->channels); dest->channels = g_strdup(src->channels);
dest->away_reason = g_strdup(src->away_reason); dest->away_reason = g_strdup(src->away_reason);

View file

@ -58,7 +58,8 @@ static void save_ips(IPADDR *ip4, IPADDR *ip6,
static void get_source_host_ip(void) static void get_source_host_ip(void)
{ {
const char *hostname; const char *hostname;
IPADDR ip4, ip6; IPADDR ip4 = { 0 };
IPADDR ip6 = { 0 };
if (source_host_ok) if (source_host_ok)
return; return;
@ -66,25 +67,28 @@ static void get_source_host_ip(void)
/* FIXME: This will block! */ /* FIXME: This will block! */
hostname = settings_get_str("hostname"); hostname = settings_get_str("hostname");
source_host_ok = *hostname != '\0' && source_host_ok = *hostname != '\0' &&
net_gethostbyname(hostname, &ip4, &ip6) == 0; net_gethostbyname_first_ips(hostname, G_RESOLVER_NAME_LOOKUP_FLAGS_DEFAULT,
&ip4, &ip6) == 0;
if (source_host_ok) if (source_host_ok) {
save_ips(&ip4, &ip6, &source_host_ip4, &source_host_ip6); save_ips(&ip4, &ip6, &source_host_ip4, &source_host_ip6);
else { } else {
g_free_and_null(source_host_ip4); g_free_and_null(source_host_ip4);
g_free_and_null(source_host_ip6); g_free_and_null(source_host_ip6);
} }
} }
static void conn_set_ip(SERVER_CONNECT_REC *conn, const char *own_host, static void conn_set_ip(SERVER_CONNECT_REC *conn, const char *own_host,
IPADDR **own_ip4, IPADDR **own_ip6) IPADDR **own_ip4, IPADDR **own_ip6)
{ {
IPADDR ip4, ip6; IPADDR ip4 = { 0 };
IPADDR ip6 = { 0 };
if (*own_ip4 == NULL && *own_ip6 == NULL) { if (*own_ip4 == NULL && *own_ip6 == NULL) {
/* resolve the IP */ /* resolve the IP */
if (net_gethostbyname(own_host, &ip4, &ip6) == 0) if (net_gethostbyname_first_ips(own_host, G_RESOLVER_NAME_LOOKUP_FLAGS_DEFAULT,
save_ips(&ip4, &ip6, own_ip4, own_ip6); &ip4, &ip6) == 0)
save_ips(&ip4, &ip6, own_ip4, own_ip6);
} }
server_connect_own_ip_save(conn, *own_ip4, *own_ip6); server_connect_own_ip_save(conn, *own_ip4, *own_ip6);
@ -305,6 +309,11 @@ static SERVER_CONNECT_REC *create_addr_conn(int chat_type, const char *address,
proto = chat_type >= 0 ? chat_protocol_find_id(chat_type) : proto = chat_type >= 0 ? chat_protocol_find_id(chat_type) :
chat_protocol_get_default(); chat_protocol_get_default();
if (proto == NULL) {
signal_stop();
return NULL;
}
g_return_val_if_fail(proto != NULL, NULL); g_return_val_if_fail(proto != NULL, NULL);
conn = proto->create_server_connect(); conn = proto->create_server_connect();
@ -448,6 +457,7 @@ static SERVER_SETUP_REC *server_setup_read(CONFIG_NODE *node)
{ {
SERVER_SETUP_REC *rec; SERVER_SETUP_REC *rec;
CHATNET_REC *chatnetrec; CHATNET_REC *chatnetrec;
CHAT_PROTOCOL_REC *proto;
char *server, *chatnet, *family; char *server, *chatnet, *family;
int port; int port;
char *value = NULL; char *value = NULL;
@ -468,27 +478,40 @@ static SERVER_SETUP_REC *server_setup_read(CONFIG_NODE *node)
rec = NULL; rec = NULL;
chatnetrec = chatnet == NULL ? NULL : chatnet_find(chatnet); if (chatnet != NULL) {
if (chatnetrec == NULL && chatnet != NULL) { chatnetrec = chatnet_find(chatnet);
/* chat network not found, create it. */ if (chatnetrec != NULL) {
if (chatnet_find_unavailable(chatnet)) { proto = CHAT_PROTOCOL(chatnetrec);
} else {
/* chat network not found, create it. */
if (chatnet_find_unavailable(chatnet)) {
/* no protocols loaded, skip loading servers */
return NULL;
}
proto = chat_protocol_get_default();
chatnetrec = proto->create_chatnet();
chatnetrec->chat_type = chat_protocol_get_default()->id;
chatnetrec->name = g_strdup(chatnet);
chatnet_create(chatnetrec);
}
} else {
chatnetrec = NULL;
proto = chat_protocol_get_default();
if (proto == NULL) {
/* no protocols loaded, skip loading servers */ /* no protocols loaded, skip loading servers */
return NULL; return NULL;
} }
chatnetrec = chat_protocol_get_default()->create_chatnet();
chatnetrec->chat_type = chat_protocol_get_default()->id;
chatnetrec->name = g_strdup(chatnet);
chatnet_create(chatnetrec);
} }
family = config_node_get_str(node, "family", ""); family = config_node_get_str(node, "family", "");
rec = CHAT_PROTOCOL(chatnetrec)->create_server_setup(); rec = proto->create_server_setup();
rec->type = module_get_uniq_id("SERVER SETUP", 0); rec->type = module_get_uniq_id("SERVER SETUP", 0);
rec->chat_type = CHAT_PROTOCOL(chatnetrec)->id; rec->chat_type = proto->id;
rec->chatnet = chatnetrec == NULL ? NULL : g_strdup(chatnetrec->name); rec->chatnet = chatnetrec == NULL ? NULL : g_strdup(chatnetrec->name);
rec->family = g_ascii_strcasecmp(family, "inet6") == 0 ? AF_INET6 : rec->family = g_ascii_strcasecmp(family, "inet6") == 0 ?
(g_ascii_strcasecmp(family, "inet") == 0 ? AF_INET : 0); AF_INET6 :
(g_ascii_strcasecmp(family, "inet") == 0 ? AF_INET : 0);
rec->address = g_strdup(server); rec->address = g_strdup(server);
rec->password = g_strdup(config_node_get_str(node, "password", NULL)); rec->password = g_strdup(config_node_get_str(node, "password", NULL));

View file

@ -51,20 +51,16 @@ void server_connect_failed(SERVER_REC *server, const char *msg)
g_source_remove(server->connect_tag); g_source_remove(server->connect_tag);
server->connect_tag = -1; server->connect_tag = -1;
} }
if (server->connect_cancellable != NULL) {
g_cancellable_cancel(server->connect_cancellable);
g_object_unref(server->connect_cancellable);
server->connect_cancellable = NULL;
}
if (server->handle != NULL) { if (server->handle != NULL) {
net_sendbuffer_destroy(server->handle, TRUE); net_sendbuffer_destroy(server->handle, TRUE);
server->handle = NULL; server->handle = NULL;
} }
if (server->connect_pipe[0] != NULL) {
g_io_channel_shutdown(server->connect_pipe[0], TRUE, NULL);
g_io_channel_unref(server->connect_pipe[0]);
g_io_channel_shutdown(server->connect_pipe[1], TRUE, NULL);
g_io_channel_unref(server->connect_pipe[1]);
server->connect_pipe[0] = NULL;
server->connect_pipe[1] = NULL;
}
server_unref(server); server_unref(server);
} }
@ -134,8 +130,7 @@ static char *server_create_tag(SERVER_CONNECT_REC *conn)
} }
g_free(tag); g_free(tag);
tag = str->str; tag = g_string_free(str, FALSE);
g_string_free(str, FALSE);
return tag; return tag;
} }
@ -157,7 +152,7 @@ static void server_connect_callback_init(SERVER_REC *server, GIOChannel *handle)
error = net_geterror(handle); error = net_geterror(handle);
if (error != 0) { if (error != 0) {
server->connection_lost = TRUE; server->connection_lost = TRUE;
server->connrec->last_failed_family = server->connrec->chosen_family; server->connrec->last_failed = server->connrec->last_connected;
server_connect_failed(server, g_strerror(error)); server_connect_failed(server, g_strerror(error));
return; return;
} }
@ -178,7 +173,7 @@ static void server_connect_callback_init_ssl(SERVER_REC *server, GIOChannel *han
error = irssi_ssl_handshake(handle); error = irssi_ssl_handshake(handle);
if (error == -1) { if (error == -1) {
server->connection_lost = TRUE; server->connection_lost = TRUE;
server->connrec->last_failed_family = server->connrec->chosen_family; server->connrec->last_failed = server->connrec->last_connected;
server_connect_failed(server, NULL); server_connect_failed(server, NULL);
return; return;
} }
@ -212,13 +207,18 @@ static void server_real_connect(SERVER_REC *server, IPADDR *ip,
g_return_if_fail(ip != NULL || unix_socket != NULL); g_return_if_fail(ip != NULL || unix_socket != NULL);
if (ip != NULL) {
server->connrec->chosen_family = ip->family;
net_ip2host(ip, ipaddr);
server->connrec->ipaddr = g_strdup(ipaddr);
}
signal_emit("server connecting", 2, server, ip); signal_emit("server connecting", 2, server, ip);
if (server->connrec->no_connect) if (server->connrec->no_connect)
return; return;
if (ip != NULL) { if (ip != NULL) {
server->connrec->chosen_family = ip->family;
own_ip = IPADDR_IS_V6(ip) ? server->connrec->own_ip6 : server->connrec->own_ip4; own_ip = IPADDR_IS_V6(ip) ? server->connrec->own_ip6 : server->connrec->own_ip4;
port = server->connrec->proxy != NULL ? port = server->connrec->proxy != NULL ?
server->connrec->proxy_port : server->connrec->port; server->connrec->proxy_port : server->connrec->port;
@ -255,12 +255,12 @@ static void server_real_connect(SERVER_REC *server, IPADDR *ip,
server->connection_lost = TRUE; server->connection_lost = TRUE;
if (ip != NULL) { if (ip != NULL) {
server->connrec->last_failed_family = ip->family; server->connrec->last_failed = server->connrec->last_connected;
} }
server_connect_failed(server, errmsg2 ? errmsg2 : errmsg); server_connect_failed(server, errmsg2 ? errmsg2 : errmsg);
g_free(errmsg2); g_free(errmsg2);
} else { } else {
server->connrec->last_failed_family = 0; server->connrec->last_failed = 0;
if (!server->connrec->use_tls) if (!server->connrec->use_tls)
server->handle = net_sendbuffer_create(handle, 0); server->handle = net_sendbuffer_create(handle, 0);
if (server->connrec->use_tls) if (server->connrec->use_tls)
@ -272,48 +272,47 @@ static void server_real_connect(SERVER_REC *server, IPADDR *ip,
} }
} }
static void server_connect_callback_readpipe(SERVER_REC *server) static int server_start_connect_resolve(SERVER_REC *server);
static void server_connect_use_resolved(SERVER_REC *server)
{ {
RESOLVED_IP_REC iprec; IPADDR *ip;
IPADDR *ip;
const char *errormsg; const char *errormsg;
RESOLVED_IP_REC *iprec = server->connrec->resolved_host;
g_source_remove(server->connect_tag); if (iprec->error != NULL) {
server->connect_tag = -1; /* error */
net_gethostbyname_return(server->connect_pipe[0], &iprec);
g_io_channel_shutdown(server->connect_pipe[0], TRUE, NULL);
g_io_channel_unref(server->connect_pipe[0]);
g_io_channel_shutdown(server->connect_pipe[1], TRUE, NULL);
g_io_channel_unref(server->connect_pipe[1]);
server->connect_pipe[0] = NULL;
server->connect_pipe[1] = NULL;
/* figure out if we should use IPv4 or v6 address */
if (iprec.error != 0) {
/* error */
ip = NULL; ip = NULL;
} else if (server->connrec->family == AF_INET) {
/* force IPv4 connection */
ip = iprec.ip4.family == 0 ? NULL : &iprec.ip4;
} else if (server->connrec->family == AF_INET6) {
/* force IPv6 connection */
ip = iprec.ip6.family == 0 ? NULL : &iprec.ip6;
} else { } else {
/* pick the one that was found. if both were found: GList *curr;
1. disprefer the last one that failed int i;
2. prefer ipv4 over ipv6 unless resolve_prefer_ipv6 is set
*/ curr = iprec->ailist;
if (iprec.ip4.family == 0 || i = 0;
(iprec.ip6.family != 0 && while (i < server->connrec->last_failed) {
(server->connrec->last_failed_family == AF_INET || if (curr != NULL) {
(settings_get_bool("resolve_prefer_ipv6") && curr = curr->next;
server->connrec->last_failed_family != AF_INET6)))) { i++;
ip = &iprec.ip6; }
/* curr is different now */
if (curr == NULL) {
resolved_ip_unref(server->connrec->resolved_host);
server->connrec->resolved_host = NULL;
server->connrec->last_failed = 0;
/* retry resolve */
server_start_connect_resolve(server);
return;
}
}
if (curr != NULL) {
GInetAddress *addr;
addr = curr->data;
server->connrec->last_connected = i + 1;
ip = g_new0(IPADDR, 1);
ip->family = g_inet_address_get_family(addr);
memcpy(&ip->ip, g_inet_address_to_bytes(addr), sizeof(ip->ip));
} else { } else {
ip = &iprec.ip4; ip = NULL;
} }
} }
@ -322,28 +321,69 @@ static void server_connect_callback_readpipe(SERVER_REC *server)
server_real_connect(server, ip, NULL); server_real_connect(server, ip, NULL);
errormsg = NULL; errormsg = NULL;
} else { } else {
if (iprec.error == 0 || net_hosterror_notfound(iprec.error)) { if (iprec->error->code == G_RESOLVER_ERROR_NOT_FOUND) {
/* IP wasn't found for the host, don't try to /* IP wasn't found for the host, don't try to
reconnect back to this server */ reconnect back to this server */
server->dns_error = TRUE; server->dns_error = TRUE;
} }
if (iprec.error == 0) { errormsg = iprec->error->message;
/* forced IPv4 or IPv6 address but it wasn't found */ if (errormsg == NULL)
errormsg = server->connrec->family == AF_INET ? errormsg = "Host lookup failed";
"IPv4 address not found for host" :
"IPv6 address not found for host";
} else {
/* gethostbyname() failed */
errormsg = iprec.errorstr != NULL ? iprec.errorstr :
"Host lookup failed";
}
server->connection_lost = TRUE; server->connection_lost = TRUE;
/* clear the error in resolved_host */
server->connrec->resolved_host = NULL;
server_connect_failed(server, errormsg); server_connect_failed(server, errormsg);
resolved_ip_unref(iprec);
} }
g_free(iprec.errorstr); g_free(ip);
}
static void server_connect_callback_resolved(RESOLVED_IP_REC *iprec, SERVER_REC *server)
{
if (server->connect_cancellable != NULL) {
g_object_unref(server->connect_cancellable);
server->connect_cancellable = NULL;
}
if (server->connrec->resolved_host != NULL) {
resolved_ip_unref(server->connrec->resolved_host);
}
server->connrec->resolved_host = iprec;
if (iprec->error == NULL && iprec->ailist == NULL) {
server->connection_lost = TRUE;
server->dns_error = TRUE;
server_connect_failed(server, "Host lookup failed");
} else {
server_connect_use_resolved(server);
}
}
static int server_start_connect_resolve(SERVER_REC *server)
{
const char *connect_address;
GResolverNameLookupFlags net_gethostbyname_flags;
connect_address =
server->connrec->proxy != NULL ? server->connrec->proxy : server->connrec->address;
net_gethostbyname_flags = G_RESOLVER_NAME_LOOKUP_FLAGS_DEFAULT;
if (server->connrec->family == AF_INET) {
net_gethostbyname_flags = G_RESOLVER_NAME_LOOKUP_FLAGS_IPV4_ONLY;
} else if (server->connrec->family == AF_INET6) {
net_gethostbyname_flags = G_RESOLVER_NAME_LOOKUP_FLAGS_IPV6_ONLY;
}
if (server->connrec->resolved_host == NULL) {
server->connect_cancellable = net_gethostbyname_nonblock(
connect_address, net_gethostbyname_flags,
(NetGethostbynameContinuationFunc) server_connect_callback_resolved, server);
return FALSE;
} else {
return TRUE;
}
} }
SERVER_REC *server_connect(SERVER_CONNECT_REC *conn) SERVER_REC *server_connect(SERVER_CONNECT_REC *conn)
@ -395,9 +435,6 @@ void server_connect_init(SERVER_REC *server)
/* starts connecting to server */ /* starts connecting to server */
int server_start_connect(SERVER_REC *server) int server_start_connect(SERVER_REC *server)
{ {
const char *connect_address;
int fd[2];
g_return_val_if_fail(server != NULL, FALSE); g_return_val_if_fail(server != NULL, FALSE);
if (!server->connrec->unix_socket && server->connrec->port <= 0) if (!server->connrec->unix_socket && server->connrec->port <= 0)
return FALSE; return FALSE;
@ -415,30 +452,17 @@ int server_start_connect(SERVER_REC *server)
/* connect with unix socket */ /* connect with unix socket */
server_real_connect(server, NULL, server->connrec->address); server_real_connect(server, NULL, server->connrec->address);
} else { } else {
int already_resolved;
/* resolve host name */ /* resolve host name */
if (pipe(fd) != 0) { already_resolved = server_start_connect_resolve(server);
g_warning("server_connect(): pipe() failed.");
g_free(server->tag);
g_free(server->nick);
return FALSE;
}
server->connect_pipe[0] = i_io_channel_new(fd[0]);
server->connect_pipe[1] = i_io_channel_new(fd[1]);
connect_address = server->connrec->proxy != NULL ?
server->connrec->proxy : server->connrec->address;
server->connect_pid =
net_gethostbyname_nonblock(connect_address,
server->connect_pipe[1], 0);
server->connect_tag =
i_input_add(server->connect_pipe[0], I_INPUT_READ,
(GInputFunction) server_connect_callback_readpipe, server);
server->connect_time = time(NULL); server->connect_time = time(NULL);
lookup_servers = g_slist_append(lookup_servers, server); lookup_servers = g_slist_append(lookup_servers, server);
signal_emit("server looking", 1, server); signal_emit("server looking", 1, server);
if (already_resolved) {
server_connect_use_resolved(server);
}
} }
return TRUE; return TRUE;
} }
@ -477,8 +501,9 @@ void server_disconnect(SERVER_REC *server)
if (server->connect_tag != -1) { if (server->connect_tag != -1) {
/* still connecting to server.. */ /* still connecting to server.. */
if (server->connect_pid != -1) server_connect_failed(server, NULL);
net_disconnect_nonblock(server->connect_pid); return;
} else if (server->connect_cancellable != NULL) {
server_connect_failed(server, NULL); server_connect_failed(server, NULL);
return; return;
} }
@ -637,6 +662,7 @@ void server_connect_unref(SERVER_CONNECT_REC *conn)
g_free_not_null(conn->proxy_string_after); g_free_not_null(conn->proxy_string_after);
g_free_not_null(conn->proxy_password); g_free_not_null(conn->proxy_password);
g_free_not_null(conn->ipaddr);
g_free_not_null(conn->tag); g_free_not_null(conn->tag);
g_free_not_null(conn->address); g_free_not_null(conn->address);
g_free_not_null(conn->chatnet); g_free_not_null(conn->chatnet);
@ -644,6 +670,10 @@ void server_connect_unref(SERVER_CONNECT_REC *conn)
g_free_not_null(conn->own_ip4); g_free_not_null(conn->own_ip4);
g_free_not_null(conn->own_ip6); g_free_not_null(conn->own_ip6);
if (conn->resolved_host != NULL) {
resolved_ip_unref(conn->resolved_host);
}
g_free_not_null(conn->password); g_free_not_null(conn->password);
g_free_not_null(conn->nick); g_free_not_null(conn->nick);
g_free_not_null(conn->username); g_free_not_null(conn->username);
@ -764,7 +794,6 @@ static void sig_chat_protocol_deinit(CHAT_PROTOCOL_REC *proto)
void servers_init(void) void servers_init(void)
{ {
settings_add_bool("server", "resolve_prefer_ipv6", FALSE);
lookup_servers = servers = NULL; lookup_servers = servers = NULL;
signal_add("chat protocol deinit", (SIGNAL_FUNC) sig_chat_protocol_deinit); signal_add("chat protocol deinit", (SIGNAL_FUNC) sig_chat_protocol_deinit);

View file

@ -2,6 +2,7 @@
#define IRSSI_CORE_SERVERS_H #define IRSSI_CORE_SERVERS_H
#include <irssi/src/core/modules.h> #include <irssi/src/core/modules.h>
#include <irssi/src/core/network.h>
/* Returns SERVER_REC if it's server, NULL if it isn't. */ /* Returns SERVER_REC if it's server, NULL if it isn't. */
#define SERVER(server) \ #define SERVER(server) \

View file

@ -26,6 +26,7 @@
#include <irssi/src/core/net-sendbuffer.h> #include <irssi/src/core/net-sendbuffer.h>
#include <irssi/src/core/pidwait.h> #include <irssi/src/core/pidwait.h>
#include <irssi/src/lib-config/iconfig.h> #include <irssi/src/lib-config/iconfig.h>
#include <irssi/src/core/misc.h>
#include <irssi/src/core/chat-protocols.h> #include <irssi/src/core/chat-protocols.h>
#include <irssi/src/core/servers.h> #include <irssi/src/core/servers.h>
@ -59,13 +60,19 @@ void session_upgrade(void)
static void cmd_upgrade(const char *data) static void cmd_upgrade(const char *data)
{ {
CONFIG_REC *session; CONFIG_REC *session;
char *session_file, *str; char *session_file, *str, *name;
char *binary; char *binary;
if (*data == '\0') if (*data == '\0')
data = irssi_binary; name = irssi_binary;
else
name = convert_home(data);
if ((binary = g_find_program_in_path(data)) == NULL) binary = g_find_program_in_path(name);
if (name != irssi_binary)
g_free(name);
if (binary == NULL)
cmd_return_error(CMDERR_PROGRAM_NOT_FOUND); cmd_return_error(CMDERR_PROGRAM_NOT_FOUND);
/* save the session */ /* save the session */

View file

@ -673,18 +673,6 @@ GSList *settings_get_sorted(void)
return list; return list;
} }
void sig_term(int n)
{
/* if we get SIGTERM after this, just die instead of coming back here. */
signal(SIGTERM, SIG_DFL);
/* quit from all servers too.. */
signal_emit("command quit", 1, "");
/* and die */
raise(SIGTERM);
}
/* Yes, this is my own stupid checksum generator, some "real" algorithm /* Yes, this is my own stupid checksum generator, some "real" algorithm
would be nice but would just take more space without much real benefit */ would be nice but would just take more space without much real benefit */
static unsigned int file_checksum(const char *fname) static unsigned int file_checksum(const char *fname)
@ -805,8 +793,6 @@ static void init_configfile(void)
signal_emit("gui dialog", 2, "error", str); signal_emit("gui dialog", 2, "error", str);
g_free(str); g_free(str);
} }
signal(SIGTERM, sig_term);
} }
int settings_reread(const char *fname) int settings_reread(const char *fname)

View file

@ -88,8 +88,7 @@ static char *get_argument(char **cmd, char **arglist)
} }
if (str->len > 0) g_string_truncate(str, str->len-1); if (str->len > 0) g_string_truncate(str, str->len-1);
ret = str->str; ret = g_string_free_and_steal(str);
g_string_free(str, FALSE);
return ret; return ret;
} }
@ -412,8 +411,7 @@ char *get_alignment(const char *text, int align, int flags, char pad)
} }
} }
ret = str->str; ret = g_string_free_and_steal(str);
g_string_free(str, FALSE);
return ret; return ret;
} }
@ -604,8 +602,7 @@ char *parse_special_string(const char *cmd, SERVER_REC *server, void *item,
} }
g_strfreev(arglist); g_strfreev(arglist);
ret = str->str; ret = g_string_free_and_steal(str);
g_string_free(str, FALSE);
return ret; return ret;
} }

View file

@ -261,7 +261,12 @@ static const char *command_history_prev_int(WINDOW_REC *window, const char *text
if (*text != '\0' && if (*text != '\0' &&
(pos == NULL || g_strcmp0(((HISTORY_ENTRY_REC *)pos->data)->text, text) != 0)) { (pos == NULL || g_strcmp0(((HISTORY_ENTRY_REC *)pos->data)->text, text) != 0)) {
/* save the old entry to history */ /* save the old entry to history */
command_history_add(history, text); if (pos != NULL && settings_get_bool("command_history_editable")) {
history_entry_destroy(pos->data);
pos->data = history_entry_new(history, text);
} else {
command_history_add(history, text);
}
} }
return history->pos == NULL ? text : ((HISTORY_ENTRY_REC *)history->pos->data)->text; return history->pos == NULL ? text : ((HISTORY_ENTRY_REC *)history->pos->data)->text;
@ -292,7 +297,12 @@ static const char *command_history_next_int(WINDOW_REC *window, const char *text
if (*text != '\0' && if (*text != '\0' &&
(pos == NULL || g_strcmp0(((HISTORY_ENTRY_REC *)pos->data)->text, text) != 0)) { (pos == NULL || g_strcmp0(((HISTORY_ENTRY_REC *)pos->data)->text, text) != 0)) {
/* save the old entry to history */ /* save the old entry to history */
command_history_add(history, text); if (pos != NULL && settings_get_bool("command_history_editable")) {
history_entry_destroy(pos->data);
pos->data = history_entry_new(history, text);
} else {
command_history_add(history, text);
}
} }
return history->pos == NULL ? "" : ((HISTORY_ENTRY_REC *)history->pos->data)->text; return history->pos == NULL ? "" : ((HISTORY_ENTRY_REC *)history->pos->data)->text;
} }
@ -467,6 +477,7 @@ void command_history_init(void)
{ {
settings_add_int("history", "max_command_history", 100); settings_add_int("history", "max_command_history", 100);
settings_add_bool("history", "window_history", FALSE); settings_add_bool("history", "window_history", FALSE);
settings_add_bool("history", "command_history_editable", FALSE);
special_history_func_set(special_history_func); special_history_func_set(special_history_func);

View file

@ -111,8 +111,7 @@ char *auto_word_complete(const char *line, int *pos)
*pos = startpos+strlen(replace); *pos = startpos+strlen(replace);
g_string_insert(result, startpos, replace); g_string_insert(result, startpos, replace);
ret = result->str; ret = g_string_free_and_steal(result);
g_string_free(result, FALSE);
} }
g_free(word); g_free(word);
@ -290,8 +289,7 @@ char *word_complete(WINDOW_REC *window, const char *line, int *pos, int erase, i
g_free_not_null(last_line); g_free_not_null(last_line);
last_line = g_strdup(result->str); last_line = g_strdup(result->str);
ret = result->str; ret = g_string_free_and_steal(result);
g_string_free(result, FALSE);
/* free the data */ /* free the data */
g_free(data); g_free(data);

View file

@ -166,7 +166,7 @@ void fe_common_core_init(void)
settings_add_bool("lookandfeel", "use_msgs_window", FALSE); settings_add_bool("lookandfeel", "use_msgs_window", FALSE);
g_get_charset(&str); g_get_charset(&str);
settings_add_str("lookandfeel", "term_charset", str); settings_add_str("lookandfeel", "term_charset", str);
settings_add_str("lookandfeel", "glib_log_domains", "all"); settings_add_str("lookandfeel", "glib_log_domains", "all -glib-gio:debug");
themes_init(); themes_init();
theme_register(fecommon_core_formats); theme_register(fecommon_core_formats);
@ -258,13 +258,19 @@ void fe_common_core_deinit(void)
g_log_set_default_handler(logger_old, NULL); g_log_set_default_handler(logger_old, NULL);
} }
static gboolean glib_domain_wanted(const char *domain) static gboolean glib_domain_wanted(const char *domain, const char *level)
{ {
const char *domains; const char *domains;
char *c, *cur; char *c, *cur;
int len = 0; int len = 0;
int print_it = 0; /* -1 for exclude, 0 for undecided, 1 for include */ int print_it = 0; /* -1 for exclude, 0 for undecided, 1 for include */
int incl; int incl;
char *domainlevel, *alllevel, *starlevel, *domainstar;
domainlevel = g_strdup_printf("%s:%s", domain, level);
alllevel = g_strdup_printf("all:%s", level);
starlevel = g_strdup_printf("*:%s", level);
domainstar = g_strdup_printf("%s:*", domain);
/* Go through each item in glib_log_domains setting to determine whether /* Go through each item in glib_log_domains setting to determine whether
* or not we want to print message from this domain */ * or not we want to print message from this domain */
@ -287,8 +293,10 @@ static gboolean glib_domain_wanted(const char *domain)
} }
/* If we got a valid item, process it */ /* If we got a valid item, process it */
if (len > 0 && (!strncmp(domain, c, len) || !strncasecmp("all", c, len) || if (len > 0 && (!strncasecmp(domain, c, len) || !strncasecmp("all", c, len) ||
!strncmp("*", c, len))) !strncmp("*", c, len) || !strncasecmp(domainstar, c, len) ||
!strncasecmp(domainlevel, c, len) ||
!strncasecmp(alllevel, c, len) || !strncasecmp(starlevel, c, len)))
print_it = incl; print_it = incl;
/* Go past any spaces towards the next item */ /* Go past any spaces towards the next item */
@ -300,6 +308,11 @@ static gboolean glib_domain_wanted(const char *domain)
len = 0; len = 0;
} while (*c != '\0' && print_it != -1); } while (*c != '\0' && print_it != -1);
g_free(domainlevel);
g_free(alllevel);
g_free(starlevel);
g_free(domainstar);
return (print_it == 1); return (print_it == 1);
} }
@ -333,7 +346,7 @@ static void i_log_func(const char *log_domain, GLogLevelFlags log_level, const c
domain = (log_domain ? log_domain : "default"); domain = (log_domain ? log_domain : "default");
/* Only print the message if we decided to */ /* Only print the message if we decided to */
if (!glib_domain_wanted(domain)) if (!glib_domain_wanted(domain, reason))
return; return;
if (windows == NULL) if (windows == NULL)

View file

@ -57,18 +57,19 @@ static int skip_next_printtext;
static char *log_theme_name; static char *log_theme_name;
static char **autolog_ignore_targets; static char **autolog_ignore_targets;
static GTimeZone *utc;
static char *log_colorizer_strip(const char *str) static char *log_colorizer_strip(const char *str)
{ {
return strip_codes(str); return strip_codes(str);
} }
static void log_add_targets(LOG_REC *log, const char *targets, const char *tag) static void log_add_targets(LOG_REC *log, const char *targets, const char *tag)
{ {
char **tmp, **items; char **tmp, **items;
g_return_if_fail(log != NULL); g_return_if_fail(log != NULL);
g_return_if_fail(targets != NULL); g_return_if_fail(targets != NULL);
items = g_strsplit(targets, " ", -1); items = g_strsplit(targets, " ", -1);
@ -83,18 +84,18 @@ static void log_add_targets(LOG_REC *log, const char *targets, const char *tag)
<fname> [<levels>] */ <fname> [<levels>] */
static void cmd_log_open(const char *data) static void cmd_log_open(const char *data)
{ {
SERVER_REC *server; SERVER_REC *server;
GHashTable *optlist; GHashTable *optlist;
char *targetarg, *fname, *levels, *servertag; char *targetarg, *fname, *levels, *servertag;
void *free_arg; void *free_arg;
char window[MAX_INT_STRLEN]; char window[MAX_INT_STRLEN];
LOG_REC *log; LOG_REC *log;
int level; int level;
if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST | if (!cmd_get_params(data, &free_arg,
PARAM_FLAG_UNKNOWN_OPTIONS | PARAM_FLAG_OPTIONS | 2 | PARAM_FLAG_GETREST | PARAM_FLAG_UNKNOWN_OPTIONS |
PARAM_FLAG_STRIP_TRAILING_WS, "log open", &optlist, PARAM_FLAG_OPTIONS | PARAM_FLAG_STRIP_TRAILING_WS,
&fname, &levels)) "log open", &optlist, &fname, &levels))
return; return;
if (*fname == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); if (*fname == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
@ -112,8 +113,7 @@ static void cmd_log_open(const char *data)
ltoa(window, active_win->refnum); ltoa(window, active_win->refnum);
targetarg = window; targetarg = window;
} }
log_item_add(log, LOG_ITEM_WINDOW_REFNUM, targetarg, log_item_add(log, LOG_ITEM_WINDOW_REFNUM, targetarg, servertag);
servertag);
} else { } else {
targetarg = g_hash_table_lookup(optlist, "targets"); targetarg = g_hash_table_lookup(optlist, "targets");
if (targetarg != NULL && *targetarg != '\0') if (targetarg != NULL && *targetarg != '\0')
@ -133,14 +133,13 @@ static void cmd_log_open(const char *data)
if (log->handle == -1 && g_hash_table_lookup(optlist, "noopen") == NULL) { if (log->handle == -1 && g_hash_table_lookup(optlist, "noopen") == NULL) {
/* start logging */ /* start logging */
if (log_start_logging(log)) { if (log_start_logging(log)) {
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, TXT_LOG_OPENED, fname);
TXT_LOG_OPENED, fname);
} else { } else {
log_close(log); log_close(log);
} }
} }
cmd_params_free(free_arg); cmd_params_free(free_arg);
} }
static LOG_REC *log_find_from_data(const char *data) static LOG_REC *log_find_from_data(const char *data)
@ -209,14 +208,13 @@ static char *log_items_get_list(LOG_REC *log)
for (tmp = log->items; tmp != NULL; tmp = tmp->next) { for (tmp = log->items; tmp != NULL; tmp = tmp->next) {
rec = tmp->data; rec = tmp->data;
g_string_append_printf(str, "%s, ", rec->name); g_string_append_printf(str, "%s, ", rec->name);
} }
g_string_truncate(str, str->len-2); g_string_truncate(str, str->len-2);
if(rec->servertag != NULL) if(rec->servertag != NULL)
g_string_append_printf(str, " (%s)", rec->servertag); g_string_append_printf(str, " (%s)", rec->servertag);
ret = str->str; ret = g_string_free_and_steal(str);
g_string_free(str, FALSE);
return ret; return ret;
} }
@ -231,13 +229,11 @@ static void cmd_log_list(void)
LOG_REC *rec = tmp->data; LOG_REC *rec = tmp->data;
levelstr = bits2level(rec->level); levelstr = bits2level(rec->level);
items = rec->items == NULL ? NULL : items = rec->items == NULL ? NULL : log_items_get_list(rec);
log_items_get_list(rec);
printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, TXT_LOG_LIST, printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, TXT_LOG_LIST, index, rec->fname,
index, rec->fname, items != NULL ? items : "", items != NULL ? items : "", levelstr, rec->autoopen ? " -autoopen" : "",
levelstr, rec->autoopen ? " -autoopen" : "", rec->handle != -1 ? " active" : "");
rec->handle != -1 ? " active" : "");
g_free_not_null(items); g_free_not_null(items);
g_free(levelstr); g_free(levelstr);
@ -253,8 +249,8 @@ static void cmd_log(const char *data, SERVER_REC *server, void *item)
command_runsub("log", data, server, item); command_runsub("log", data, server, item);
} }
static LOG_REC *logs_find_item(int type, const char *item, static LOG_REC *logs_find_item(int type, const char *item, const char *servertag,
const char *servertag, LOG_ITEM_REC **ret_item) LOG_ITEM_REC **ret_item)
{ {
LOG_ITEM_REC *logitem; LOG_ITEM_REC *logitem;
GSList *tmp; GSList *tmp;
@ -284,17 +280,17 @@ static void cmd_window_log(const char *data)
if (!cmd_get_params(data, &free_arg, 2, &set, &fname)) if (!cmd_get_params(data, &free_arg, 2, &set, &fname))
return; return;
ltoa(window, active_win->refnum); ltoa(window, active_win->refnum);
log = logs_find_item(LOG_ITEM_WINDOW_REFNUM, window, NULL, NULL); log = logs_find_item(LOG_ITEM_WINDOW_REFNUM, window, NULL, NULL);
open_log = close_log = FALSE; open_log = close_log = FALSE;
if (g_ascii_strcasecmp(set, "ON") == 0) if (g_ascii_strcasecmp(set, "ON") == 0)
open_log = TRUE; open_log = TRUE;
else if (g_ascii_strcasecmp(set, "OFF") == 0) { else if (g_ascii_strcasecmp(set, "OFF") == 0) {
close_log = TRUE; close_log = TRUE;
} else if (g_ascii_strcasecmp(set, "TOGGLE") == 0) { } else if (g_ascii_strcasecmp(set, "TOGGLE") == 0) {
open_log = log == NULL; open_log = log == NULL;
close_log = log != NULL; close_log = log != NULL;
} else { } else {
printformat(NULL, NULL, MSGLEVEL_CLIENTERROR, TXT_NOT_TOGGLE); printformat(NULL, NULL, MSGLEVEL_CLIENTERROR, TXT_NOT_TOGGLE);
cmd_params_free(free_arg); cmd_params_free(free_arg);
@ -309,7 +305,7 @@ static void cmd_window_log(const char *data)
active_win->name != NULL ? "" : window); active_win->name != NULL ? "" : window);
log = log_create_rec(fname, MSGLEVEL_ALL); log = log_create_rec(fname, MSGLEVEL_ALL);
log->colorizer = log_colorizer_strip; log->colorizer = log_colorizer_strip;
log_item_add(log, LOG_ITEM_WINDOW_REFNUM, window, NULL); log_item_add(log, LOG_ITEM_WINDOW_REFNUM, window, NULL);
log_update(log); log_update(log);
g_free(fname); g_free(fname);
} }
@ -322,7 +318,7 @@ static void cmd_window_log(const char *data)
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, TXT_LOG_CLOSED, log->fname); printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, TXT_LOG_CLOSED, log->fname);
} }
cmd_params_free(free_arg); cmd_params_free(free_arg);
} }
/* Create log file entry to window, but don't start logging */ /* Create log file entry to window, but don't start logging */
@ -331,21 +327,34 @@ static void cmd_window_logfile(const char *data)
{ {
LOG_REC *log; LOG_REC *log;
char window[MAX_INT_STRLEN]; char window[MAX_INT_STRLEN];
void *free_arg;
char *fname;
ltoa(window, active_win->refnum); if (!cmd_get_params(data, &free_arg, 1, &fname)) {
return;
}
if (!fname || strlen(fname) == 0) {
cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
}
ltoa(window, active_win->refnum);
log = logs_find_item(LOG_ITEM_WINDOW_REFNUM, window, NULL, NULL); log = logs_find_item(LOG_ITEM_WINDOW_REFNUM, window, NULL, NULL);
if (log != NULL) { if (log != NULL) {
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, TXT_WINDOWLOG_FILE_LOGGING); printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, TXT_WINDOWLOG_FILE_LOGGING);
cmd_params_free(free_arg);
return; return;
} }
log = log_create_rec(data, MSGLEVEL_ALL); log = log_create_rec(fname, MSGLEVEL_ALL);
log->colorizer = log_colorizer_strip; log->colorizer = log_colorizer_strip;
log_item_add(log, LOG_ITEM_WINDOW_REFNUM, window, NULL); log_item_add(log, LOG_ITEM_WINDOW_REFNUM, window, NULL);
log_update(log); log_update(log);
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, TXT_WINDOWLOG_FILE, data); printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, TXT_WINDOWLOG_FILE, data);
cmd_params_free(free_arg);
} }
/* window's refnum changed - update the logs to log the new window refnum */ /* window's refnum changed - update the logs to log the new window refnum */
@ -355,7 +364,7 @@ static void sig_window_refnum_changed(WINDOW_REC *window, gpointer old_refnum)
LOG_REC *log; LOG_REC *log;
LOG_ITEM_REC *item; LOG_ITEM_REC *item;
ltoa(winnum, GPOINTER_TO_INT(old_refnum)); ltoa(winnum, GPOINTER_TO_INT(old_refnum));
log = logs_find_item(LOG_ITEM_WINDOW_REFNUM, winnum, NULL, &item); log = logs_find_item(LOG_ITEM_WINDOW_REFNUM, winnum, NULL, &item);
if (log != NULL) { if (log != NULL) {
@ -368,7 +377,7 @@ static void sig_window_refnum_changed(WINDOW_REC *window, gpointer old_refnum)
static void sig_server_disconnected(SERVER_REC *server) static void sig_server_disconnected(SERVER_REC *server)
{ {
LOG_ITEM_REC *logitem; LOG_ITEM_REC *logitem;
GSList *tmp, *next; GSList *tmp, *next;
for (tmp = logs; tmp != NULL; tmp = next) { for (tmp = logs; tmp != NULL; tmp = next) {
@ -376,13 +385,13 @@ static void sig_server_disconnected(SERVER_REC *server)
next = tmp->next; next = tmp->next;
if (!log->temp || log->items == NULL) if (!log->temp || log->items == NULL)
continue; continue;
logitem = log->items->data; logitem = log->items->data;
if (logitem->type == LOG_ITEM_TARGET && if (logitem->type == LOG_ITEM_TARGET && logitem->servertag != NULL &&
logitem->servertag != NULL &&
g_ascii_strcasecmp(logitem->servertag, server->tag) == 0 && g_ascii_strcasecmp(logitem->servertag, server->tag) == 0 &&
server_ischannel(server, logitem->name)) /* kludge again.. so we won't close dcc chats */ server_ischannel(
server, logitem->name)) /* kludge again.. so we won't close dcc chats */
log_close(log); log_close(log);
} }
} }
@ -414,15 +423,14 @@ static char *escape_target(const char *target)
*p++ = *target; *p++ = *target;
} }
target++; target++;
} }
*p = '\0'; *p = '\0';
return str; return str;
} }
static void autolog_open(SERVER_REC *server, const char *server_tag, static void autolog_open(SERVER_REC *server, const char *server_tag, const char *target)
const char *target)
{ {
LOG_REC *log; LOG_REC *log;
char *fname, *dir, *fixed_target, *params; char *fname, *dir, *fixed_target, *params;
@ -443,17 +451,16 @@ static void autolog_open(SERVER_REC *server, const char *server_tag,
if (CHAT_PROTOCOL(server)->case_insensitive) if (CHAT_PROTOCOL(server)->case_insensitive)
ascii_strdown(fixed_target); ascii_strdown(fixed_target);
/* $0 = target, $1 = server tag */ /* $0 = target, $1 = server tag */
params = g_strconcat(fixed_target, " ", server_tag, NULL); params = g_strconcat(fixed_target, " ", server_tag, NULL);
g_free(fixed_target); g_free(fixed_target);
fname = parse_special_string(autolog_path, server, NULL, fname = parse_special_string(autolog_path, server, NULL, params, NULL, 0);
params, NULL, 0);
g_free(params); g_free(params);
if (log_find(fname) == NULL) { if (log_find(fname) == NULL) {
log = log_create_rec(fname, autolog_level); log = log_create_rec(fname, autolog_level);
if (!settings_get_bool("autolog_colors")) if (!settings_get_bool("autolog_colors"))
log->colorizer = log_colorizer_strip; log->colorizer = log_colorizer_strip;
log_item_add(log, LOG_ITEM_TARGET, target, server_tag); log_item_add(log, LOG_ITEM_TARGET, target, server_tag);
@ -484,8 +491,8 @@ static void autolog_open_check(TEXT_DEST_REC *dest)
we're parting the channel with /WINDOW CLOSE.. Maybe a small we're parting the channel with /WINDOW CLOSE.. Maybe a small
timeout would be nice instead of immediately closing the log file timeout would be nice instead of immediately closing the log file
after "window item destroyed" */ after "window item destroyed" */
if (level == MSGLEVEL_PARTS || if (level == MSGLEVEL_PARTS || (autolog_level & level) == 0 || target == NULL ||
(autolog_level & level) == 0 || target == NULL || *target == '\0') *target == '\0')
return; return;
deftarget = server ? server->nick : "unknown"; deftarget = server ? server->nick : "unknown";
@ -495,8 +502,7 @@ static void autolog_open_check(TEXT_DEST_REC *dest)
&& channel_setup_find(target, server_tag) == NULL) && channel_setup_find(target, server_tag) == NULL)
return; return;
if (autolog_ignore_targets != NULL && if (autolog_ignore_targets != NULL && strarray_find_dest(autolog_ignore_targets, dest))
strarray_find_dest(autolog_ignore_targets, dest))
return; return;
if (target != NULL) if (target != NULL)
@ -512,8 +518,7 @@ static void log_single_line(WINDOW_REC *window, const char *server_tag, const ch
if (window != NULL) { if (window != NULL) {
/* save to log created with /WINDOW LOG */ /* save to log created with /WINDOW LOG */
ltoa(windownum, window->refnum); ltoa(windownum, window->refnum);
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, t); log_write_rec(log, text, level, t);
} }
@ -542,7 +547,7 @@ static void log_line(TEXT_DEST_REC *dest, const char *text)
char *val; char *val;
if ((val = g_hash_table_lookup(dest->meta, "time")) != NULL) { if ((val = g_hash_table_lookup(dest->meta, "time")) != NULL) {
GDateTime *time; GDateTime *time;
if ((time = g_date_time_new_from_iso8601(val, NULL)) != NULL) { if ((time = g_date_time_new_from_iso8601(val, utc)) != NULL) {
t = g_date_time_to_unix(time); t = g_date_time_to_unix(time);
g_date_time_unref(time); g_date_time_unref(time);
} }
@ -553,8 +558,7 @@ static void log_line(TEXT_DEST_REC *dest, const char *text)
g_strfreev(lines); g_strfreev(lines);
} }
static void sig_printtext(TEXT_DEST_REC *dest, const char *text, static void sig_printtext(TEXT_DEST_REC *dest, const char *text, const char *stripped)
const char *stripped)
{ {
if (skip_next_printtext) { if (skip_next_printtext) {
skip_next_printtext = FALSE; skip_next_printtext = FALSE;
@ -564,8 +568,8 @@ static void sig_printtext(TEXT_DEST_REC *dest, const char *text,
log_line(dest, text); log_line(dest, text);
} }
static void sig_print_format(THEME_REC *theme, const char *module, static void sig_print_format(THEME_REC *theme, const char *module, TEXT_DEST_REC *dest,
TEXT_DEST_REC *dest, void *formatnum, char **args) void *formatnum, char **args)
{ {
char *str, *linestart, *tmp; char *str, *linestart, *tmp;
@ -579,14 +583,14 @@ static void sig_print_format(THEME_REC *theme, const char *module,
if (theme == log_theme) if (theme == log_theme)
return; return;
str = format_get_text_theme_charargs(log_theme, module, dest, str = format_get_text_theme_charargs(log_theme, module, dest, GPOINTER_TO_INT(formatnum),
GPOINTER_TO_INT(formatnum), args); args);
if (str != NULL && *str != '\0') { if (str != NULL && *str != '\0') {
skip_next_printtext = TRUE; skip_next_printtext = TRUE;
/* add the line start format */ /* add the line start format */
linestart = format_get_level_tag(log_theme, dest); linestart = format_get_level_tag(log_theme, dest);
tmp = str; tmp = str;
str = format_add_linestart(tmp, linestart); str = format_add_linestart(tmp, linestart);
g_free_not_null(linestart); g_free_not_null(linestart);
g_free(tmp); g_free(tmp);
@ -605,14 +609,14 @@ static int sig_autoremove(void)
GSList *tmp, *next; GSList *tmp, *next;
time_t removetime; time_t removetime;
removetime = time(NULL)-AUTOLOG_INACTIVITY_CLOSE; removetime = time(NULL) - AUTOLOG_INACTIVITY_CLOSE;
for (tmp = logs; tmp != NULL; tmp = next) { for (tmp = logs; tmp != NULL; tmp = next) {
LOG_REC *log = tmp->data; LOG_REC *log = tmp->data;
next = tmp->next; next = tmp->next;
if (!log->temp || log->last > removetime || log->items == NULL) if (!log->temp || log->last > removetime || log->items == NULL)
continue; continue;
/* Close only logs with private messages */ /* Close only logs with private messages */
logitem = log->items->data; logitem = log->items->data;
@ -620,8 +624,8 @@ static int sig_autoremove(void)
continue; continue;
server = server_find_tag(logitem->servertag); server = server_find_tag(logitem->servertag);
if (logitem->type == LOG_ITEM_TARGET && if (logitem->type == LOG_ITEM_TARGET && server != NULL &&
server != NULL && !server_ischannel(server, logitem->name)) !server_ischannel(server, logitem->name))
log_close(log); log_close(log);
} }
return 1; return 1;
@ -632,43 +636,40 @@ static void sig_window_item_remove(WINDOW_REC *window, WI_ITEM_REC *item)
LOG_REC *log; LOG_REC *log;
log = logs_find_item(LOG_ITEM_TARGET, item->visible_name, log = logs_find_item(LOG_ITEM_TARGET, item->visible_name,
item->server == NULL ? NULL : item->server == NULL ? NULL : item->server->tag, NULL);
item->server->tag, NULL);
if (log != NULL && log->temp) if (log != NULL && log->temp)
log_close(log); log_close(log);
} }
static void sig_log_locked(LOG_REC *log) static void sig_log_locked(LOG_REC *log)
{ {
printformat(NULL, NULL, MSGLEVEL_CLIENTERROR, printformat(NULL, NULL, MSGLEVEL_CLIENTERROR, TXT_LOG_LOCKED, log->real_fname);
TXT_LOG_LOCKED, log->real_fname);
} }
static void sig_log_create_failed(LOG_REC *log) static void sig_log_create_failed(LOG_REC *log)
{ {
printformat(NULL, NULL, MSGLEVEL_CLIENTERROR, printformat(NULL, NULL, MSGLEVEL_CLIENTERROR, TXT_LOG_CREATE_FAILED, log->real_fname,
TXT_LOG_CREATE_FAILED, g_strerror(errno));
log->real_fname, g_strerror(errno));
} }
static void sig_log_new(LOG_REC *log) static void sig_log_new(LOG_REC *log)
{ {
if (!settings_get_bool("awaylog_colors") && if (!settings_get_bool("awaylog_colors") &&
g_strcmp0(log->fname, settings_get_str("awaylog_file")) == 0) g_strcmp0(log->fname, settings_get_str("awaylog_file")) == 0)
log->colorizer = log_colorizer_strip; log->colorizer = log_colorizer_strip;
} }
static void sig_log_config_read(LOG_REC *log, CONFIG_NODE *node) static void sig_log_config_read(LOG_REC *log, CONFIG_NODE *node)
{ {
if (!config_node_get_bool(node, "colors", FALSE)) if (!config_node_get_bool(node, "colors", FALSE))
log->colorizer = log_colorizer_strip; log->colorizer = log_colorizer_strip;
} }
static void sig_log_config_save(LOG_REC *log, CONFIG_NODE *node) static void sig_log_config_save(LOG_REC *log, CONFIG_NODE *node)
{ {
if (log->colorizer == NULL) if (log->colorizer == NULL)
iconfig_node_set_bool(node, "colors", TRUE); iconfig_node_set_bool(node, "colors", TRUE);
else else
iconfig_node_set_str(node, "colors", NULL); iconfig_node_set_str(node, "colors", NULL);
} }
@ -685,7 +686,7 @@ static void sig_awaylog_show(LOG_REC *log, gpointer pmsgs, gpointer pfilepos)
else { else {
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, TXT_LOG_AWAY_MSGS, log->real_fname, msgs); printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, TXT_LOG_AWAY_MSGS, log->real_fname, msgs);
str = g_strdup_printf("\"%s\" %d", log->real_fname, filepos); str = g_strdup_printf("\"%s\" %d", log->real_fname, filepos);
signal_emit("command cat", 1, str); signal_emit("command cat", 1, str);
g_free(str); g_free(str);
} }
@ -744,15 +745,16 @@ void fe_log_init(void)
{ {
autoremove_tag = g_timeout_add(60000, (GSourceFunc) sig_autoremove, NULL); autoremove_tag = g_timeout_add(60000, (GSourceFunc) sig_autoremove, NULL);
skip_next_printtext = FALSE; skip_next_printtext = FALSE;
utc = g_time_zone_new_utc();
settings_add_bool("log", "awaylog_colors", TRUE); settings_add_bool("log", "awaylog_colors", TRUE);
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_choice("log", "log_server_time", 2, "off;on;auto"); settings_add_choice("log", "log_server_time", 2, "off;on;auto");
settings_add_str("log", "autolog_path", "~/irclogs/$tag/$0.log"); 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", "");
autolog_level = 0; autolog_level = 0;
@ -811,6 +813,7 @@ void fe_log_deinit(void)
if (autolog_ignore_targets != NULL) if (autolog_ignore_targets != NULL)
g_strfreev(autolog_ignore_targets); g_strfreev(autolog_ignore_targets);
g_time_zone_unref(utc);
g_free_not_null(autolog_path); g_free_not_null(autolog_path);
g_free_not_null(log_theme_name); g_free_not_null(log_theme_name);
} }

View file

@ -133,8 +133,7 @@ char *expand_emphasis(WI_ITEM_REC *item, const char *text)
} }
} }
ret = str->str; ret = g_string_free_and_steal(str);
g_string_free(str, FALSE);
return ret; return ret;
} }
@ -730,9 +729,8 @@ static void sig_nicklist_new(CHANNEL_REC *channel, NICK_REC *nick)
n++; n++;
} while (printnick_exists(firstnick, nick, newnick->str)); } while (printnick_exists(firstnick, nick, newnick->str));
g_hash_table_insert(printnicks, nick, newnick->str); g_hash_table_insert(printnicks, nick, g_string_free_and_steal(newnick));
g_string_free(newnick, FALSE); g_free(nickhost);
g_free(nickhost);
} }
static void sig_nicklist_remove(CHANNEL_REC *channel, NICK_REC *nick) static void sig_nicklist_remove(CHANNEL_REC *channel, NICK_REC *nick)

View file

@ -101,8 +101,14 @@ static SERVER_SETUP_REC *create_server_setup(GHashTable *optlist)
} }
} }
server = rec->create_server_setup(); if (rec == NULL) {
server->chat_type = rec->id; /* no protocols loaded, bail out */
signal_emit("chat protocol unknown", 1, "(none)");
return NULL;
}
server = rec->create_server_setup();
server->chat_type = rec->id;
server->tls_verify = TRUE; server->tls_verify = TRUE;
return server; return server;
} }

View file

@ -616,8 +616,7 @@ char *format_string_expand(const char *text, int *flags)
text++; text++;
} }
ret = out->str; ret = g_string_free_and_steal(out);
g_string_free(out, FALSE);
return ret; return ret;
} }
@ -792,8 +791,7 @@ static char *format_get_text_args(TEXT_DEST_REC *dest,
text++; text++;
} }
ret = out->str; ret = g_string_free_and_steal(out);
g_string_free(out, FALSE);
return ret; return ret;
} }
@ -888,8 +886,7 @@ char *format_add_linestart(const char *text, const char *linestart)
text++; text++;
} }
ret = str->str; ret = g_string_free_and_steal(str);
g_string_free(str, FALSE);
return ret; return ret;
} }
@ -913,8 +910,7 @@ char *format_add_lineend(const char *text, const char *linestart)
} }
g_string_append(str, linestart); g_string_append(str, linestart);
ret = str->str; ret = g_string_free_and_steal(str);
g_string_free(str, FALSE);
return ret; return ret;
} }
@ -1279,7 +1275,7 @@ static void get_mirc_color(const char **str, int *fg_ret, int *bg_ret)
#define IS_COLOR_CODE(c) \ #define IS_COLOR_CODE(c) \
((c) == 2 || (c) == 3 || (c) == 4 || (c) == 6 || (c) == 7 || \ ((c) == 2 || (c) == 3 || (c) == 4 || (c) == 6 || (c) == 7 || \
(c) == 15 || (c) == 22 || (c) == 27 || (c) == 29 || (c) == 31) (c) == 15 || (c) == 17 || (c) == 22 || (c) == 27 || (c) == 29 || (c) == 31)
/* 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. */
@ -1550,9 +1546,17 @@ void format_send_as_gui_flags(TEXT_DEST_REC *dest, const char *text, SIGNAL_FUNC
break; break;
case 15: case 15:
/* remove all styling */ /* remove all styling */
fgcolor = theme->default_color; if (!hide_text_style) {
bgcolor = -1; if (!hide_colors) {
flags &= GUI_PRINT_FLAG_INDENT|GUI_PRINT_FLAG_MONOSPACE; fgcolor = theme->default_color;
bgcolor = -1;
}
flags &= GUI_PRINT_FLAG_INDENT | GUI_PRINT_FLAG_MONOSPACE;
}
break;
case 17:
if (!hide_text_style)
flags ^= GUI_PRINT_FLAG_MONOSPACE;
break; break;
case 22: case 22:
/* reverse */ /* reverse */

View file

@ -469,8 +469,7 @@ static void sig_print_text(TEXT_DEST_REC *dest, const char *text,
} }
g_string_append(str, text + pos); g_string_append(str, text + pos);
newstr = str->str; newstr = g_string_free_and_steal(str);
g_string_free(str, FALSE);
format_dest_meta_stash(dest, "hilight-start", format_dest_meta_stash(dest, "hilight-start",
tmp = g_strdup_printf("%d", hilight_start)); tmp = g_strdup_printf("%d", hilight_start));
@ -626,7 +625,7 @@ static void cmd_hilight_show(void)
} }
/* SYNTAX: HILIGHT [-nick | -word | -line] [-mask | -full | -matchcase | -regexp] /* SYNTAX: HILIGHT [-nick | -word | -line] [-mask | -full | -matchcase | -regexp]
[-color <color>] [-actcolor <color>] [-level <level>] [-color <color>] [-actcolor <color>] [-level <level>] [-priority <number>]
[-network <network>] [-channels <channels>] <text> */ [-network <network>] [-channels <channels>] <text> */
static void cmd_hilight(const char *data) static void cmd_hilight(const char *data)
{ {

View file

@ -3,7 +3,7 @@
if have_capsicum if have_capsicum
fe_common_core_capsicum_source = files('fe-capsicum.c') fe_common_core_capsicum_source = files('fe-capsicum.c')
else else
fe_common_core_capsicum_source = [] fe_common_core_capsicum_source = [ ]
endif endif
fe_common_core_sources = [ fe_common_core_sources = [
@ -43,10 +43,11 @@ fe_common_core_sources = [
+ [ + [
default_theme_h, default_theme_h,
irssi_version_h, irssi_version_h,
] ],
] ]
libfe_common_core_a = static_library('fe_common_core', libfe_common_core_a = static_library(
'fe_common_core',
fe_common_core_sources, fe_common_core_sources,
include_directories : rootinc, include_directories : rootinc,
implicit_include_directories : false, implicit_include_directories : false,
@ -54,10 +55,12 @@ libfe_common_core_a = static_library('fe_common_core',
def_helpdir, def_helpdir,
def_themesdir, def_themesdir,
], ],
dependencies : dep) dependencies : dep,
)
if want_fuzzer if want_fuzzer
libfuzzer_fe_common_core_a = static_library('fuzzer_fe_common_core', libfuzzer_fe_common_core_a = static_library(
'fuzzer_fe_common_core',
fe_common_core_sources, fe_common_core_sources,
include_directories : rootinc, include_directories : rootinc,
implicit_include_directories : false, implicit_include_directories : false,
@ -66,7 +69,8 @@ if want_fuzzer
def_themesdir, def_themesdir,
def_suppress_printf_fallback, def_suppress_printf_fallback,
], ],
dependencies : dep) dependencies : dep,
)
endif endif
install_headers( install_headers(
@ -96,4 +100,5 @@ install_headers(
'window-items.h', 'window-items.h',
'windows-layout.h', 'windows-layout.h',
), ),
subdir : incdir / 'src' / 'fe-common' / 'core') subdir : incdir / 'src' / 'fe-common' / 'core',
)

View file

@ -39,9 +39,9 @@ FORMAT_REC fecommon_core_formats[] = {
{ "set_server_sticky", "Window's server set sticky", 1, { 0 } }, { "set_server_sticky", "Window's server set sticky", 1, { 0 } },
{ "unset_server_sticky", "Window's server isn't sticky anymore", 0 }, { "unset_server_sticky", "Window's server isn't sticky anymore", 0 },
{ "window_name_not_unique", "Window names must be unique", 1, { 0 } }, { "window_name_not_unique", "Window names must be unique", 1, { 0 } },
{ "window_level", "Window level is now $0", 1, { 0 } }, { "window_level", "Window level is $0", 1, { 0 } },
{ "window_set_immortal", "Window is now immortal", 0 }, { "window_set_immortal", "Window is immortal", 0 },
{ "window_unset_immortal", "Window isn't immortal anymore", 0 }, { "window_unset_immortal", "Window isn't immortal", 0 },
{ "window_immortal_error", "Window is immortal, if you really want to close it, say /WINDOW IMMORTAL OFF", 0 }, { "window_immortal_error", "Window is immortal, if you really want to close it, say /WINDOW IMMORTAL OFF", 0 },
{ "windowlist_header", "%#Ref Name Active item Server Level", 0 }, { "windowlist_header", "%#Ref Name Active item Server Level", 0 },
{ "windowlist_line", "%#$[4]0 %|$[20]1 $[15]2 $[15]3 $4", 5, { 1, 0, 0, 0, 0 } }, { "windowlist_line", "%#$[4]0 %|$[20]1 $[15]2 $[15]3 $4", 5, { 1, 0, 0, 0, 0 } },

View file

@ -24,6 +24,7 @@
#include <irssi/src/core/signals.h> #include <irssi/src/core/signals.h>
#include <irssi/src/core/commands.h> #include <irssi/src/core/commands.h>
#include <irssi/src/core/settings.h> #include <irssi/src/core/settings.h>
#include <irssi/src/core/misc.h>
#include <irssi/src/core/levels.h> #include <irssi/src/core/levels.h>
#include <irssi/src/core/servers.h> #include <irssi/src/core/servers.h>
@ -240,8 +241,7 @@ static char *printtext_get_args(TEXT_DEST_REC *dest, const char *str,
} }
} }
ret = out->str; ret = g_string_free_and_steal(out);
g_string_free(out, FALSE);
return ret; return ret;
} }
@ -270,8 +270,7 @@ static char *printtext_expand_formats(const char *str, int *flags)
} }
} }
ret = out->str; ret = g_string_free_and_steal(out);
g_string_free(out, FALSE);
return ret; return ret;
} }

View file

@ -395,9 +395,8 @@ char *theme_format_expand_get(THEME_REC *theme, const char **format)
(*format)++; (*format)++;
} }
ret = str->str; ret = g_string_free_and_steal(str);
g_string_free(str, FALSE); return ret;
return ret;
} }
static char *theme_format_expand_data_rec(THEME_REC *theme, const char **format, static char *theme_format_expand_data_rec(THEME_REC *theme, const char **format,
@ -496,8 +495,7 @@ static char *theme_format_expand_abstract(THEME_REC *theme, const char **formatp
p++; p++;
} }
g_free(ret); g_free(ret);
abstract = str->str; abstract = g_string_free_and_steal(str);
g_string_free(str, FALSE);
/* abstract may itself contain abstracts or replaces */ /* abstract may itself contain abstracts or replaces */
p = abstract; p = abstract;
@ -568,15 +566,14 @@ static char *theme_format_expand_data_rec(THEME_REC *theme, const char **format,
} }
} }
/* save the last color */ /* save the last color */
if (save_last_fg != NULL) if (save_last_fg != NULL)
*save_last_fg = last_fg; *save_last_fg = last_fg;
if (save_last_bg != NULL) if (save_last_bg != NULL)
*save_last_bg = last_bg; *save_last_bg = last_bg;
ret = str->str; ret = g_string_free_and_steal(str);
g_string_free(str, FALSE); return ret;
return ret;
} }
/* expand the data part in {abstract data} */ /* expand the data part in {abstract data} */
@ -645,9 +642,8 @@ static char *theme_format_compress_colors(THEME_REC *theme, const char *format)
} }
} }
ret = str->str; ret = g_string_free_and_steal(str);
g_string_free(str, FALSE); return ret;
return ret;
} }
char *theme_format_expand(THEME_REC *theme, const char *format) char *theme_format_expand(THEME_REC *theme, const char *format)

View file

@ -400,7 +400,7 @@ static void cmd_window_previous(void)
window_set_active(window_find_refnum(num)); window_set_active(window_find_refnum(num));
} }
/* SYNTAX: WINDOW LEVEL [<level>] */ /* SYNTAX: WINDOW LEVEL [<levels>] */
static void cmd_window_level(const char *data) static void cmd_window_level(const char *data)
{ {
char *level; char *level;

View file

@ -1,6 +1,7 @@
# this file is part of irssi # this file is part of irssi
libfe_irc_dcc_a = static_library('fe_irc_dcc', libfe_irc_dcc_a = static_library(
'fe_irc_dcc',
files( files(
'fe-dcc-chat-messages.c', 'fe-dcc-chat-messages.c',
'fe-dcc-chat.c', 'fe-dcc-chat.c',
@ -16,12 +17,17 @@ libfe_irc_dcc_a = static_library('fe_irc_dcc',
def_helpdir, def_helpdir,
def_sysconfdir, def_sysconfdir,
], ],
dependencies : dep) dependencies : dep,
shared_module('fe_irc_dcc', )
shared_library(
'fe_irc_dcc',
name_suffix : module_suffix,
install : true, install : true,
install_dir : moduledir, install_dir : moduledir,
link_with : dl_cross_irc_dcc, link_with : dl_cross_irc_dcc + dl_cross_irc_core + dl_cross_irssi_main,
link_whole : libfe_irc_dcc_a) link_whole : libfe_irc_dcc_a,
override_options : [ 'b_lundef=false' ],
)
install_headers( install_headers(
files( files(
@ -29,4 +35,5 @@ install_headers(
'module-formats.h', 'module-formats.h',
'module.h', 'module.h',
), ),
subdir : incdir / 'src' / 'fe-common' / 'irc' / 'dcc') subdir : incdir / 'src' / 'fe-common' / 'irc' / 'dcc',
)

View file

@ -119,11 +119,10 @@ static void ctcp_default_reply(IRC_SERVER_REC *server, const char *data,
g_free(ctcp); g_free(ctcp);
} }
static void ctcp_ping_reply(IRC_SERVER_REC *server, const char *data, static void ctcp_ping_reply(IRC_SERVER_REC *server, const char *data, const char *nick,
const char *nick, const char *addr, const char *addr, const char *target)
const char *target)
{ {
gint64 tv, tv2; gint64 tv, tv2 = 0;
long usecs; long usecs;
g_return_if_fail(data != NULL); g_return_if_fail(data != NULL);
@ -141,8 +140,9 @@ static void ctcp_ping_reply(IRC_SERVER_REC *server, const char *data,
tv2 += tv * G_TIME_SPAN_SECOND; tv2 += tv * G_TIME_SPAN_SECOND;
tv = g_get_real_time(); tv = g_get_real_time();
usecs = tv - tv2; usecs = tv - tv2;
printformat(server, server_ischannel(SERVER(server), target) ? target : nick, MSGLEVEL_CTCPS, printformat(server, server_ischannel(SERVER(server), target) ? target : nick,
IRCTXT_CTCP_PING_REPLY, nick, usecs / G_TIME_SPAN_SECOND, usecs % G_TIME_SPAN_SECOND); MSGLEVEL_CTCPS, IRCTXT_CTCP_PING_REPLY, nick, usecs / G_TIME_SPAN_SECOND,
usecs % G_TIME_SPAN_SECOND);
} }
void fe_ctcp_init(void) void fe_ctcp_init(void)

View file

@ -35,6 +35,7 @@
#include <irssi/src/fe-common/core/printtext.h> #include <irssi/src/fe-common/core/printtext.h>
#include <irssi/src/fe-common/core/fe-channels.h> #include <irssi/src/fe-common/core/fe-channels.h>
#include <irssi/src/fe-common/irc/fe-irc-server.h> #include <irssi/src/fe-common/irc/fe-irc-server.h>
#include <irssi/src/fe-common/irc/fe-irc-channels.h>
static void print_event_received(IRC_SERVER_REC *server, const char *data, static void print_event_received(IRC_SERVER_REC *server, const char *data,
const char *nick, int target_param); const char *nick, int target_param);
@ -143,45 +144,74 @@ static void event_ban_list(IRC_SERVER_REC *server, const char *data)
IRC_CHANNEL_REC *chanrec; IRC_CHANNEL_REC *chanrec;
BAN_REC *banrec; BAN_REC *banrec;
const char *channel; const char *channel;
char *params, *ban, *setby, *tims; char *params, *ban, *setby, *tims, *timestr, *ago;
long secs;
g_return_if_fail(data != NULL); g_return_if_fail(data != NULL);
params = event_get_params(data, 5, NULL, &channel, params = event_get_params(data, 5, NULL, &channel,
&ban, &setby, &tims); &ban, &setby, &tims);
secs = *tims == '\0' ? 0 : timestr = my_asctime((time_t) atoll(tims));
(long) (time(NULL) - atol(tims)); ago = time_ago((time_t) atoll(tims));
chanrec = irc_channel_find(server, channel); chanrec = irc_channel_find(server, channel);
banrec = chanrec == NULL ? NULL : banlist_find(chanrec->banlist, ban); banrec = chanrec == NULL ? NULL : banlist_find(chanrec->banlist, ban);
channel = get_visible_target(server, channel); channel = get_visible_target(server, channel);
printformat(server, channel, MSGLEVEL_CRAP, printformat(server, channel, MSGLEVEL_CRAP,
*setby == '\0' ? IRCTXT_BANLIST : IRCTXT_BANLIST_LONG, *setby == '\0' ? IRCTXT_BANLIST : IRCTXT_BANLIST_LONG,
banrec == NULL ? 0 : g_slist_index(chanrec->banlist, banrec)+1, banrec == NULL ? 0 : g_slist_index(chanrec->banlist, banrec) + 1, channel, ban,
channel, ban, setby, secs); setby, ago, timestr);
g_free(timestr);
g_free(params); g_free(params);
} }
static void event_eban_list(IRC_SERVER_REC *server, const char *data) static void event_eban_list(IRC_SERVER_REC *server, const char *data)
{ {
const char *channel; const char *channel;
char *params, *ban, *setby, *tims; char *params, *ban, *setby, *tims, *timestr, *ago;
long secs;
g_return_if_fail(data != NULL); g_return_if_fail(data != NULL);
params = event_get_params(data, 5, NULL, &channel, params = event_get_params(data, 5, NULL, &channel,
&ban, &setby, &tims); &ban, &setby, &tims);
secs = *tims == '\0' ? 0 : timestr = my_asctime((time_t) atoll(tims));
(long) (time(NULL) - atol(tims)); ago = time_ago((time_t) atoll(tims));
channel = get_visible_target(server, channel); channel = get_visible_target(server, channel);
printformat(server, channel, MSGLEVEL_CRAP, printformat(server, channel, MSGLEVEL_CRAP,
*setby == '\0' ? IRCTXT_EBANLIST : IRCTXT_EBANLIST_LONG, *setby == '\0' ? IRCTXT_EBANLIST : IRCTXT_EBANLIST_LONG, channel, ban, setby,
channel, ban, setby, secs); timestr, ago);
g_free(timestr);
g_free(params);
}
static void do_quiet_list(IRC_SERVER_REC *server, const char *channel, char *ban, char *setby,
char *tims)
{
char *timestr, *ago;
timestr = my_asctime((time_t) atoll(tims));
ago = time_ago((time_t) atoll(tims));
channel = get_visible_target(server, channel);
printformat(server, channel, MSGLEVEL_CRAP,
*setby == '\0' ? IRCTXT_QUIETLIST : IRCTXT_QUIETLIST_LONG, channel, ban, setby,
ago, timestr);
g_free(timestr);
}
static void event_quiet_list(IRC_SERVER_REC *server, const char *data)
{
const char *channel;
char *params, *ban, *setby, *tims;
g_return_if_fail(data != NULL);
params = event_get_params(data, 6, NULL, &channel, NULL, &ban, &setby, &tims);
do_quiet_list(server, channel, ban, setby, tims);
g_free(params); g_free(params);
} }
@ -214,20 +244,21 @@ static void event_accept_list(IRC_SERVER_REC *server, const char *data)
static void event_invite_list(IRC_SERVER_REC *server, const char *data) static void event_invite_list(IRC_SERVER_REC *server, const char *data)
{ {
const char *channel; const char *channel;
char *params, *invite, *setby, *tims; char *params, *invite, *setby, *tims, *timestr, *ago;
long secs;
g_return_if_fail(data != NULL); g_return_if_fail(data != NULL);
params = event_get_params(data, 5, NULL, &channel, &invite, params = event_get_params(data, 5, NULL, &channel, &invite,
&setby, &tims); &setby, &tims);
secs = *tims == '\0' ? 0 : timestr = my_asctime((time_t) atoll(tims));
(long) (time(NULL) - atol(tims)); ago = time_ago((time_t) atoll(tims));
channel = get_visible_target(server, channel); channel = get_visible_target(server, channel);
printformat(server, channel, MSGLEVEL_CRAP, printformat(server, channel, MSGLEVEL_CRAP,
*setby == '\0' ? IRCTXT_INVITELIST : IRCTXT_INVITELIST_LONG, *setby == '\0' ? IRCTXT_INVITELIST : IRCTXT_INVITELIST_LONG, channel, invite,
channel, invite, setby, secs); setby, timestr, ago);
g_free(timestr);
g_free(params); g_free(params);
} }
@ -695,6 +726,26 @@ static void event_target_received(IRC_SERVER_REC *server, const char *data,
print_event_received(server, data, nick, TRUE); print_event_received(server, data, nick, TRUE);
} }
static void event_hybrid_quiet_list(IRC_SERVER_REC *server, const char *data)
{
const char *channel;
char *params, *ban, *setby, *tims;
g_return_if_fail(data != NULL);
params = event_get_params(data, 5, NULL, &channel, &ban, &setby, &tims);
if (*tims == '\0') {
/* probably not a quiet list */
event_target_received(server, data, NULL);
return;
}
do_quiet_list(server, channel, ban, setby, tims);
g_free(params);
}
static void event_motd(IRC_SERVER_REC *server, const char *data, static void event_motd(IRC_SERVER_REC *server, const char *data,
const char *nick, const char *addr) const char *nick, const char *addr)
{ {
@ -727,6 +778,8 @@ void fe_events_numeric_init(void)
signal_add("event 281", (SIGNAL_FUNC) event_accept_list); signal_add("event 281", (SIGNAL_FUNC) event_accept_list);
signal_add("event 367", (SIGNAL_FUNC) event_ban_list); signal_add("event 367", (SIGNAL_FUNC) event_ban_list);
signal_add("event 348", (SIGNAL_FUNC) event_eban_list); signal_add("event 348", (SIGNAL_FUNC) event_eban_list);
signal_add("event 728", (SIGNAL_FUNC) event_quiet_list);
signal_add("event 344", (SIGNAL_FUNC) event_hybrid_quiet_list); /* used by ircd-hybrid */
signal_add("event 346", (SIGNAL_FUNC) event_invite_list); signal_add("event 346", (SIGNAL_FUNC) event_invite_list);
signal_add("event 433", (SIGNAL_FUNC) event_nick_in_use); signal_add("event 433", (SIGNAL_FUNC) event_nick_in_use);
signal_add("event 332", (SIGNAL_FUNC) event_topic_get); signal_add("event 332", (SIGNAL_FUNC) event_topic_get);
@ -785,8 +838,7 @@ void fe_events_numeric_init(void)
signal_add("event 470", (SIGNAL_FUNC) event_received); signal_add("event 470", (SIGNAL_FUNC) event_received);
signal_add("event 479", (SIGNAL_FUNC) event_received); signal_add("event 479", (SIGNAL_FUNC) event_received);
signal_add("event 344", (SIGNAL_FUNC) event_target_received); /* reop list */ signal_add("event 345", (SIGNAL_FUNC) event_target_received); /* end of reop list/hybrid quiet list */
signal_add("event 345", (SIGNAL_FUNC) event_target_received); /* end of reop list */
signal_add("event 347", (SIGNAL_FUNC) event_target_received); /* end of invite exception list */ signal_add("event 347", (SIGNAL_FUNC) event_target_received); /* end of invite exception list */
signal_add("event 349", (SIGNAL_FUNC) event_target_received); /* end of ban exception list */ signal_add("event 349", (SIGNAL_FUNC) event_target_received); /* end of ban exception list */
signal_add("event 368", (SIGNAL_FUNC) event_target_received); /* end of ban list */ signal_add("event 368", (SIGNAL_FUNC) event_target_received); /* end of ban list */
@ -804,7 +856,6 @@ void fe_events_numeric_init(void)
signal_add("event 506", (SIGNAL_FUNC) event_target_received); /* cannot send (+R) */ signal_add("event 506", (SIGNAL_FUNC) event_target_received); /* cannot send (+R) */
signal_add("event 716", (SIGNAL_FUNC) event_target_received); /* cannot /msg (+g) */ signal_add("event 716", (SIGNAL_FUNC) event_target_received); /* cannot /msg (+g) */
signal_add("event 717", (SIGNAL_FUNC) event_target_received); /* +g notified */ signal_add("event 717", (SIGNAL_FUNC) event_target_received); /* +g notified */
signal_add("event 728", (SIGNAL_FUNC) event_target_received); /* quiet (or other) list */
signal_add("event 729", (SIGNAL_FUNC) event_target_received); /* end of quiet (or other) list */ signal_add("event 729", (SIGNAL_FUNC) event_target_received); /* end of quiet (or other) list */
/* clang-format on */ /* clang-format on */
} }
@ -825,6 +876,8 @@ void fe_events_numeric_deinit(void)
signal_remove("event 281", (SIGNAL_FUNC) event_accept_list); signal_remove("event 281", (SIGNAL_FUNC) event_accept_list);
signal_remove("event 367", (SIGNAL_FUNC) event_ban_list); signal_remove("event 367", (SIGNAL_FUNC) event_ban_list);
signal_remove("event 348", (SIGNAL_FUNC) event_eban_list); signal_remove("event 348", (SIGNAL_FUNC) event_eban_list);
signal_remove("event 728", (SIGNAL_FUNC) event_quiet_list);
signal_remove("event 344", (SIGNAL_FUNC) event_hybrid_quiet_list);
signal_remove("event 346", (SIGNAL_FUNC) event_invite_list); signal_remove("event 346", (SIGNAL_FUNC) event_invite_list);
signal_remove("event 433", (SIGNAL_FUNC) event_nick_in_use); signal_remove("event 433", (SIGNAL_FUNC) event_nick_in_use);
signal_remove("event 332", (SIGNAL_FUNC) event_topic_get); signal_remove("event 332", (SIGNAL_FUNC) event_topic_get);
@ -879,7 +932,6 @@ void fe_events_numeric_deinit(void)
signal_remove("event 470", (SIGNAL_FUNC) event_received); signal_remove("event 470", (SIGNAL_FUNC) event_received);
signal_remove("event 479", (SIGNAL_FUNC) event_received); signal_remove("event 479", (SIGNAL_FUNC) event_received);
signal_remove("event 344", (SIGNAL_FUNC) event_target_received);
signal_remove("event 345", (SIGNAL_FUNC) event_target_received); signal_remove("event 345", (SIGNAL_FUNC) event_target_received);
signal_remove("event 347", (SIGNAL_FUNC) event_target_received); signal_remove("event 347", (SIGNAL_FUNC) event_target_received);
signal_remove("event 349", (SIGNAL_FUNC) event_target_received); signal_remove("event 349", (SIGNAL_FUNC) event_target_received);
@ -898,6 +950,5 @@ void fe_events_numeric_deinit(void)
signal_remove("event 506", (SIGNAL_FUNC) event_target_received); signal_remove("event 506", (SIGNAL_FUNC) event_target_received);
signal_remove("event 716", (SIGNAL_FUNC) event_target_received); signal_remove("event 716", (SIGNAL_FUNC) event_target_received);
signal_remove("event 717", (SIGNAL_FUNC) event_target_received); signal_remove("event 717", (SIGNAL_FUNC) event_target_received);
signal_remove("event 728", (SIGNAL_FUNC) event_target_received);
signal_remove("event 729", (SIGNAL_FUNC) event_target_received); signal_remove("event 729", (SIGNAL_FUNC) event_target_received);
} }

View file

@ -73,6 +73,38 @@ const char *fe_channel_skip_prefix(IRC_SERVER_REC *server, const char *target)
return target; return target;
} }
/* Get time elapsed since an event */
char *time_ago(time_t seconds)
{
static char ret[128];
long unsigned years, weeks, days, hours, minutes;
seconds = time(NULL) - seconds;
years = seconds / (86400 * 365);
seconds %= (86400 * 365);
weeks = seconds / 604800;
days = (seconds / 86400) % 7;
hours = (seconds / 3600) % 24;
minutes = (seconds / 60) % 60;
seconds %= 60;
if (years)
snprintf(ret, sizeof(ret), "%luy %luw %lud", years, weeks, days);
else if (weeks)
snprintf(ret, sizeof(ret), "%luw %lud %luh", weeks, days, hours);
else if (days)
snprintf(ret, sizeof(ret), "%lud %luh %lum", days, hours, minutes);
else if (hours)
snprintf(ret, sizeof(ret), "%luh %lum", hours, minutes);
else if (minutes)
snprintf(ret, sizeof(ret), "%lum %lus", minutes, (long unsigned) seconds);
else
snprintf(ret, sizeof(ret), "%lus", (long unsigned) seconds);
return ret;
}
static void sig_channel_rejoin(SERVER_REC *server, REJOIN_REC *rec) static void sig_channel_rejoin(SERVER_REC *server, REJOIN_REC *rec)
{ {
g_return_if_fail(rec != NULL); g_return_if_fail(rec != NULL);

View file

@ -3,6 +3,7 @@
int fe_channel_is_opchannel(IRC_SERVER_REC *server, const char *target); int fe_channel_is_opchannel(IRC_SERVER_REC *server, const char *target);
const char *fe_channel_skip_prefix(IRC_SERVER_REC *server, const char *target); const char *fe_channel_skip_prefix(IRC_SERVER_REC *server, const char *target);
char *time_ago(time_t seconds);
void fe_irc_channels_init(void); void fe_irc_channels_init(void);
void fe_irc_channels_deinit(void); void fe_irc_channels_deinit(void);

View file

@ -39,6 +39,7 @@
#include <irssi/src/fe-common/core/window-items.h> #include <irssi/src/fe-common/core/window-items.h>
#include <irssi/src/fe-common/core/printtext.h> #include <irssi/src/fe-common/core/printtext.h>
#include <irssi/src/fe-common/core/keyboard.h> #include <irssi/src/fe-common/core/keyboard.h>
#include <irssi/src/fe-common/irc/fe-irc-channels.h>
/* SYNTAX: ME <message> */ /* SYNTAX: ME <message> */
static void cmd_me(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *item) static void cmd_me(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *item)
@ -224,15 +225,16 @@ static void bans_show_channel(IRC_CHANNEL_REC *channel, IRC_SERVER_REC *server)
/* show bans.. */ /* show bans.. */
counter = 1; counter = 1;
for (tmp = channel->banlist; tmp != NULL; tmp = tmp->next) { for (tmp = channel->banlist; tmp != NULL; tmp = tmp->next) {
char *timestr, *ago;
BAN_REC *rec = tmp->data; BAN_REC *rec = tmp->data;
timestr = my_asctime(rec->time);
ago = time_ago(rec->time);
printformat(server, channel->visible_name, MSGLEVEL_CRAP, printformat(server, channel->visible_name, MSGLEVEL_CRAP,
(rec->setby == NULL || *rec->setby == '\0') ? (rec->setby == NULL || *rec->setby == '\0') ? IRCTXT_BANLIST :
IRCTXT_BANLIST : IRCTXT_BANLIST_LONG, IRCTXT_BANLIST_LONG,
counter, channel->visible_name, counter, channel->visible_name, rec->ban, rec->setby, ago, timestr);
rec->ban, rec->setby, counter++;
(int) (time(NULL)-rec->time));
counter++;
} }
} }

View file

@ -173,7 +173,7 @@ static void sig_message_own_action(IRC_SERVER_REC *server, const char *msg,
oldtarget = target; oldtarget = target;
target = fe_channel_skip_prefix(IRC_SERVER(server), target); target = fe_channel_skip_prefix(IRC_SERVER(server), target);
if (server_ischannel(SERVER(server), target)) if (server_ischannel(SERVER(server), target))
item = irc_channel_find(server, target); item = channel_find(SERVER(server), target);
else else
item = irc_query_find(server, target); item = irc_query_find(server, target);
@ -208,7 +208,7 @@ static void sig_message_irc_action(IRC_SERVER_REC *server, const char *msg,
return; return;
if (server_ischannel(SERVER(server), target)) { if (server_ischannel(SERVER(server), target)) {
item = irc_channel_find(server, target); item = channel_find(SERVER(server), target);
} else { } else {
own = (!g_strcmp0(nick, server->nick)); own = (!g_strcmp0(nick, server->nick));
item = privmsg_get_query(SERVER(server), own ? target : nick, FALSE, level); item = privmsg_get_query(SERVER(server), own ? target : nick, FALSE, level);

View file

@ -51,7 +51,7 @@ const char *get_visible_target(IRC_SERVER_REC *server, const char *target)
return target; return target;
} }
/* SYNTAX: SERVER ADD|MODIFY [-4 | -6] [-tls_cert <cert>] [-tls_pkey <pkey>] /* SYNTAX: SERVER ADD|MODIFY [-4 | -6] [-cap | -nocap] [-tls_cert <cert>] [-tls_pkey <pkey>]
[-tls_pass <password>] [-tls_verify] [-tls_cafile <cafile>] [-tls_pass <password>] [-tls_verify] [-tls_cafile <cafile>]
[-tls_capath <capath>] [-tls_ciphers <list>] [-tls | -notls] [-tls_capath <capath>] [-tls_ciphers <list>] [-tls | -notls]
[-starttls | -nostarttls | -disallow_starttls | -nodisallow_starttls] [-starttls | -nostarttls | -disallow_starttls | -nodisallow_starttls]

View file

@ -137,7 +137,7 @@ static void get_server_splits(void *key, NETSPLIT_REC *split,
g_string_append_printf(chanrec->nicks, "%s, ", split->nick); g_string_append_printf(chanrec->nicks, "%s, ", split->nick);
if (chanrec->nick_count == netsplit_max_nicks) if (chanrec->nick_count == netsplit_max_nicks)
chanrec->maxnickpos = chanrec->nicks->len; chanrec->maxnickpos = chanrec->nicks->len - 2;
} }
} }
} }

View file

@ -1,6 +1,7 @@
# this file is part of irssi # this file is part of irssi
libfe_common_irc_a = static_library('fe_common_irc', libfe_common_irc_a = static_library(
'fe_common_irc',
files( files(
'fe-cap.c', 'fe-cap.c',
'fe-common-irc.c', 'fe-common-irc.c',
@ -27,12 +28,17 @@ libfe_common_irc_a = static_library('fe_common_irc',
def_helpdir, def_helpdir,
def_themesdir, def_themesdir,
], ],
dependencies : dep) dependencies : dep,
shared_module('fe_common_irc', )
shared_library(
'fe_common_irc',
name_suffix : module_suffix,
install : true, install : true,
install_dir : moduledir, install_dir : moduledir,
link_with : dl_cross_irc_core, link_with : dl_cross_irc_core + dl_cross_irssi_main,
link_whole : libfe_common_irc_a) link_whole : libfe_common_irc_a,
override_options : [ 'b_lundef=false' ],
)
install_headers( install_headers(
files( files(
@ -41,7 +47,8 @@ install_headers(
'module-formats.h', 'module-formats.h',
'module.h', 'module.h',
), ),
subdir : incdir / 'src' / 'fe-common' / 'irc') subdir : incdir / 'src' / 'fe-common' / 'irc',
)
subdir('dcc') subdir('dcc')
subdir('notifylist') subdir('notifylist')

View file

@ -81,12 +81,14 @@ FORMAT_REC fecommon_irc_formats[] = {
{ "bantype", "Ban type changed to {channel $0}", 1, { 0 } }, { "bantype", "Ban type changed to {channel $0}", 1, { 0 } },
{ "no_bans", "No bans in channel {channel $0}", 1, { 0 } }, { "no_bans", "No bans in channel {channel $0}", 1, { 0 } },
{ "banlist", "$0 - {channel $1}: ban {ban $2}", 3, { 1, 0, 0 } }, { "banlist", "$0 - {channel $1}: ban {ban $2}", 3, { 1, 0, 0 } },
{ "banlist_long", "$0 - {channel $1}: ban {ban $2} {comment by {nick $3}, $4 secs ago}", 5, { 1, 0, 0, 0, 1 } }, { "banlist_long", "$0 - {channel $1}: ban {ban $2} {comment by {nick $3}, on $5 ($4 ago)}", 6, { 1, 0, 0, 0, 0, 0 } },
{ "quietlist", "{channel $0}: quiet {ban $1}", 2, { 0, 0 } },
{ "quietlist_long", "{channel $0}: quiet {ban $1} {comment by {nick $2}, on $4 ($3 ago)}", 5, { 0, 0, 0, 0, 0 } },
{ "ebanlist", "{channel $0}: ban exception {ban $1}", 2, { 0, 0 } }, { "ebanlist", "{channel $0}: ban exception {ban $1}", 2, { 0, 0 } },
{ "ebanlist_long", "{channel $0}: ban exception {ban $1} {comment by {nick $2}, $3 secs ago}", 4, { 0, 0, 0, 1 } }, { "ebanlist_long", "{channel $0}: ban exception {ban $1} {comment by {nick $2}, on $4 ($3 ago)}", 5, { 0, 0, 0, 0, 0 } },
{ "no_invitelist", "Invite list is empty in channel {channel $0}", 1, { 0 } }, { "no_invitelist", "Invite list is empty in channel {channel $0}", 1, { 0 } },
{ "invitelist", "{channel $0}: invite {ban $1}", 2, { 0, 0 } }, { "invitelist", "{channel $0}: invite {ban $1}", 2, { 0, 0 } },
{ "invitelist_long", "{channel $0}: invite {ban $1} {comment by {nick $2}, $3 secs ago}", 4, { 0, 0, 0, 1 } }, { "invitelist_long", "{channel $0}: invite {ban $1} {comment by {nick $2}, on $3 ($4 ago)}", 5, { 0, 0, 0, 0, 0 } },
{ "no_such_channel", "{channel $0}: No such channel", 1, { 0 } }, { "no_such_channel", "{channel $0}: No such channel", 1, { 0 } },
{ "channel_synced", "Join to {channel $0} was synced in {hilight $1} secs", 2, { 0, 2 } }, { "channel_synced", "Join to {channel $0} was synced in {hilight $1} secs", 2, { 0, 2 } },
{ "server_help_start", "$1", 2, { 0, 0 } }, { "server_help_start", "$1", 2, { 0, 0 } },

View file

@ -59,6 +59,8 @@ enum {
IRCTXT_NO_BANS, IRCTXT_NO_BANS,
IRCTXT_BANLIST, IRCTXT_BANLIST,
IRCTXT_BANLIST_LONG, IRCTXT_BANLIST_LONG,
IRCTXT_QUIETLIST,
IRCTXT_QUIETLIST_LONG,
IRCTXT_EBANLIST, IRCTXT_EBANLIST,
IRCTXT_EBANLIST_LONG, IRCTXT_EBANLIST_LONG,
IRCTXT_NO_INVITELIST, IRCTXT_NO_INVITELIST,

View file

@ -1,6 +1,7 @@
# this file is part of irssi # this file is part of irssi
libfe_irc_notifylist_a = static_library('fe_irc_notifylist', libfe_irc_notifylist_a = static_library(
'fe_irc_notifylist',
files( files(
'fe-notifylist.c', 'fe-notifylist.c',
'module-formats.c', 'module-formats.c',
@ -11,16 +12,22 @@ libfe_irc_notifylist_a = static_library('fe_irc_notifylist',
def_helpdir, def_helpdir,
def_sysconfdir, def_sysconfdir,
], ],
dependencies : dep) dependencies : dep,
shared_module('fe_irc_notifylist', )
shared_library(
'fe_irc_notifylist',
name_suffix : module_suffix,
install : true, install : true,
install_dir : moduledir, install_dir : moduledir,
link_with : dl_cross_irc_notifylist, link_with : dl_cross_irc_notifylist + dl_cross_irssi_main,
link_whole : libfe_irc_notifylist_a) link_whole : libfe_irc_notifylist_a,
override_options : [ 'b_lundef=false' ],
)
install_headers( install_headers(
files( files(
'module-formats.h', 'module-formats.h',
'module.h', 'module.h',
), ),
subdir : incdir / 'src' / 'fe-common' / 'irc' / 'notifylist') subdir : incdir / 'src' / 'fe-common' / 'irc' / 'notifylist',
)

View file

@ -1,6 +1,4 @@
# this file is part of irssi # this file is part of irssi
subdir('core') # intentionally empty
foreach s : chat_modules
subdir(s)
endforeach

View file

@ -1,5 +1,6 @@
# this file is part of irssi # this file is part of irssi
executable('theme-load-fuzz', executable(
'theme-load-fuzz',
files( files(
'../../null-logger.c', '../../null-logger.c',
'theme-load.c', 'theme-load.c',
@ -10,12 +11,12 @@ executable('theme-load-fuzz',
libcore_a, libcore_a,
libfuzzer_fe_common_core_a, libfuzzer_fe_common_core_a,
], ],
link_args : [fuzzer_lib], link_args : [ fuzzer_lib ],
link_language : fuzzer_link_language, link_language : fuzzer_link_language,
include_directories : rootinc, include_directories : rootinc,
implicit_include_directories : false, implicit_include_directories : false,
install : true, install : true,
dependencies : dep dependencies : dep,
) )
# noinst_headers = files( # noinst_headers = files(

View file

@ -1,6 +1,7 @@
# this file is part of irssi # this file is part of irssi
executable('event-get-params-fuzz', executable(
'event-get-params-fuzz',
files( files(
'../../null-logger.c', '../../null-logger.c',
'event-get-params.c', 'event-get-params.c',
@ -12,12 +13,12 @@ executable('event-get-params-fuzz',
libirc_core_a, libirc_core_a,
libfuzzer_fe_common_core_a, libfuzzer_fe_common_core_a,
], ],
link_args : [fuzzer_lib], link_args : [ fuzzer_lib ],
link_language : fuzzer_link_language, link_language : fuzzer_link_language,
include_directories : rootinc, include_directories : rootinc,
implicit_include_directories : false, implicit_include_directories : false,
install : true, install : true,
dependencies : dep dependencies : dep,
) )
# noinst_headers = files( # noinst_headers = files(

View file

@ -3,7 +3,8 @@
subdir('irc') subdir('irc')
subdir('fe-common') subdir('fe-common')
executable('irssi-fuzz', executable(
'irssi-fuzz',
files( files(
'null-logger.c', 'null-logger.c',
'irssi.c', 'irssi.c',
@ -14,15 +15,16 @@ executable('irssi-fuzz',
libcore_a, libcore_a,
libfuzzer_fe_common_core_a, libfuzzer_fe_common_core_a,
], ],
link_args : [fuzzer_lib], link_args : [ fuzzer_lib ],
link_language : fuzzer_link_language, link_language : fuzzer_link_language,
include_directories : rootinc, include_directories : rootinc,
implicit_include_directories : false, implicit_include_directories : false,
install : true, install : true,
dependencies : dep dependencies : dep,
) )
executable('server-fuzz', executable(
'server-fuzz',
files( files(
'null-logger.c', 'null-logger.c',
'server.c', 'server.c',
@ -37,12 +39,12 @@ executable('server-fuzz',
libfe_irc_dcc_a, libfe_irc_dcc_a,
libfe_irc_notifylist_a, libfe_irc_notifylist_a,
], ],
link_args : [fuzzer_lib], link_args : [ fuzzer_lib ],
link_language : fuzzer_link_language, link_language : fuzzer_link_language,
include_directories : rootinc, include_directories : rootinc,
implicit_include_directories : false, implicit_include_directories : false,
install : true, install : true,
dependencies : dep dependencies : dep,
) )
# noinst_headers = files( # noinst_headers = files(

View file

@ -30,6 +30,7 @@
#include <irssi/src/core/misc.h> #include <irssi/src/core/misc.h>
#include <irssi/src/core/servers-setup.h> #include <irssi/src/core/servers-setup.h>
#include <irssi/src/core/rawlog.h> #include <irssi/src/core/rawlog.h>
#include <irssi/src/core/network-openssl.h>
#include <irssi/src/core/net-sendbuffer.h> #include <irssi/src/core/net-sendbuffer.h>
#include <stddef.h> #include <stddef.h>

View file

@ -29,10 +29,11 @@
static GMainLoop *main_loop; static GMainLoop *main_loop;
static char *autoload_module; static char *autoload_module;
static int reload; static int reload;
static int quitting;
static void sig_exit(void) static void sig_exit(void)
{ {
g_main_loop_quit(main_loop); quitting = TRUE;
} }
static void sig_reload(void) static void sig_reload(void)
@ -103,7 +104,14 @@ int main(int argc, char **argv)
reload = FALSE; reload = FALSE;
module_load(autoload_module, NULL); module_load(autoload_module, NULL);
main_loop = g_main_loop_new(NULL, TRUE); main_loop = g_main_loop_new(NULL, TRUE);
g_main_loop_run(main_loop); while (!quitting && !reload) {
if (sigterm_received) {
sigterm_received = FALSE;
signal_emit("gui exit", 0);
}
g_main_context_iteration(NULL, TRUE);
}
g_main_loop_unref(main_loop); g_main_loop_unref(main_loop);
} }
while (reload); while (reload);

View file

@ -1,19 +1,24 @@
# this file is part of irssi # this file is part of irssi
executable('botti', fe_none_irssi = executable(
'botti',
files( files(
'irssi.c', 'irssi.c',
), ),
include_directories : rootinc, include_directories : rootinc,
implicit_include_directories : false, implicit_include_directories : false,
export_dynamic : true, export_dynamic : true,
implib : true,
link_with : [ link_with : [
libconfig_a, libconfig_a,
libcore_a, libcore_a,
], ],
install : true, install : true,
dependencies : dep dependencies : dep,
) )
if need_dl_cross_link_main
dl_cross_irssi_main = [ fe_none_irssi ]
endif
# noinst_headers = files( # noinst_headers = files(
# 'module.h', # 'module.h',

View file

@ -405,7 +405,7 @@ void gui_printtext_init(void)
indent_functions = g_hash_table_new((GHashFunc) g_str_hash, indent_functions = g_hash_table_new((GHashFunc) g_str_hash,
(GCompareFunc) g_str_equal); (GCompareFunc) g_str_equal);
settings_add_int("history", "scrollback_lines", 500); settings_add_int("history", "scrollback_lines", 5000);
settings_add_time("history", "scrollback_time", "1day"); settings_add_time("history", "scrollback_time", "1day");
settings_add_time("history", "scrollback_max_age", "0"); settings_add_time("history", "scrollback_max_age", "0");
settings_add_int("history", "scrollback_burst_remove", 10); settings_add_int("history", "scrollback_burst_remove", 10);

View file

@ -331,6 +331,11 @@ int main(int argc, char **argv)
/* Does the same as g_main_run(main_loop), except we /* Does the same as g_main_run(main_loop), except we
can call our dirty-checker after each iteration */ can call our dirty-checker after each iteration */
while (!quitting) { while (!quitting) {
if (sigterm_received) {
sigterm_received = FALSE;
signal_emit("gui exit", 0);
}
if (sighup_received) { if (sighup_received) {
sighup_received = FALSE; sighup_received = FALSE;

View file

@ -87,17 +87,20 @@ static void show_lastlog(const char *searchtext, GHashTable *optlist,
{ {
WINDOW_REC *window; WINDOW_REC *window;
LINE_REC *startline; LINE_REC *startline;
GList *list, *tmp; TEXT_BUFFER_VIEW_REC *view;
GString *line; TEXT_BUFFER_REC *buffer;
char *str; GSList *texts, *tmp;
GList *list, *tmp2;
char *str;
int level, before, after, len, date = FALSE; int level, before, after, len, date = FALSE;
level = cmd_options_get_level("lastlog", optlist); level = cmd_options_get_level("lastlog", optlist);
if (level == -1) return; /* error in options */ if (level == -1) return; /* error in options */
if (level == 0) level = MSGLEVEL_ALL; if (level == 0) level = MSGLEVEL_ALL;
view = WINDOW_GUI(active_win)->view;
if (g_hash_table_lookup(optlist, "clear") != NULL) { if (g_hash_table_lookup(optlist, "clear") != NULL) {
textbuffer_view_remove_lines_by_level(WINDOW_GUI(active_win)->view, MSGLEVEL_LASTLOG); textbuffer_view_remove_lines_by_level(view, MSGLEVEL_LASTLOG);
if (*searchtext == '\0') if (*searchtext == '\0')
return; return;
} }
@ -115,16 +118,17 @@ static void show_lastlog(const char *searchtext, GHashTable *optlist,
return; return;
} }
} }
view = WINDOW_GUI(window)->view;
if (g_hash_table_lookup(optlist, "new") != NULL) if (g_hash_table_lookup(optlist, "new") != NULL)
startline = textbuffer_view_get_bookmark(WINDOW_GUI(window)->view, "lastlog_last_check"); startline = textbuffer_view_get_bookmark(view, "lastlog_last_check");
else if (g_hash_table_lookup(optlist, "away") != NULL) else if (g_hash_table_lookup(optlist, "away") != NULL)
startline = textbuffer_view_get_bookmark(WINDOW_GUI(window)->view, "lastlog_last_away"); startline = textbuffer_view_get_bookmark(view, "lastlog_last_away");
else else
startline = NULL; startline = NULL;
if (startline == NULL) if (startline == NULL)
startline = textbuffer_view_get_lines(WINDOW_GUI(window)->view); startline = textbuffer_view_get_lines(view);
str = g_hash_table_lookup(optlist, "#"); str = g_hash_table_lookup(optlist, "#");
if (str != NULL) { if (str != NULL) {
@ -143,22 +147,21 @@ static void show_lastlog(const char *searchtext, GHashTable *optlist,
if (g_hash_table_lookup(optlist, "date") != NULL) if (g_hash_table_lookup(optlist, "date") != NULL)
date = TRUE; date = TRUE;
list = textbuffer_find_text(WINDOW_GUI(window)->view->buffer, startline, buffer = view->buffer;
level, MSGLEVEL_LASTLOG, list = textbuffer_find_text(buffer, startline, level, MSGLEVEL_LASTLOG, searchtext, before,
searchtext, before, after, after, g_hash_table_lookup(optlist, "regexp") != NULL,
g_hash_table_lookup(optlist, "regexp") != NULL, g_hash_table_lookup(optlist, "word") != NULL,
g_hash_table_lookup(optlist, "word") != NULL, g_hash_table_lookup(optlist, "case") != NULL);
g_hash_table_lookup(optlist, "case") != NULL);
len = g_list_length(list); len = g_list_length(list);
if (count <= 0) if (count <= 0)
tmp = list; tmp2 = list;
else { else {
int pos = len-count-start; int pos = len-count-start;
if (pos < 0) pos = 0; if (pos < 0) pos = 0;
tmp = pos > len ? NULL : g_list_nth(list, pos); tmp2 = pos > len ? NULL : g_list_nth(list, pos);
len = g_list_length(tmp); len = g_list_length(tmp2);
} }
if (g_hash_table_lookup(optlist, "count") != NULL) { if (g_hash_table_lookup(optlist, "count") != NULL) {
@ -177,29 +180,21 @@ static void show_lastlog(const char *searchtext, GHashTable *optlist,
return; return;
} }
if (fhandle == NULL && g_hash_table_lookup(optlist, "-") == NULL) /* collect the line texts */
printformat(NULL, NULL, MSGLEVEL_LASTLOG, TXT_LASTLOG_START); texts = NULL;
for (; tmp2 != NULL && (count < 0 || count > 0); tmp2 = tmp2->next) {
line = g_string_new(NULL); GString *line;
while (tmp != NULL && (count < 0 || count > 0)) { LINE_REC *rec = tmp2->data;
LINE_REC *rec = tmp->data;
if (rec == NULL) { if (rec == NULL) {
if (tmp->next == NULL) if (tmp2->next == NULL)
break; break;
if (fhandle != NULL) { texts = g_slist_prepend(texts, NULL);
fwrite("--\n", 3, 1, fhandle);
} else {
printformat_window(active_win,
MSGLEVEL_LASTLOG,
TXT_LASTLOG_SEPARATOR);
}
tmp = tmp->next;
continue; continue;
} }
/* get the line text */ line = g_string_new(NULL);
textbuffer_line2text(WINDOW_GUI(window)->view->buffer, rec, fhandle == NULL, line); textbuffer_line2text(buffer, rec, fhandle == NULL, line);
if (!settings_get_bool("timestamps")) { if (!settings_get_bool("timestamps")) {
struct tm *tm = localtime(&rec->info.time); struct tm *tm = localtime(&rec->info.time);
char timestamp[10]; char timestamp[10];
@ -213,7 +208,31 @@ static void show_lastlog(const char *searchtext, GHashTable *optlist,
if (date == TRUE) if (date == TRUE)
prepend_date(window, rec, line); prepend_date(window, rec, line);
/* write to file/window */ texts = g_slist_prepend(texts, line);
count--;
}
texts = g_slist_reverse(texts);
if (fhandle == NULL && g_hash_table_lookup(optlist, "-") == NULL)
printformat(NULL, NULL, MSGLEVEL_LASTLOG, TXT_LASTLOG_START);
for (tmp = texts; tmp != NULL; tmp = tmp->next) {
GString *line = tmp->data;
if (line == NULL) {
if (tmp->next == NULL)
break;
if (fhandle != NULL) {
fwrite("--\n", 3, 1, fhandle);
} else {
printformat_window(active_win, MSGLEVEL_LASTLOG,
TXT_LASTLOG_SEPARATOR);
}
continue;
}
/* write to file/window */
if (fhandle != NULL) { if (fhandle != NULL) {
fwrite(line->str, line->len, 1, fhandle); fwrite(line->str, line->len, 1, fhandle);
fputc('\n', fhandle); fputc('\n', fhandle);
@ -221,18 +240,15 @@ static void show_lastlog(const char *searchtext, GHashTable *optlist,
printtext_window(active_win, MSGLEVEL_LASTLOG, printtext_window(active_win, MSGLEVEL_LASTLOG,
"%s", line->str); "%s", line->str);
} }
g_string_free(line, TRUE);
count--;
tmp = tmp->next;
} }
g_string_free(line, TRUE);
if (fhandle == NULL && g_hash_table_lookup(optlist, "-") == NULL) if (fhandle == NULL && g_hash_table_lookup(optlist, "-") == NULL)
printformat(NULL, NULL, MSGLEVEL_LASTLOG, TXT_LASTLOG_END); printformat(NULL, NULL, MSGLEVEL_LASTLOG, TXT_LASTLOG_END);
textbuffer_view_set_bookmark_bottom(WINDOW_GUI(window)->view, textbuffer_view_set_bookmark_bottom(view, "lastlog_last_check");
"lastlog_last_check");
g_slist_free(texts);
g_list_free(list); g_list_free(list);
} }

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