mirror of
https://github.com/ZoiteChat/zoitechat.git
synced 2026-03-13 17:20:21 +00:00
Compare commits
14 Commits
appimage-e
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 7e113cdec2 | |||
| 1fdd7f3804 | |||
|
|
288fa3caf7 | ||
| 27e9b4933d | |||
|
|
c43915d609 | ||
| 989ecc5a23 | |||
| a225af6d71 | |||
| d2407c39c7 | |||
| 4754cf3927 | |||
|
|
b23c1a73ca | ||
|
|
166542f1e3 | ||
| 05f4bf382d | |||
|
|
a2e2bdf803 | ||
| 99f97b82a6 |
53
.github/workflows/appimage-build.yml
vendored
53
.github/workflows/appimage-build.yml
vendored
@@ -36,7 +36,6 @@ jobs:
|
|||||||
libgtk-3-bin libglib2.0-bin shared-mime-info gsettings-desktop-schemas \
|
libgtk-3-bin libglib2.0-bin shared-mime-info gsettings-desktop-schemas \
|
||||||
libluajit-5.1-dev libpci-dev libperl-dev libssl-dev libayatana-appindicator3-dev \
|
libluajit-5.1-dev libpci-dev libperl-dev libssl-dev libayatana-appindicator3-dev \
|
||||||
perl python3 python3-minimal python3-dev python3-cffi mono-devel desktop-file-utils \
|
perl python3 python3-minimal python3-dev python3-cffi mono-devel desktop-file-utils \
|
||||||
fonts-noto-color-emoji breeze-gtk-theme \
|
|
||||||
patchelf file curl
|
patchelf file curl
|
||||||
|
|
||||||
- name: Configure
|
- name: Configure
|
||||||
@@ -105,26 +104,6 @@ jobs:
|
|||||||
cp -a /usr/lib/x86_64-linux-gnu/libpython3*.so* AppDir/usr/lib/x86_64-linux-gnu/
|
cp -a /usr/lib/x86_64-linux-gnu/libpython3*.so* AppDir/usr/lib/x86_64-linux-gnu/
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -d "/usr/share/gtk-3.0/emoji" ]; then
|
|
||||||
install -d AppDir/usr/share/gtk-3.0
|
|
||||||
cp -a /usr/share/gtk-3.0/emoji AppDir/usr/share/gtk-3.0/
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -f "/usr/share/fonts/truetype/noto/NotoColorEmoji.ttf" ]; then
|
|
||||||
install -d AppDir/usr/share/fonts/truetype/noto
|
|
||||||
cp -a /usr/share/fonts/truetype/noto/NotoColorEmoji.ttf AppDir/usr/share/fonts/truetype/noto/
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -d "/usr/lib/x86_64-linux-gnu/gtk-3.0/modules" ]; then
|
|
||||||
install -d AppDir/usr/lib/x86_64-linux-gnu/gtk-3.0
|
|
||||||
cp -a /usr/lib/x86_64-linux-gnu/gtk-3.0/modules AppDir/usr/lib/x86_64-linux-gnu/gtk-3.0/
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -d "/usr/lib/gtk-3.0/modules" ]; then
|
|
||||||
install -d AppDir/usr/lib/gtk-3.0
|
|
||||||
cp -a /usr/lib/gtk-3.0/modules AppDir/usr/lib/gtk-3.0/
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Verify bundled plugins
|
- name: Verify bundled plugins
|
||||||
run: |
|
run: |
|
||||||
set -eux
|
set -eux
|
||||||
@@ -165,26 +144,6 @@ jobs:
|
|||||||
export PATH="${PATH:-/usr/bin:/bin}:$APPDIR/usr/bin"
|
export PATH="${PATH:-/usr/bin:/bin}:$APPDIR/usr/bin"
|
||||||
export LD_LIBRARY_PATH="$APPDIR/usr/lib:$APPDIR/usr/lib/x86_64-linux-gnu:${LD_LIBRARY_PATH:-}"
|
export LD_LIBRARY_PATH="$APPDIR/usr/lib:$APPDIR/usr/lib/x86_64-linux-gnu:${LD_LIBRARY_PATH:-}"
|
||||||
export XDG_DATA_DIRS="$APPDIR/usr/share:${XDG_DATA_DIRS:-/usr/local/share:/usr/share}"
|
export XDG_DATA_DIRS="$APPDIR/usr/share:${XDG_DATA_DIRS:-/usr/local/share:/usr/share}"
|
||||||
export GTK_EXE_PREFIX="$APPDIR/usr"
|
|
||||||
export GTK_DATA_PREFIX="$APPDIR/usr"
|
|
||||||
gtk_path_entries=""
|
|
||||||
if [ -d "$APPDIR/usr/lib/x86_64-linux-gnu/gtk-3.0" ]; then
|
|
||||||
gtk_path_entries="$APPDIR/usr/lib/x86_64-linux-gnu/gtk-3.0"
|
|
||||||
fi
|
|
||||||
if [ -d "$APPDIR/usr/lib/gtk-3.0" ]; then
|
|
||||||
gtk_path_entries="${gtk_path_entries:+$gtk_path_entries:}$APPDIR/usr/lib/gtk-3.0"
|
|
||||||
fi
|
|
||||||
if [ -n "$gtk_path_entries" ]; then
|
|
||||||
export GTK_PATH="$gtk_path_entries${GTK_PATH:+:$GTK_PATH}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -d "$APPDIR/etc/fonts" ]; then
|
|
||||||
export FONTCONFIG_SYSROOT="$APPDIR"
|
|
||||||
export FONTCONFIG_PATH="$APPDIR/etc/fonts${FONTCONFIG_PATH:+:$FONTCONFIG_PATH}"
|
|
||||||
if [ -f "$APPDIR/etc/fonts/fonts.conf" ]; then
|
|
||||||
export FONTCONFIG_FILE="$APPDIR/etc/fonts/fonts.conf"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -d "$APPDIR/usr/lib/x86_64-linux-gnu/zoitechat/plugins" ]; then
|
if [ -d "$APPDIR/usr/lib/x86_64-linux-gnu/zoitechat/plugins" ]; then
|
||||||
export ZOITECHAT_LIBDIR="$APPDIR/usr/lib/x86_64-linux-gnu/zoitechat/plugins"
|
export ZOITECHAT_LIBDIR="$APPDIR/usr/lib/x86_64-linux-gnu/zoitechat/plugins"
|
||||||
@@ -233,16 +192,6 @@ jobs:
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
for hook_dir in "$APPDIR/apprun-hooks" "$APPDIR/usr/apprun-hooks"; do
|
|
||||||
if [ -d "$hook_dir" ]; then
|
|
||||||
for hook in "$hook_dir"/*.sh; do
|
|
||||||
if [ -f "$hook" ]; then
|
|
||||||
. "$hook"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
exec "$APPDIR/usr/bin/zoitechat" "$@"
|
exec "$APPDIR/usr/bin/zoitechat" "$@"
|
||||||
EOF
|
EOF
|
||||||
chmod +x AppRun
|
chmod +x AppRun
|
||||||
@@ -268,7 +217,7 @@ jobs:
|
|||||||
subject-path: Zoitechat-*-x86_64.AppImage
|
subject-path: Zoitechat-*-x86_64.AppImage
|
||||||
|
|
||||||
- name: Upload AppImage artifact
|
- name: Upload AppImage artifact
|
||||||
uses: actions/upload-artifact@v5
|
uses: actions/upload-artifact@v6
|
||||||
with:
|
with:
|
||||||
name: zoitechat-appimage
|
name: zoitechat-appimage
|
||||||
path: Zoitechat-*-x86_64.AppImage
|
path: Zoitechat-*-x86_64.AppImage
|
||||||
|
|||||||
2
.github/workflows/flatpak-build.yml
vendored
2
.github/workflows/flatpak-build.yml
vendored
@@ -36,7 +36,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Upload Flatpak Bundle
|
- name: Upload Flatpak Bundle
|
||||||
id: upload_flatpak
|
id: upload_flatpak
|
||||||
uses: actions/upload-artifact@v5
|
uses: actions/upload-artifact@v6
|
||||||
with:
|
with:
|
||||||
name: zoitechat.flatpak
|
name: zoitechat.flatpak
|
||||||
path: zoitechat.flatpak
|
path: zoitechat.flatpak
|
||||||
|
|||||||
2
.github/workflows/manjaro-package-build.yml
vendored
2
.github/workflows/manjaro-package-build.yml
vendored
@@ -74,7 +74,7 @@ jobs:
|
|||||||
cp -v "$GITHUB_WORKSPACE"/packaging/manjaro/.SRCINFO artifacts/
|
cp -v "$GITHUB_WORKSPACE"/packaging/manjaro/.SRCINFO artifacts/
|
||||||
|
|
||||||
- name: Upload package artifacts
|
- name: Upload package artifacts
|
||||||
uses: actions/upload-artifact@v5
|
uses: actions/upload-artifact@v6
|
||||||
with:
|
with:
|
||||||
name: zoitechat-manjaro-package
|
name: zoitechat-manjaro-package
|
||||||
path: artifacts/*
|
path: artifacts/*
|
||||||
|
|||||||
4
.github/workflows/windows-build.yml
vendored
4
.github/workflows/windows-build.yml
vendored
@@ -143,7 +143,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Upload Installer
|
- name: Upload Installer
|
||||||
id: upload_installer
|
id: upload_installer
|
||||||
uses: actions/upload-artifact@v5
|
uses: actions/upload-artifact@v6
|
||||||
with:
|
with:
|
||||||
name: Installer ${{ matrix.arch }}
|
name: Installer ${{ matrix.arch }}
|
||||||
path: ZoiteChat-*.exe
|
path: ZoiteChat-*.exe
|
||||||
@@ -157,7 +157,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Upload Build Files
|
- name: Upload Build Files
|
||||||
id: upload_buildfiles
|
id: upload_buildfiles
|
||||||
uses: actions/upload-artifact@v5
|
uses: actions/upload-artifact@v6
|
||||||
with:
|
with:
|
||||||
name: Build Files ${{ matrix.arch }}
|
name: Build Files ${{ matrix.arch }}
|
||||||
path: zoitechat-build
|
path: zoitechat-build
|
||||||
|
|||||||
@@ -16,11 +16,10 @@
|
|||||||
"--filesystem=~/.themes:ro",
|
"--filesystem=~/.themes:ro",
|
||||||
"--filesystem=~/.icons:ro",
|
"--filesystem=~/.icons:ro",
|
||||||
"--filesystem=xdg-run/tray-icon:create",
|
"--filesystem=xdg-run/tray-icon:create",
|
||||||
|
"--env=GTK_CSD=1",
|
||||||
"--talk-name=org.freedesktop.Notifications",
|
"--talk-name=org.freedesktop.Notifications",
|
||||||
"--talk-name=org.kde.StatusNotifierWatcher",
|
"--talk-name=org.kde.StatusNotifierWatcher",
|
||||||
"--talk-name=com.canonical.AppMenu.Registrar",
|
"--talk-name=com.canonical.AppMenu.Registrar",
|
||||||
|
|
||||||
"--talk-name=org.mpris.MediaPlayer2.*"
|
"--talk-name=org.mpris.MediaPlayer2.*"
|
||||||
],
|
],
|
||||||
"add-extensions": {
|
"add-extensions": {
|
||||||
@@ -40,6 +39,7 @@
|
|||||||
"shared-modules/libcanberra/libcanberra.json",
|
"shared-modules/libcanberra/libcanberra.json",
|
||||||
"shared-modules/libayatana-appindicator/libayatana-appindicator-gtk3.json",
|
"shared-modules/libayatana-appindicator/libayatana-appindicator-gtk3.json",
|
||||||
"python3-cffi.json",
|
"python3-cffi.json",
|
||||||
|
"perl.json",
|
||||||
{
|
{
|
||||||
"name": "lgi",
|
"name": "lgi",
|
||||||
"buildsystem": "meson",
|
"buildsystem": "meson",
|
||||||
@@ -56,8 +56,8 @@
|
|||||||
"buildsystem": "meson",
|
"buildsystem": "meson",
|
||||||
"config-opts": [
|
"config-opts": [
|
||||||
"-Ddbus-service-use-appid=true",
|
"-Ddbus-service-use-appid=true",
|
||||||
"-Dwith-perl=false",
|
"-Dwith-perl=perl",
|
||||||
"-Dwith-python=false",
|
"-Dwith-python=python3",
|
||||||
"-Dwith-lua=lua"
|
"-Dwith-lua=lua"
|
||||||
],
|
],
|
||||||
"build-options": {
|
"build-options": {
|
||||||
|
|||||||
20
flatpak/perl.json
Normal file
20
flatpak/perl.json
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"name": "perl",
|
||||||
|
"buildsystem": "simple",
|
||||||
|
"build-commands": [
|
||||||
|
"./Configure -des -Dprefix=/app -Dvendorprefix=/app -Duseshrplib -Dman1dir=none -Dman3dir=none",
|
||||||
|
"make -j${FLATPAK_BUILDER_N_JOBS}",
|
||||||
|
"make install"
|
||||||
|
],
|
||||||
|
"cleanup": [
|
||||||
|
"/share/man",
|
||||||
|
"/lib/perl5/*/*/CORE/*.a"
|
||||||
|
],
|
||||||
|
"sources": [
|
||||||
|
{
|
||||||
|
"type": "archive",
|
||||||
|
"url": "https://www.cpan.org/src/5.0/perl-5.40.1.tar.xz",
|
||||||
|
"sha256": "dfa20c2eef2b4af133525610bbb65dd13777ecf998c9c5b1ccf0d308e732ee3f"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -7,13 +7,13 @@
|
|||||||
"sources": [
|
"sources": [
|
||||||
{
|
{
|
||||||
"type": "file",
|
"type": "file",
|
||||||
"url": "https://files.pythonhosted.org/packages/0f/86/e19659527668d70be91d0369aeaa055b4eb396b0f387a4f92293a20035bd/pycparser-2.20.tar.gz",
|
"url": "https://files.pythonhosted.org/packages/1d/b2/31537cf4b1ca988837256c910a668b553fceb8f069bedc4b1c826024b52c/pycparser-2.22.tar.gz",
|
||||||
"sha256": "2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0"
|
"sha256": "491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "file",
|
"type": "file",
|
||||||
"url": "https://files.pythonhosted.org/packages/a8/20/025f59f929bbcaa579704f443a438135918484fffaacfaddba776b374563/cffi-1.14.5.tar.gz",
|
"url": "https://files.pythonhosted.org/packages/fc/97/c783634659c2920c3fc70419e3af40972dbaf758daa229a7d6ea6135c90d/cffi-1.17.1.tar.gz",
|
||||||
"sha256": "fd78e5fee591709f32ef6edb9a015b4aa1a5022598e36227500c8f4e02328d9c"
|
"sha256": "1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -32,6 +32,7 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#else
|
#else
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
|
#include <strings.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
|||||||
@@ -59,11 +59,8 @@ static const struct defaultserver def[] =
|
|||||||
{0, "irc.afternet.org"},
|
{0, "irc.afternet.org"},
|
||||||
|
|
||||||
{"Aitvaras", 0},
|
{"Aitvaras", 0},
|
||||||
#ifdef USE_OPENSSL
|
|
||||||
{0, "irc.data.lt/+6668"},
|
{0, "irc.data.lt/+6668"},
|
||||||
{0, "irc.omicron.lt/+6668"},
|
|
||||||
{0, "irc.vub.lt/+6668"},
|
{0, "irc.vub.lt/+6668"},
|
||||||
#endif
|
|
||||||
{0, "irc.data.lt"},
|
{0, "irc.data.lt"},
|
||||||
{0, "irc.omicron.lt"},
|
{0, "irc.omicron.lt"},
|
||||||
{0, "irc.vub.lt"},
|
{0, "irc.vub.lt"},
|
||||||
@@ -96,9 +93,6 @@ static const struct defaultserver def[] =
|
|||||||
{"ChatSpike", 0, 0, 0, LOGIN_SASL},
|
{"ChatSpike", 0, 0, 0, LOGIN_SASL},
|
||||||
{0, "irc.chatspike.net"},
|
{0, "irc.chatspike.net"},
|
||||||
|
|
||||||
{"DaIRC", 0},
|
|
||||||
{0, "irc.dairc.net"},
|
|
||||||
|
|
||||||
{"DALnet", 0, 0, 0, LOGIN_NICKSERV},
|
{"DALnet", 0, 0, 0, LOGIN_NICKSERV},
|
||||||
/* Self signed */
|
/* Self signed */
|
||||||
{0, "us.dal.net"},
|
{0, "us.dal.net"},
|
||||||
@@ -106,32 +100,18 @@ static const struct defaultserver def[] =
|
|||||||
{"DarkMyst", 0, 0, 0, LOGIN_SASL, 0, TRUE},
|
{"DarkMyst", 0, 0, 0, LOGIN_SASL, 0, TRUE},
|
||||||
{0, "irc.darkmyst.org"},
|
{0, "irc.darkmyst.org"},
|
||||||
|
|
||||||
#ifdef USE_OPENSSL
|
|
||||||
{"darkscience", 0, 0, 0, LOGIN_SASL, 0, TRUE},
|
{"darkscience", 0, 0, 0, LOGIN_SASL, 0, TRUE},
|
||||||
{0, "irc.darkscience.net"},
|
{0, "irc.darkscience.net"},
|
||||||
{0, "irc.drk.sc"},
|
{0, "irc.drk.sc"},
|
||||||
{0, "irc.darkscience.ws"},
|
|
||||||
#endif
|
|
||||||
|
|
||||||
{"Dark-Tou-Net", 0},
|
|
||||||
{0, "irc.d-t-net.de"},
|
|
||||||
|
|
||||||
{"DigitalIRC", 0, 0, 0, LOGIN_SASL, 0, TRUE},
|
{"DigitalIRC", 0, 0, 0, LOGIN_SASL, 0, TRUE},
|
||||||
{0, "irc.digitalirc.org"},
|
{0, "irc.digitalirc.org"},
|
||||||
|
|
||||||
#ifdef USE_OPENSSL
|
|
||||||
{"DosersNET", 0, 0, 0, LOGIN_SASL, 0, TRUE},
|
{"DosersNET", 0, 0, 0, LOGIN_SASL, 0, TRUE},
|
||||||
{0, "irc.dosers.net/+6697"},
|
{0, "irc.dosers.net/+6697"},
|
||||||
#endif
|
|
||||||
|
|
||||||
{"EFnet", 0},
|
{"EFnet", 0, 0, 0, LOGIN_SASL, 0, TRUE},
|
||||||
{0, "irc.choopa.net"},
|
{0, "irc.efnet.org"},
|
||||||
{0, "efnet.port80.se"},
|
|
||||||
{0, "irc.underworld.no"},
|
|
||||||
{0, "efnet.deic.eu"},
|
|
||||||
|
|
||||||
{"EnterTheGame", 0},
|
|
||||||
{0, "irc.enterthegame.com"},
|
|
||||||
|
|
||||||
{"EntropyNet", 0, 0, 0, LOGIN_SASL, 0, TRUE},
|
{"EntropyNet", 0, 0, 0, LOGIN_SASL, 0, TRUE},
|
||||||
{0, "irc.entropynet.net"},
|
{0, "irc.entropynet.net"},
|
||||||
@@ -146,10 +126,6 @@ static const struct defaultserver def[] =
|
|||||||
/* Self signed */
|
/* Self signed */
|
||||||
{0, "irc.europnet.org"},
|
{0, "irc.europnet.org"},
|
||||||
|
|
||||||
{"FDFNet", 0},
|
|
||||||
/* Self signed */
|
|
||||||
{0, "irc.fdfnet.net"},
|
|
||||||
|
|
||||||
{"GameSurge", 0},
|
{"GameSurge", 0},
|
||||||
{0, "irc.gamesurge.net"},
|
{0, "irc.gamesurge.net"},
|
||||||
|
|
||||||
@@ -162,86 +138,60 @@ static const struct defaultserver def[] =
|
|||||||
{"GIMPNet", 0},
|
{"GIMPNet", 0},
|
||||||
/* Invalid hostname in cert */
|
/* Invalid hostname in cert */
|
||||||
{0, "irc.gimp.org"},
|
{0, "irc.gimp.org"},
|
||||||
{0, "irc.gnome.org"},
|
|
||||||
|
|
||||||
{"GlobalGamers", 0},
|
|
||||||
#ifdef USE_OPENSSL
|
|
||||||
{0, "irc.globalgamers.net/+6660"},
|
|
||||||
#endif
|
|
||||||
{0, "irc.globalgamers.net"},
|
|
||||||
|
|
||||||
#ifdef USE_OPENSSL
|
|
||||||
{"hackint", 0, 0, 0, LOGIN_SASL, 0, TRUE},
|
{"hackint", 0, 0, 0, LOGIN_SASL, 0, TRUE},
|
||||||
{0, "irc.hackint.org"},
|
{0, "irc.hackint.org"},
|
||||||
{0, "irc.eu.hackint.org"},
|
{0, "irc.eu.hackint.org"},
|
||||||
#endif
|
|
||||||
|
|
||||||
{"Hashmark", 0},
|
{"Hashmark", 0},
|
||||||
{0, "irc.hashmark.net"},
|
{0, "irc.hashmark.net"},
|
||||||
|
|
||||||
{"ICQ-Chat", 0, 0, 0, LOGIN_SASL, 0, TRUE},
|
|
||||||
{0, "irc.icq-chat.com"},
|
|
||||||
|
|
||||||
{"Interlinked", 0, 0, 0, LOGIN_SASL, 0, TRUE},
|
{"Interlinked", 0, 0, 0, LOGIN_SASL, 0, TRUE},
|
||||||
{0, "irc.interlinked.me"},
|
{0, "irc.interlinked.me"},
|
||||||
|
|
||||||
{"Irc-Nerds", 0, 0, 0, LOGIN_SASL, 0, TRUE},
|
{"Irc-Nerds", 0, 0, 0, LOGIN_SASL, 0, TRUE},
|
||||||
{0, "irc.irc-nerds.net"},
|
{0, "irc.irc-nerds.net"},
|
||||||
|
|
||||||
{"IRC4Fun", 0, 0, 0, LOGIN_SASL, 0, TRUE},
|
{"IRC4Fun", 0, 0, 0, LOGIN_SASL, 0, TRUE},
|
||||||
{0, "irc.irc4fun.net"},
|
{0, "irc.irc4fun.net"},
|
||||||
|
|
||||||
{"IRCNet", 0},
|
{"IRCNet", 0},
|
||||||
{0, "open.ircnet.net"},
|
{0, "open.ircnet.net"},
|
||||||
|
|
||||||
{"IRCtoo", 0},
|
|
||||||
{0, "irc.irctoo.net"},
|
|
||||||
|
|
||||||
{"Keyboard-Failure", 0},
|
{"Keyboard-Failure", 0},
|
||||||
/* SSL is self-signed */
|
/* SSL is self-signed */
|
||||||
{0, "irc.kbfail.net"},
|
{0, "irc.kbfail.net"},
|
||||||
|
|
||||||
{"Libera.Chat", 0, 0, 0, LOGIN_SASL, 0, TRUE},
|
{"Libera.Chat", 0, 0, 0, LOGIN_SASL, 0, TRUE},
|
||||||
{0, "irc.libera.chat"},
|
{0, "irc.libera.chat"},
|
||||||
|
|
||||||
#ifdef USE_OPENSSL
|
|
||||||
{"LibertaCasa", 0, 0, 0, LOGIN_SASL, 0, TRUE},
|
{"LibertaCasa", 0, 0, 0, LOGIN_SASL, 0, TRUE},
|
||||||
{0, "irc.liberta.casa"},
|
{0, "irc.liberta.casa"},
|
||||||
#endif
|
|
||||||
|
|
||||||
{"LibraIRC", 0},
|
{"LibraIRC", 0},
|
||||||
/* Self signed */
|
/* Self signed */
|
||||||
{0, "irc.librairc.net"},
|
{0, "irc.librairc.net"},
|
||||||
|
|
||||||
#ifdef USE_OPENSSL
|
|
||||||
{"LinkNet", 0},
|
{"LinkNet", 0},
|
||||||
{0, "irc.link-net.org/+7000"},
|
{0, "irc.link-net.org/+7000"},
|
||||||
#endif
|
|
||||||
|
|
||||||
{"MindForge", 0, 0, 0, LOGIN_SASL},
|
{"MindForge", 0, 0, 0, LOGIN_SASL},
|
||||||
{0, "irc.mindforge.org"},
|
{0, "irc.mindforge.org"},
|
||||||
|
|
||||||
{"MIXXnet", 0},
|
{"MIXXnet", 0},
|
||||||
{0, "irc.mixxnet.net"},
|
{0, "irc.mixxnet.net"},
|
||||||
|
|
||||||
{"Newnet", 0, 0, 0, LOGIN_SASL, 0, TRUE},
|
{"Newnet", 0, 0, 0, LOGIN_SASL, 0, TRUE},
|
||||||
{0, "irc.newnet.net"},
|
{0, "irc.newnet.net"},
|
||||||
{0, "australia-au.newnet.net"},
|
{0, "australia-au.newnet.net"},
|
||||||
{0, "beauharnois-ca.newnet.net"},
|
{0, "beauharnois-ca.newnet.net"},
|
||||||
{0, "vancouver-ca.newnet.net"},
|
{0, "vancouver-ca.newnet.net"},
|
||||||
{0, "gravelines-fr.newnet.net"},
|
{0, "gravelines-fr.newnet.net"},
|
||||||
{0, "sao-paulo.newnet.net"},
|
{0, "sao-paulo.newnet.net"},
|
||||||
|
|
||||||
{"Oceanius", 0, 0, 0, LOGIN_SASL},
|
|
||||||
/* Self signed */
|
|
||||||
{0, "irc.oceanius.com"},
|
|
||||||
|
|
||||||
{"OFTC", 0, 0, 0, 0, 0, TRUE},
|
{"OFTC", 0, 0, 0, 0, 0, TRUE},
|
||||||
{0, "irc.oftc.net"},
|
{0, "irc.oftc.net"},
|
||||||
|
|
||||||
{"OtherNet", 0},
|
|
||||||
{0, "irc.othernet.org"},
|
|
||||||
|
|
||||||
{"OzOrg", 0},
|
{"OzOrg", 0},
|
||||||
{0, "irc.oz.org"},
|
{0, "irc.oz.org"},
|
||||||
|
|
||||||
@@ -268,8 +218,6 @@ static const struct defaultserver def[] =
|
|||||||
{"RusNet", 0, 0, "KOI8-R (Cyrillic)"},
|
{"RusNet", 0, 0, "KOI8-R (Cyrillic)"},
|
||||||
/* Self signed */
|
/* Self signed */
|
||||||
{0, "irc.tomsk.net"},
|
{0, "irc.tomsk.net"},
|
||||||
{0, "irc.run.net"},
|
|
||||||
{0, "irc.ru"},
|
|
||||||
{0, "irc.lucky.net"},
|
{0, "irc.lucky.net"},
|
||||||
|
|
||||||
{"Serenity-IRC", 0},
|
{"Serenity-IRC", 0},
|
||||||
@@ -291,7 +239,7 @@ static const struct defaultserver def[] =
|
|||||||
{"SorceryNet", 0, 0, 0, LOGIN_SASL},
|
{"SorceryNet", 0, 0, 0, LOGIN_SASL},
|
||||||
/* Self signed */
|
/* Self signed */
|
||||||
{0, "irc.sorcery.net"},
|
{0, "irc.sorcery.net"},
|
||||||
|
|
||||||
{"SpotChat", 0, 0, 0, LOGIN_SASL, 0, TRUE},
|
{"SpotChat", 0, 0, 0, LOGIN_SASL, 0, TRUE},
|
||||||
{0, "irc.spotchat.org"},
|
{0, "irc.spotchat.org"},
|
||||||
|
|
||||||
@@ -299,9 +247,6 @@ static const struct defaultserver def[] =
|
|||||||
/* Self signed */
|
/* Self signed */
|
||||||
{0, "irc.station51.net"},
|
{0, "irc.station51.net"},
|
||||||
|
|
||||||
{"StormBit", 0, 0, 0, LOGIN_SASL, 0, TRUE},
|
|
||||||
{0, "irc.stormbit.net"},
|
|
||||||
|
|
||||||
{"SwiftIRC", 0},
|
{"SwiftIRC", 0},
|
||||||
/* Expired cert */
|
/* Expired cert */
|
||||||
{0, "irc.swiftirc.net"},
|
{0, "irc.swiftirc.net"},
|
||||||
@@ -312,23 +257,16 @@ static const struct defaultserver def[] =
|
|||||||
|
|
||||||
{"Techtronix", 0, 0, 0, LOGIN_SASL, 0, TRUE},
|
{"Techtronix", 0, 0, 0, LOGIN_SASL, 0, TRUE},
|
||||||
{0, "irc.techtronix.net"},
|
{0, "irc.techtronix.net"},
|
||||||
|
|
||||||
{"tilde.chat", 0, 0, 0, LOGIN_SASL, 0, TRUE},
|
{"tilde.chat", 0, 0, 0, LOGIN_SASL, 0, TRUE},
|
||||||
{0, "irc.tilde.chat"},
|
{0, "irc.tilde.chat"},
|
||||||
|
|
||||||
{"TURLINet", 0, 0, 0, 0, 0, TRUE},
|
{"TURLINet", 0, 0, 0, 0, 0, TRUE},
|
||||||
/* all servers use UTF-8 and valid certs */
|
/* all servers use UTF-8 and valid certs */
|
||||||
{0, "irc.servx.org"},
|
{0, "irc.servx.org"},
|
||||||
{0, "i.valware.uk"},
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef USE_OPENSSL
|
|
||||||
{"TripSit", 0, 0, 0, LOGIN_SASL, 0, TRUE},
|
{"TripSit", 0, 0, 0, LOGIN_SASL, 0, TRUE},
|
||||||
{0, "irc.tripsit.me"},
|
{0, "irc.tripsit.me"},
|
||||||
{0, "newirc.tripsit.me"},
|
|
||||||
{0, "coconut.tripsit.me"},
|
|
||||||
{0, "innsbruck.tripsit.me"},
|
|
||||||
#endif
|
|
||||||
|
|
||||||
{"UnderNet", 0, 0, 0, LOGIN_CUSTOM, "MSG x@channels.undernet.org login %u %p"},
|
{"UnderNet", 0, 0, 0, LOGIN_CUSTOM, "MSG x@channels.undernet.org login %u %p"},
|
||||||
{0, "us.undernet.org"},
|
{0, "us.undernet.org"},
|
||||||
@@ -338,8 +276,8 @@ static const struct defaultserver def[] =
|
|||||||
|
|
||||||
{"Zoite", 0, 0, 0, LOGIN_SASL, 0, TRUE},
|
{"Zoite", 0, 0, 0, LOGIN_SASL, 0, TRUE},
|
||||||
{0, "irc.zoite.net"},
|
{0, "irc.zoite.net"},
|
||||||
{0, "penumbra.zoite.net"},
|
{0, "penumbra.zoite.net"},
|
||||||
{0, "hedy.zoite.net"},
|
{0, "hedy.zoite.net"},
|
||||||
|
|
||||||
{0,0}
|
{0,0}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1572,6 +1572,12 @@ menu_away (GtkCheckMenuItem *item, gpointer none)
|
|||||||
handle_command (current_sess, gtk_check_menu_item_get_active (item) ? "away" : "back", FALSE);
|
handle_command (current_sess, gtk_check_menu_item_get_active (item) ? "away" : "back", FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
menu_away_toggle (GtkWidget *item, gpointer none)
|
||||||
|
{
|
||||||
|
handle_command (current_sess, current_sess->server->is_away ? "back" : "away", FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
menu_chanlist (GtkWidget * wid, gpointer none)
|
menu_chanlist (GtkWidget * wid, gpointer none)
|
||||||
{
|
{
|
||||||
@@ -1888,30 +1894,12 @@ menu_about (GtkWidget *wid, gpointer sess)
|
|||||||
gtk_widget_show_all (GTK_WIDGET(dialog));
|
gtk_widget_show_all (GTK_WIDGET(dialog));
|
||||||
}
|
}
|
||||||
|
|
||||||
#define ICON_NEW "zc-menu-new"
|
|
||||||
#define ICON_NETWORK_LIST "zc-menu-network-list"
|
|
||||||
#define ICON_LOAD_PLUGIN "zc-menu-load-plugin"
|
|
||||||
#define ICON_DETACH "zc-menu-detach"
|
|
||||||
#define ICON_CLOSE "zc-menu-close"
|
|
||||||
#define ICON_QUIT "zc-menu-quit"
|
|
||||||
#define ICON_DISCONNECT "zc-menu-disconnect"
|
|
||||||
#define ICON_CONNECT "zc-menu-connect"
|
|
||||||
#define ICON_JOIN "zc-menu-join"
|
|
||||||
#define ICON_CHANLIST "zc-menu-chanlist"
|
|
||||||
#define ICON_PREFERENCES "zc-menu-preferences"
|
|
||||||
#define ICON_CLEAR "zc-menu-clear"
|
|
||||||
#define ICON_SAVE "zc-menu-save"
|
|
||||||
#define ICON_SEARCH "zc-menu-search"
|
|
||||||
#define ICON_FIND "zc-menu-find"
|
|
||||||
#define ICON_HELP "zc-menu-help"
|
|
||||||
#define ICON_ABOUT "zc-menu-about"
|
|
||||||
|
|
||||||
static struct mymenu mymenu[] = {
|
static struct mymenu mymenu[] = {
|
||||||
{N_("_ZoiteChat"), 0, 0, M_NEWMENU, MENU_ID_ZOITECHAT, 0, 1},
|
{N_("_ZoiteChat"), 0, 0, M_NEWMENU, MENU_ID_ZOITECHAT, 0, 1},
|
||||||
{N_("Network Li_st"), menu_open_server_list, ICON_NETWORK_LIST, M_MENUSTOCK, 0, 0, 1, GDK_KEY_s},
|
{N_("Network Li_st"), menu_open_server_list, 0, M_MENUITEM, 0, 0, 1, GDK_KEY_s},
|
||||||
{0, 0, 0, M_SEP, 0, 0, 0},
|
{0, 0, 0, M_SEP, 0, 0, 0},
|
||||||
|
|
||||||
{N_("_New"), 0, ICON_NEW, M_MENUSUB, 0, 0, 1},
|
{N_("_New"), 0, 0, M_MENUSUB, 0, 0, 1},
|
||||||
{N_("Server Tab"), menu_newserver_tab, 0, M_MENUITEM, 0, 0, 1, GDK_KEY_t},
|
{N_("Server Tab"), menu_newserver_tab, 0, M_MENUITEM, 0, 0, 1, GDK_KEY_t},
|
||||||
{N_("Channel Tab"), menu_newchannel_tab, 0, M_MENUITEM, 0, 0, 1},
|
{N_("Channel Tab"), menu_newchannel_tab, 0, M_MENUITEM, 0, 0, 1},
|
||||||
{N_("Server Window"), menu_newserver_window, 0, M_MENUITEM, 0, 0, 1, GDK_KEY_n},
|
{N_("Server Window"), menu_newserver_window, 0, M_MENUITEM, 0, 0, 1, GDK_KEY_n},
|
||||||
@@ -1919,14 +1907,14 @@ static struct mymenu mymenu[] = {
|
|||||||
{0, 0, 0, M_END, 0, 0, 0},
|
{0, 0, 0, M_END, 0, 0, 0},
|
||||||
{0, 0, 0, M_SEP, 0, 0, 0},
|
{0, 0, 0, M_SEP, 0, 0, 0},
|
||||||
|
|
||||||
{N_("_Load Plugin or Script" ELLIPSIS), menu_loadplugin, ICON_LOAD_PLUGIN, M_MENUSTOCK, 0, 0, 1},
|
{N_("_Load Plugin or Script" ELLIPSIS), menu_loadplugin, 0, M_MENUITEM, 0, 0, 1},
|
||||||
{0, 0, 0, M_SEP, 0, 0, 0}, /* 11 */
|
{0, 0, 0, M_SEP, 0, 0, 0}, /* 11 */
|
||||||
#define DETACH_OFFSET (12)
|
#define DETACH_OFFSET (12)
|
||||||
{0, menu_detach, ICON_DETACH, M_MENUSTOCK, 0, 0, 1}, /* 12 */
|
{0, menu_detach, 0, M_MENUITEM, 0, 0, 1}, /* 12 */
|
||||||
#define CLOSE_OFFSET (13)
|
#define CLOSE_OFFSET (13)
|
||||||
{0, menu_close, ICON_CLOSE, M_MENUSTOCK, 0, 0, 1},
|
{0, menu_close, 0, M_MENUITEM, 0, 0, 1},
|
||||||
{0, 0, 0, M_SEP, 0, 0, 0},
|
{0, 0, 0, M_SEP, 0, 0, 0},
|
||||||
{N_("_Quit"), menu_quit, ICON_QUIT, M_MENUSTOCK, 0, 0, 1, GDK_KEY_q}, /* 15 */
|
{N_("_Quit"), menu_quit, 0, M_MENUITEM, 0, 0, 1, GDK_KEY_q}, /* 15 */
|
||||||
|
|
||||||
{N_("_View"), 0, 0, M_NEWMENU, 0, 0, 1},
|
{N_("_View"), 0, 0, M_NEWMENU, 0, 0, 1},
|
||||||
#define MENUBAR_OFFSET (17)
|
#define MENUBAR_OFFSET (17)
|
||||||
@@ -1952,18 +1940,18 @@ static struct mymenu mymenu[] = {
|
|||||||
{N_ ("_Fullscreen"), menu_fullscreen_toggle, 0, M_MENUTOG, MENU_ID_FULLSCREEN, 0, 1, GDK_KEY_F11},
|
{N_ ("_Fullscreen"), menu_fullscreen_toggle, 0, M_MENUTOG, MENU_ID_FULLSCREEN, 0, 1, GDK_KEY_F11},
|
||||||
|
|
||||||
{N_("_Server"), 0, 0, M_NEWMENU, 0, 0, 1},
|
{N_("_Server"), 0, 0, M_NEWMENU, 0, 0, 1},
|
||||||
{N_("_Disconnect"), menu_disconnect, ICON_DISCONNECT, M_MENUSTOCK, MENU_ID_DISCONNECT, 0, 1},
|
{N_("_Disconnect"), menu_disconnect, 0, M_MENUITEM, MENU_ID_DISCONNECT, 0, 1},
|
||||||
{N_("_Reconnect"), menu_reconnect, ICON_CONNECT, M_MENUSTOCK, MENU_ID_RECONNECT, 0, 1},
|
{N_("_Reconnect"), menu_reconnect, 0, M_MENUITEM, MENU_ID_RECONNECT, 0, 1},
|
||||||
{N_("_Join a Channel" ELLIPSIS), menu_join, ICON_JOIN, M_MENUSTOCK, MENU_ID_JOIN, 0, 1},
|
{N_("_Join a Channel" ELLIPSIS), menu_join, 0, M_MENUITEM, MENU_ID_JOIN, 0, 1},
|
||||||
{N_("Channel _List"), menu_chanlist, ICON_CHANLIST, M_MENUSTOCK, 0, 0, 1},
|
{N_("Channel _List"), menu_chanlist, 0, M_MENUITEM, 0, 0, 1},
|
||||||
{0, 0, 0, M_SEP, 0, 0, 0},
|
{0, 0, 0, M_SEP, 0, 0, 0},
|
||||||
#define AWAY_OFFSET (41)
|
#define AWAY_OFFSET (41)
|
||||||
{N_("Marked _Away"), menu_away, 0, M_MENUTOG, MENU_ID_AWAY, 0, 1, GDK_KEY_a},
|
{N_("Marked _Away"), menu_away_toggle, 0, M_MENUITEM, MENU_ID_AWAY, 0, 1, GDK_KEY_a},
|
||||||
|
|
||||||
{N_("_Usermenu"), 0, 0, M_NEWMENU, MENU_ID_USERMENU, 0, 1}, /* 40 */
|
{N_("_Usermenu"), 0, 0, M_NEWMENU, MENU_ID_USERMENU, 0, 1}, /* 40 */
|
||||||
|
|
||||||
{N_("S_ettings"), 0, 0, M_NEWMENU, 0, 0, 1},
|
{N_("S_ettings"), 0, 0, M_NEWMENU, 0, 0, 1},
|
||||||
{N_("_Preferences"), menu_settings, ICON_PREFERENCES, M_MENUSTOCK, 0, 0, 1},
|
{N_("_Preferences"), menu_settings, 0, M_MENUITEM, 0, 0, 1},
|
||||||
{0, 0, 0, M_SEP, 0, 0, 0},
|
{0, 0, 0, M_SEP, 0, 0, 0},
|
||||||
{N_("Auto Replace"), menu_rpopup, 0, M_MENUITEM, 0, 0, 1},
|
{N_("Auto Replace"), menu_rpopup, 0, M_MENUITEM, 0, 0, 1},
|
||||||
{N_("CTCP Replies"), menu_ctcpguiopen, 0, M_MENUITEM, 0, 0, 1},
|
{N_("CTCP Replies"), menu_ctcpguiopen, 0, M_MENUITEM, 0, 0, 1},
|
||||||
@@ -1989,18 +1977,18 @@ static struct mymenu mymenu[] = {
|
|||||||
{N_("Reset Marker Line"), menu_resetmarker, 0, M_MENUITEM, 0, 0, 1, GDK_KEY_m},
|
{N_("Reset Marker Line"), menu_resetmarker, 0, M_MENUITEM, 0, 0, 1, GDK_KEY_m},
|
||||||
{N_("Move to Marker Line"), menu_movetomarker, 0, M_MENUITEM, 0, 0, 1, GDK_KEY_M},
|
{N_("Move to Marker Line"), menu_movetomarker, 0, M_MENUITEM, 0, 0, 1, GDK_KEY_M},
|
||||||
{N_("_Copy Selection"), menu_copy_selection, 0, M_MENUITEM, 0, 0, 1, GDK_KEY_C},
|
{N_("_Copy Selection"), menu_copy_selection, 0, M_MENUITEM, 0, 0, 1, GDK_KEY_C},
|
||||||
{N_("C_lear Text"), menu_flushbuffer, ICON_CLEAR, M_MENUSTOCK, 0, 0, 1},
|
{N_("C_lear Text"), menu_flushbuffer, 0, M_MENUITEM, 0, 0, 1},
|
||||||
{N_("Save Text" ELLIPSIS), menu_savebuffer, ICON_SAVE, M_MENUSTOCK, 0, 0, 1},
|
{N_("Save Text" ELLIPSIS), menu_savebuffer, 0, M_MENUITEM, 0, 0, 1},
|
||||||
#define SEARCH_OFFSET (70)
|
#define SEARCH_OFFSET (70)
|
||||||
{N_("Search"), 0, ICON_SEARCH, M_MENUSUB, 0, 0, 1},
|
{N_("Search"), 0, 0, M_MENUSUB, 0, 0, 1},
|
||||||
{N_("Search Text" ELLIPSIS), menu_search, ICON_FIND, M_MENUSTOCK, 0, 0, 1, GDK_KEY_f},
|
{N_("Search Text" ELLIPSIS), menu_search, 0, M_MENUITEM, 0, 0, 1, GDK_KEY_f},
|
||||||
{N_("Search Next" ), menu_search_next, ICON_FIND, M_MENUSTOCK, 0, 0, 1, GDK_KEY_g},
|
{N_("Search Next" ), menu_search_next, 0, M_MENUITEM, 0, 0, 1, GDK_KEY_g},
|
||||||
{N_("Search Previous" ), menu_search_prev, ICON_FIND, M_MENUSTOCK, 0, 0, 1, GDK_KEY_G},
|
{N_("Search Previous" ), menu_search_prev, 0, M_MENUITEM, 0, 0, 1, GDK_KEY_G},
|
||||||
{0, 0, 0, M_END, 0, 0, 0},
|
{0, 0, 0, M_END, 0, 0, 0},
|
||||||
|
|
||||||
{N_("_Help"), 0, 0, M_NEWMENU, 0, 0, 1}, /* 74 */
|
{N_("_Help"), 0, 0, M_NEWMENU, 0, 0, 1}, /* 74 */
|
||||||
{N_("_Contents"), menu_docs, ICON_HELP, M_MENUSTOCK, 0, 0, 1, GDK_KEY_F1},
|
{N_("_Contents"), menu_docs, 0, M_MENUITEM, 0, 0, 1, GDK_KEY_F1},
|
||||||
{N_("_About"), menu_about, ICON_ABOUT, M_MENUSTOCK, 0, 0, 1},
|
{N_("_About"), menu_about, 0, M_MENUITEM, 0, 0, 1},
|
||||||
|
|
||||||
{0, 0, 0, M_END, 0, 0, 0},
|
{0, 0, 0, M_END, 0, 0, 0},
|
||||||
};
|
};
|
||||||
@@ -2008,11 +1996,14 @@ static struct mymenu mymenu[] = {
|
|||||||
void
|
void
|
||||||
menu_set_away (session_gui *gui, int away)
|
menu_set_away (session_gui *gui, int away)
|
||||||
{
|
{
|
||||||
GtkCheckMenuItem *item = GTK_CHECK_MENU_ITEM (gui->menu_item[MENU_ID_AWAY]);
|
if (GTK_IS_CHECK_MENU_ITEM (gui->menu_item[MENU_ID_AWAY]))
|
||||||
|
{
|
||||||
|
GtkCheckMenuItem *item = GTK_CHECK_MENU_ITEM (gui->menu_item[MENU_ID_AWAY]);
|
||||||
|
|
||||||
g_signal_handlers_block_by_func (G_OBJECT (item), menu_away, NULL);
|
g_signal_handlers_block_by_func (G_OBJECT (item), menu_away, NULL);
|
||||||
gtk_check_menu_item_set_active (item, away);
|
gtk_check_menu_item_set_active (item, away);
|
||||||
g_signal_handlers_unblock_by_func (G_OBJECT (item), menu_away, NULL);
|
g_signal_handlers_unblock_by_func (G_OBJECT (item), menu_away, NULL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
525
tools/scan-zoitechat-servlist.sh
Normal file
525
tools/scan-zoitechat-servlist.sh
Normal file
@@ -0,0 +1,525 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -Eeuo pipefail
|
||||||
|
IFS=$'\n\t'
|
||||||
|
|
||||||
|
SCRIPT_NAME=$(basename "$0")
|
||||||
|
VERSION="1.0.0"
|
||||||
|
|
||||||
|
REPO_URL="${REPO_URL:-}"
|
||||||
|
BRANCH="${BRANCH:-main}"
|
||||||
|
CHECKOUT_DIR="${CHECKOUT_DIR:-/tmp/zoitechat-servscan}"
|
||||||
|
SERVLIST_PATH="${SERVLIST_PATH:-}"
|
||||||
|
EMAIL_TO="${EMAIL_TO:-}"
|
||||||
|
EMAIL_FROM="${EMAIL_FROM:-servscan@$(hostname -f 2>/dev/null || hostname)}"
|
||||||
|
SUBJECT_PREFIX="${SUBJECT_PREFIX:-ZoiteChat servlist scan}"
|
||||||
|
CONNECT_TIMEOUT="${CONNECT_TIMEOUT:-8}"
|
||||||
|
SSL_TIMEOUT="${SSL_TIMEOUT:-15}"
|
||||||
|
PLAIN_PORT="${PLAIN_PORT:-6667}"
|
||||||
|
SSL_PORT="${SSL_PORT:-6697}"
|
||||||
|
DO_CLONE=1
|
||||||
|
DO_EMAIL=1
|
||||||
|
|
||||||
|
TMP_DIR=""
|
||||||
|
REPORT_FILE=""
|
||||||
|
ROWS_FILE=""
|
||||||
|
COMMIT_REF="local-file"
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
cat <<USAGE
|
||||||
|
Usage:
|
||||||
|
${SCRIPT_NAME} --repo <git-url> --branch <branch> --email-to <address> [options]
|
||||||
|
${SCRIPT_NAME} --servlist <path/to/src/common/servlist.c> --email-to <address> [options]
|
||||||
|
|
||||||
|
Options:
|
||||||
|
--repo <url> Git repository to clone or update.
|
||||||
|
--branch <name> Branch to scan. Default: ${BRANCH}
|
||||||
|
--checkout-dir <path> Dedicated checkout dir. Default: ${CHECKOUT_DIR}
|
||||||
|
--servlist <path> Scan a local servlist.c instead of cloning.
|
||||||
|
--email-to <address> Recipient email address.
|
||||||
|
--email-from <address> From address for the email.
|
||||||
|
--subject-prefix <text> Subject prefix. Default: ${SUBJECT_PREFIX}
|
||||||
|
--connect-timeout <sec> TCP timeout. Default: ${CONNECT_TIMEOUT}
|
||||||
|
--ssl-timeout <sec> TLS timeout. Default: ${SSL_TIMEOUT}
|
||||||
|
--plain-port <port> Default non-SSL IRC port. Default: ${PLAIN_PORT}
|
||||||
|
--ssl-port <port> Default SSL IRC port. Default: ${SSL_PORT}
|
||||||
|
--no-clone Do not clone. Requires --servlist.
|
||||||
|
--no-email Print report only.
|
||||||
|
-h, --help Show this help.
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
- Existing checkouts in --checkout-dir are hard-reset to origin/<branch>.
|
||||||
|
- SSL is tested when the network defaults to SSL or the host uses /+port.
|
||||||
|
- Email delivery uses sendmail, mailx, or mail.
|
||||||
|
USAGE
|
||||||
|
}
|
||||||
|
|
||||||
|
die() {
|
||||||
|
printf 'Error: %s\n' "$*" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup() {
|
||||||
|
if [[ -n "${TMP_DIR}" && -d "${TMP_DIR}" ]]; then
|
||||||
|
rm -rf "${TMP_DIR}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
trap cleanup EXIT
|
||||||
|
|
||||||
|
sanitize_detail() {
|
||||||
|
local text=${1:-}
|
||||||
|
text=$(printf '%s' "$text" | tr '\n' ' ' | sed -E 's/[[:space:]]+/ /g; s/^ +//; s/ +$//')
|
||||||
|
printf '%.220s' "$text"
|
||||||
|
}
|
||||||
|
|
||||||
|
extract_ssl_error() {
|
||||||
|
local raw=${1:-}
|
||||||
|
local line
|
||||||
|
|
||||||
|
line=$(printf '%s\n' "$raw" | grep -E 'Verify return code:|verify error:|unable to get local issuer certificate|self-signed certificate|certificate has expired|hostname mismatch|wrong version number|no peer certificate available|tlsv1 alert|sslv3 alert|Connection refused|connect:' | head -n1 || true)
|
||||||
|
if [[ -z "$line" ]]; then
|
||||||
|
line=$(printf '%s\n' "$raw" | tail -n5 | head -n1 || true)
|
||||||
|
fi
|
||||||
|
sanitize_detail "$line"
|
||||||
|
}
|
||||||
|
|
||||||
|
require_cmd() {
|
||||||
|
command -v "$1" >/dev/null 2>&1 || die "Missing required command: $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
parse_args() {
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
--repo)
|
||||||
|
REPO_URL=${2:?missing value for --repo}
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--branch)
|
||||||
|
BRANCH=${2:?missing value for --branch}
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--checkout-dir)
|
||||||
|
CHECKOUT_DIR=${2:?missing value for --checkout-dir}
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--servlist)
|
||||||
|
SERVLIST_PATH=${2:?missing value for --servlist}
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--email-to)
|
||||||
|
EMAIL_TO=${2:?missing value for --email-to}
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--email-from)
|
||||||
|
EMAIL_FROM=${2:?missing value for --email-from}
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--subject-prefix)
|
||||||
|
SUBJECT_PREFIX=${2:?missing value for --subject-prefix}
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--connect-timeout)
|
||||||
|
CONNECT_TIMEOUT=${2:?missing value for --connect-timeout}
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--ssl-timeout)
|
||||||
|
SSL_TIMEOUT=${2:?missing value for --ssl-timeout}
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--plain-port)
|
||||||
|
PLAIN_PORT=${2:?missing value for --plain-port}
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--ssl-port)
|
||||||
|
SSL_PORT=${2:?missing value for --ssl-port}
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--no-clone)
|
||||||
|
DO_CLONE=0
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--no-email)
|
||||||
|
DO_EMAIL=0
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-h|--help)
|
||||||
|
usage
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
die "Unknown argument: $1"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ -n "${SERVLIST_PATH}" && -z "${REPO_URL}" ]]; then
|
||||||
|
DO_CLONE=0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ${DO_CLONE} -eq 1 && -z "${REPO_URL}" && -z "${SERVLIST_PATH}" ]]; then
|
||||||
|
die "Provide --repo or --servlist"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ${DO_CLONE} -eq 0 && -z "${SERVLIST_PATH}" ]]; then
|
||||||
|
die "--no-clone requires --servlist"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ${DO_EMAIL} -eq 1 && -z "${EMAIL_TO}" ]]; then
|
||||||
|
die "Provide --email-to, or use --no-email for testing"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
prepare_workspace() {
|
||||||
|
TMP_DIR=$(mktemp -d)
|
||||||
|
REPORT_FILE="${TMP_DIR}/report.txt"
|
||||||
|
ROWS_FILE="${TMP_DIR}/rows.tsv"
|
||||||
|
}
|
||||||
|
|
||||||
|
clone_or_update_repo() {
|
||||||
|
[[ ${DO_CLONE} -eq 1 ]] || return 0
|
||||||
|
|
||||||
|
require_cmd git
|
||||||
|
|
||||||
|
if [[ -d "${CHECKOUT_DIR}/.git" ]]; then
|
||||||
|
git -C "${CHECKOUT_DIR}" fetch --depth 1 origin "${BRANCH}"
|
||||||
|
git -C "${CHECKOUT_DIR}" checkout -q "${BRANCH}" 2>/dev/null || git -C "${CHECKOUT_DIR}" checkout -q -B "${BRANCH}" "origin/${BRANCH}"
|
||||||
|
git -C "${CHECKOUT_DIR}" reset --hard "origin/${BRANCH}" >/dev/null
|
||||||
|
else
|
||||||
|
rm -rf "${CHECKOUT_DIR}"
|
||||||
|
git clone --depth 1 --branch "${BRANCH}" "${REPO_URL}" "${CHECKOUT_DIR}" >/dev/null
|
||||||
|
fi
|
||||||
|
|
||||||
|
COMMIT_REF=$(git -C "${CHECKOUT_DIR}" rev-parse --short HEAD)
|
||||||
|
SERVLIST_PATH="${CHECKOUT_DIR}/src/common/servlist.c"
|
||||||
|
}
|
||||||
|
|
||||||
|
validate_inputs() {
|
||||||
|
require_cmd awk
|
||||||
|
require_cmd grep
|
||||||
|
require_cmd sed
|
||||||
|
require_cmd openssl
|
||||||
|
require_cmd timeout
|
||||||
|
|
||||||
|
[[ -f "${SERVLIST_PATH}" ]] || die "servlist.c not found: ${SERVLIST_PATH}"
|
||||||
|
}
|
||||||
|
|
||||||
|
parse_servlist() {
|
||||||
|
awk '
|
||||||
|
function clean_comment(s) {
|
||||||
|
gsub(/^[[:space:]]*\/\*[[:space:]]*/, "", s)
|
||||||
|
gsub(/[[:space:]]*\*\/[[:space:]]*$/, "", s)
|
||||||
|
gsub(/[[:space:]]+/, " ", s)
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
/static const struct defaultserver def\[\]/ {
|
||||||
|
in_def = 1
|
||||||
|
next
|
||||||
|
}
|
||||||
|
|
||||||
|
!in_def { next }
|
||||||
|
|
||||||
|
/^[[:space:]]*#(if|ifdef|ifndef|else|elif|endif)/ { next }
|
||||||
|
/^[[:space:]]*\};/ { exit }
|
||||||
|
|
||||||
|
/^[[:space:]]*\/\*/ {
|
||||||
|
last_comment = clean_comment($0)
|
||||||
|
next
|
||||||
|
}
|
||||||
|
|
||||||
|
/^[[:space:]]*\{[[:space:]]*0[[:space:]]*,[[:space:]]*0[[:space:]]*\}[[:space:]]*,?[[:space:]]*$/ {
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
|
||||||
|
/^[[:space:]]*\{[[:space:]]*"/ {
|
||||||
|
line = $0
|
||||||
|
sub(/^[[:space:]]*\{[[:space:]]*"/, "", line)
|
||||||
|
split(line, parts, /"/)
|
||||||
|
current_network = parts[1]
|
||||||
|
current_ssl = ($0 ~ /,[[:space:]]*TRUE[[:space:]]*\}[[:space:]]*,?[[:space:]]*$/) ? 1 : 0
|
||||||
|
last_comment = ""
|
||||||
|
next
|
||||||
|
}
|
||||||
|
|
||||||
|
/^[[:space:]]*\{[[:space:]]*0[[:space:]]*,[[:space:]]*"/ {
|
||||||
|
line = $0
|
||||||
|
sub(/^[[:space:]]*\{[[:space:]]*0[[:space:]]*,[[:space:]]*"/, "", line)
|
||||||
|
split(line, parts, /"/)
|
||||||
|
gsub(/\t/, " ", last_comment)
|
||||||
|
printf "%s\t%s\t%s\t%s\n", current_network, current_ssl, parts[1], last_comment
|
||||||
|
last_comment = ""
|
||||||
|
next
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
last_comment = ""
|
||||||
|
}
|
||||||
|
' "${SERVLIST_PATH}"
|
||||||
|
}
|
||||||
|
|
||||||
|
scan_server() {
|
||||||
|
local network=$1
|
||||||
|
local ssl_default=$2
|
||||||
|
local hostspec=$3
|
||||||
|
local note=${4:-}
|
||||||
|
|
||||||
|
local host="$hostspec"
|
||||||
|
local port=""
|
||||||
|
local port_part=""
|
||||||
|
local explicit_ssl=0
|
||||||
|
local ssl_expected=$ssl_default
|
||||||
|
local tcp_status="FAIL"
|
||||||
|
local tcp_detail=""
|
||||||
|
local ssl_status="N/A"
|
||||||
|
local ssl_detail="-"
|
||||||
|
local ssl_raw=""
|
||||||
|
local tcp_raw=""
|
||||||
|
local tcp_rc=0
|
||||||
|
local ssl_rc=0
|
||||||
|
local verify_line=""
|
||||||
|
local cert_block=""
|
||||||
|
local cert_meta=""
|
||||||
|
local enddate=""
|
||||||
|
local expires_note=""
|
||||||
|
|
||||||
|
if [[ "$hostspec" == */* ]]; then
|
||||||
|
host=${hostspec%/*}
|
||||||
|
port_part=${hostspec##*/}
|
||||||
|
if [[ "$port_part" == +* ]]; then
|
||||||
|
explicit_ssl=1
|
||||||
|
port=${port_part#+}
|
||||||
|
else
|
||||||
|
port=$port_part
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ${explicit_ssl} -eq 1 ]]; then
|
||||||
|
ssl_expected=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z "$port" ]]; then
|
||||||
|
if [[ ${ssl_expected} -eq 1 ]]; then
|
||||||
|
port=$SSL_PORT
|
||||||
|
else
|
||||||
|
port=$PLAIN_PORT
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
set +e
|
||||||
|
tcp_raw=$(timeout "${CONNECT_TIMEOUT}" bash -c "exec 3<>/dev/tcp/${host}/${port}" 2>&1)
|
||||||
|
tcp_rc=$?
|
||||||
|
set -e
|
||||||
|
|
||||||
|
if [[ ${tcp_rc} -eq 0 ]]; then
|
||||||
|
tcp_status="OK"
|
||||||
|
tcp_detail="connected"
|
||||||
|
elif [[ ${tcp_rc} -eq 124 ]]; then
|
||||||
|
tcp_detail="timeout"
|
||||||
|
else
|
||||||
|
tcp_detail=$(sanitize_detail "$tcp_raw")
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ${ssl_expected} -eq 1 ]]; then
|
||||||
|
if [[ "$tcp_status" != "OK" ]]; then
|
||||||
|
ssl_status="SKIPPED"
|
||||||
|
ssl_detail="tcp failed"
|
||||||
|
else
|
||||||
|
set +e
|
||||||
|
ssl_raw=$(timeout "${SSL_TIMEOUT}" openssl s_client \
|
||||||
|
-connect "${host}:${port}" \
|
||||||
|
-servername "${host}" \
|
||||||
|
-verify_return_error \
|
||||||
|
-verify_hostname "${host}" \
|
||||||
|
< /dev/null 2>&1)
|
||||||
|
ssl_rc=$?
|
||||||
|
set -e
|
||||||
|
|
||||||
|
if [[ ${ssl_rc} -eq 124 ]]; then
|
||||||
|
ssl_status="INVALID"
|
||||||
|
ssl_detail="tls timeout"
|
||||||
|
else
|
||||||
|
verify_line=$(printf '%s\n' "$ssl_raw" | grep -E 'Verify return code:' | tail -n1 || true)
|
||||||
|
cert_block=$(printf '%s\n' "$ssl_raw" | awk '
|
||||||
|
/-----BEGIN CERTIFICATE-----/ { found = 1 }
|
||||||
|
found { print }
|
||||||
|
/-----END CERTIFICATE-----/ { exit }
|
||||||
|
')
|
||||||
|
|
||||||
|
if [[ -n "$cert_block" ]]; then
|
||||||
|
cert_meta=$(printf '%s\n' "$cert_block" | openssl x509 -noout -enddate 2>/dev/null || true)
|
||||||
|
enddate=$(printf '%s\n' "$cert_meta" | sed -n 's/^notAfter=//p' | head -n1)
|
||||||
|
if [[ -n "$enddate" ]]; then
|
||||||
|
expires_note="expires ${enddate}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if printf '%s\n' "$ssl_raw" | grep -q 'Verify return code: 0 (ok)'; then
|
||||||
|
ssl_status="VALID"
|
||||||
|
ssl_detail="ok"
|
||||||
|
else
|
||||||
|
ssl_status="INVALID"
|
||||||
|
ssl_detail=$(extract_ssl_error "$ssl_raw")
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -n "$verify_line" && "$ssl_status" != "VALID" ]]; then
|
||||||
|
ssl_detail=$(sanitize_detail "$verify_line")
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -n "$expires_note" ]]; then
|
||||||
|
ssl_detail="${ssl_detail}; ${expires_note}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
printf '%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n' \
|
||||||
|
"$network" \
|
||||||
|
"$host" \
|
||||||
|
"$port" \
|
||||||
|
"$ssl_expected" \
|
||||||
|
"$tcp_status" \
|
||||||
|
"$ssl_status" \
|
||||||
|
"$ssl_detail" \
|
||||||
|
"$note"
|
||||||
|
}
|
||||||
|
|
||||||
|
build_report() {
|
||||||
|
local total=0
|
||||||
|
local tcp_ok=0
|
||||||
|
local tcp_fail=0
|
||||||
|
local ssl_expected_count=0
|
||||||
|
local ssl_valid=0
|
||||||
|
local ssl_invalid=0
|
||||||
|
local issue_count=0
|
||||||
|
local scan_status="CLEAN"
|
||||||
|
local repo_display="${REPO_URL:-local file}"
|
||||||
|
local generated_at
|
||||||
|
local host_name
|
||||||
|
generated_at=$(date '+%Y-%m-%d %H:%M:%S %Z')
|
||||||
|
host_name=$(hostname -f 2>/dev/null || hostname)
|
||||||
|
|
||||||
|
while IFS=$'\t' read -r network ssl_default hostspec note; do
|
||||||
|
[[ -n "$network" ]] || continue
|
||||||
|
scan_server "$network" "$ssl_default" "$hostspec" "$note" >> "${ROWS_FILE}"
|
||||||
|
done < <(parse_servlist)
|
||||||
|
|
||||||
|
while IFS=$'\t' read -r network host port ssl_expected tcp_status ssl_status ssl_detail note; do
|
||||||
|
((total += 1))
|
||||||
|
|
||||||
|
if [[ "$tcp_status" == "OK" ]]; then
|
||||||
|
((tcp_ok += 1))
|
||||||
|
else
|
||||||
|
((tcp_fail += 1))
|
||||||
|
((issue_count += 1))
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$ssl_expected" == "1" ]]; then
|
||||||
|
((ssl_expected_count += 1))
|
||||||
|
if [[ "$ssl_status" == "VALID" ]]; then
|
||||||
|
((ssl_valid += 1))
|
||||||
|
else
|
||||||
|
((ssl_invalid += 1))
|
||||||
|
((issue_count += 1))
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done < "${ROWS_FILE}"
|
||||||
|
|
||||||
|
if [[ ${issue_count} -gt 0 ]]; then
|
||||||
|
scan_status="ISSUES"
|
||||||
|
fi
|
||||||
|
|
||||||
|
{
|
||||||
|
printf 'ZoiteChat servlist scan report\n'
|
||||||
|
printf 'Status: %s\n' "$scan_status"
|
||||||
|
printf 'Generated: %s\n' "$generated_at"
|
||||||
|
printf 'Runner: %s\n' "$host_name"
|
||||||
|
printf 'Repo: %s\n' "$repo_display"
|
||||||
|
printf 'Branch: %s\n' "$BRANCH"
|
||||||
|
printf 'Commit: %s\n' "$COMMIT_REF"
|
||||||
|
printf 'servlist: %s\n' "$SERVLIST_PATH"
|
||||||
|
printf '\n'
|
||||||
|
printf 'Summary\n'
|
||||||
|
printf ' Total servers scanned : %d\n' "$total"
|
||||||
|
printf ' TCP reachable : %d\n' "$tcp_ok"
|
||||||
|
printf ' TCP failed : %d\n' "$tcp_fail"
|
||||||
|
printf ' SSL expected : %d\n' "$ssl_expected_count"
|
||||||
|
printf ' SSL valid : %d\n' "$ssl_valid"
|
||||||
|
printf ' SSL invalid/skipped : %d\n' "$ssl_invalid"
|
||||||
|
printf '\n'
|
||||||
|
printf '%-18s %-34s %-6s %-4s %-5s %-8s %s\n' 'Network' 'Server' 'Port' 'SSL' 'TCP' 'TLS' 'Details'
|
||||||
|
printf '%-18s %-34s %-6s %-4s %-5s %-8s %s\n' '------------------' '----------------------------------' '------' '----' '-----' '--------' '-------'
|
||||||
|
|
||||||
|
while IFS=$'\t' read -r network host port ssl_expected tcp_status ssl_status ssl_detail note; do
|
||||||
|
local detail="$ssl_detail"
|
||||||
|
if [[ "$ssl_expected" != "1" ]]; then
|
||||||
|
detail="$tcp_status"
|
||||||
|
fi
|
||||||
|
if [[ -n "$note" ]]; then
|
||||||
|
detail="${detail} | comment: ${note}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
printf '%-18.18s %-34.34s %-6s %-4s %-5s %-8s %s\n' \
|
||||||
|
"$network" \
|
||||||
|
"$host" \
|
||||||
|
"$port" \
|
||||||
|
"$([[ "$ssl_expected" == "1" ]] && printf 'yes' || printf 'no')" \
|
||||||
|
"$tcp_status" \
|
||||||
|
"$ssl_status" \
|
||||||
|
"$detail"
|
||||||
|
done < "${ROWS_FILE}"
|
||||||
|
} > "${REPORT_FILE}"
|
||||||
|
}
|
||||||
|
|
||||||
|
send_report() {
|
||||||
|
[[ ${DO_EMAIL} -eq 1 ]] || return 0
|
||||||
|
|
||||||
|
local status_word="CLEAN"
|
||||||
|
local subject=""
|
||||||
|
|
||||||
|
if grep -q '^Status: ISSUES$' "${REPORT_FILE}"; then
|
||||||
|
status_word="ISSUES"
|
||||||
|
fi
|
||||||
|
|
||||||
|
subject="${SUBJECT_PREFIX} [${status_word}] $(date '+%Y-%m-%d')"
|
||||||
|
|
||||||
|
if command -v sendmail >/dev/null 2>&1; then
|
||||||
|
{
|
||||||
|
printf 'To: %s\n' "$EMAIL_TO"
|
||||||
|
printf 'From: %s\n' "$EMAIL_FROM"
|
||||||
|
printf 'Subject: %s\n' "$subject"
|
||||||
|
printf 'Date: %s\n' "$(LC_ALL=C date -R)"
|
||||||
|
printf 'MIME-Version: 1.0\n'
|
||||||
|
printf 'Content-Type: text/plain; charset=UTF-8\n'
|
||||||
|
printf '\n'
|
||||||
|
cat "${REPORT_FILE}"
|
||||||
|
} | sendmail -t
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if command -v mailx >/dev/null 2>&1; then
|
||||||
|
mailx -r "$EMAIL_FROM" -s "$subject" "$EMAIL_TO" < "${REPORT_FILE}"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if command -v mail >/dev/null 2>&1; then
|
||||||
|
if mail --help 2>&1 | grep -q -- ' -r'; then
|
||||||
|
mail -r "$EMAIL_FROM" -s "$subject" "$EMAIL_TO" < "${REPORT_FILE}"
|
||||||
|
else
|
||||||
|
mail -s "$subject" "$EMAIL_TO" < "${REPORT_FILE}"
|
||||||
|
fi
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
die "No supported mailer found. Install sendmail, mailx, or mail."
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
parse_args "$@"
|
||||||
|
prepare_workspace
|
||||||
|
clone_or_update_repo
|
||||||
|
validate_inputs
|
||||||
|
build_report
|
||||||
|
cat "${REPORT_FILE}"
|
||||||
|
send_report
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
||||||
Reference in New Issue
Block a user