Compare commits

..

1 Commits

Author SHA1 Message Date
Patrick Griffis
d68c3e7ead WIP: Use GSocketClient for IRC connections
TODO:
- Proxy support (some will be lost along the way)
- Remove all OpenSSL usage from fe-gtk?
- DCC support?
2021-07-13 22:09:26 -05:00
76 changed files with 837 additions and 2221 deletions

View File

@ -1,7 +1,7 @@
name: Flatpak Build name: Flatpak Build
on: [push, pull_request] on: [push, pull_request]
jobs: jobs:
flatpak_build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
container: container:
image: bilelmoussaoui/flatpak-github-actions:gnome-40 image: bilelmoussaoui/flatpak-github-actions:gnome-40

View File

@ -1,41 +0,0 @@
name: MSYS2 Build
on: [push, pull_request]
jobs:
msys2_build:
runs-on: windows-latest
defaults:
run:
shell: msys2 {0}
steps:
- uses: actions/checkout@v2
- uses: msys2/setup-msys2@v2
with:
install: >-
mingw-w64-x86_64-gcc
mingw-w64-x86_64-pkg-config
mingw-w64-x86_64-python3-cffi
mingw-w64-x86_64-meson
mingw-w64-x86_64-gtk2
mingw-w64-x86_64-gtk-update-icon-cache
mingw-w64-x86_64-luajit
mingw-w64-x86_64-desktop-file-utils
- name: Configure
run: >-
meson build
-Dtext-frontend=true
-Ddbus=disabled
-Dwith-upd=false
-Dwith-perl=false
- name: Build
run: ninja -C build
- name: Test
run: ninja -C build test
- name: Install
run: ninja -C build install

View File

@ -1,7 +1,7 @@
name: Ubuntu Build name: Ubuntu Build
on: [push, pull_request] on: [push, pull_request]
jobs: jobs:
ubuntu_build: build:
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
steps: steps:
@ -10,7 +10,7 @@ jobs:
- name: Install Dependencies - name: Install Dependencies
run: | run: |
sudo apt-get update sudo apt-get update
sudo apt-get install -y meson libcanberra-dev libdbus-glib-1-dev libglib2.0-dev libgtk2.0-dev libluajit-5.1-dev libpci-dev libperl-dev libssl-dev python3-dev python3-cffi mono-devel desktop-file-utils sudo apt-get install -y meson libcanberra-dev libdbus-glib-1-dev libglib2.0-dev libgtk2.0-dev libluajit-5.1-dev libpci-dev libperl-dev libproxy-dev libssl-dev python3-dev python3-cffi mono-devel desktop-file-utils
- name: Configure - name: Configure
run: meson build -Dtext=true -Dtheme-manager=true -Dauto_features=enabled run: meson build -Dtext=true -Dtheme-manager=true -Dauto_features=enabled

View File

@ -2,7 +2,7 @@ name: Windows Build
on: [push, pull_request] on: [push, pull_request]
jobs: jobs:
windows_build: build:
runs-on: windows-2019 runs-on: windows-2019
strategy: strategy:
matrix: matrix:
@ -28,7 +28,7 @@ jobs:
Invoke-WebRequest https://dl.hexchat.net/misc/idpsetup-1.5.1.exe -OutFile deps\idpsetup.exe Invoke-WebRequest https://dl.hexchat.net/misc/idpsetup-1.5.1.exe -OutFile deps\idpsetup.exe
& deps\idpsetup.exe /VERYSILENT & deps\idpsetup.exe /VERYSILENT
Invoke-WebRequest https://dl.hexchat.net/gtk/gtk-${{ matrix.platform }}-2018-08-29-openssl1.1.7z -OutFile deps\gtk-${{ matrix.arch }}.7z Invoke-WebRequest https://dl.hexchat.net/gtk/gtk-${{ matrix.platform }}-2018-08-29.7z -OutFile deps\gtk-${{ matrix.arch }}.7z
& 7z.exe x deps\gtk-${{ matrix.arch }}.7z -oC:\gtk-build\gtk & 7z.exe x deps\gtk-${{ matrix.arch }}.7z -oC:\gtk-build\gtk
Invoke-WebRequest https://dl.hexchat.net/gtk-win32/gendef-20111031.7z -OutFile deps\gendef.7z Invoke-WebRequest https://dl.hexchat.net/gtk-win32/gendef-20111031.7z -OutFile deps\gendef.7z
@ -41,11 +41,11 @@ jobs:
& 7z.exe x deps\perl-${{ matrix.arch }}.7z -oC:\gtk-build\perl-5.20\${{ matrix.platform }} & 7z.exe x deps\perl-${{ matrix.arch }}.7z -oC:\gtk-build\perl-5.20\${{ matrix.platform }}
New-Item -Path "c:\gtk-build" -Name "python-2.7" -ItemType "Directory" New-Item -Path "c:\gtk-build" -Name "python-2.7" -ItemType "Directory"
New-Item -Path "c:\gtk-build" -Name "python-3.8" -ItemType "Directory" New-Item -Path "c:\gtk-build" -Name "python-3.6" -ItemType "Directory"
New-Item -Path "c:\gtk-build\python-2.7" -Name "${{ matrix.platform }}" -ItemType "SymbolicLink" -Value "C:/hostedtoolcache/windows/Python/2.7.18/${{ matrix.arch }}" New-Item -Path "c:\gtk-build\python-2.7" -Name "${{ matrix.platform }}" -ItemType "SymbolicLink" -Value "C:/hostedtoolcache/windows/Python/2.7.18/${{ matrix.arch }}"
New-Item -Path "c:\gtk-build\python-3.8" -Name "${{ matrix.platform }}" -ItemType "SymbolicLink" -Value "C:/hostedtoolcache/windows/Python/3.8.10/${{ matrix.arch }}" New-Item -Path "c:\gtk-build\python-3.6" -Name "${{ matrix.platform }}" -ItemType "SymbolicLink" -Value "C:/hostedtoolcache/windows/Python/3.6.8/${{ matrix.arch }}"
C:/hostedtoolcache/windows/Python/3.8.10/${{ matrix.arch }}/python.exe -m pip install cffi C:/hostedtoolcache/windows/Python/3.6.8/${{ matrix.arch }}/python.exe -m pip install cffi
C:/hostedtoolcache/windows/Python/2.7.18/${{ matrix.arch }}/python.exe -m pip install -qq cffi C:/hostedtoolcache/windows/Python/2.7.18/${{ matrix.arch }}/python.exe -m pip install -qq cffi
shell: powershell shell: powershell

View File

@ -1,11 +1,9 @@
icondir = join_paths(get_option('datadir'), 'icons/hicolor') icondir = join_paths(get_option('datadir'), 'icons/hicolor')
install_data( install_data(
'hexchat.png', 'hexchat.png',
rename: 'io.github.Hexchat.png',
install_dir: join_paths(icondir, '48x48/apps') install_dir: join_paths(icondir, '48x48/apps')
) )
install_data( install_data(
'hexchat.svg', 'hexchat.svg',
rename: 'io.github.Hexchat.svg',
install_dir: join_paths(icondir, 'scalable/apps') install_dir: join_paths(icondir, 'scalable/apps')
) )

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<component type="addon"> <component type="addon">
<id>io.github.Hexchat.Plugin.@NAME@</id> <id>io.github.Hexchat.Plugin.@NAME@</id>
<extends>io.github.Hexchat</extends> <extends>io.github.Hexchat.desktop</extends>
<name>@NAME@ Plugin</name> <name>@NAME@ Plugin</name>
<summary>@SUMMARY@</summary> <summary>@SUMMARY@</summary>
<url type="homepage">https://hexchat.github.io/</url> <url type="homepage">https://hexchat.github.io/</url>

View File

@ -1,8 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<component type="desktop-application"> <component type="desktop">
<id>io.github.Hexchat</id> <id>io.github.Hexchat.desktop</id>
<name>HexChat</name> <name>HexChat</name>
<launchable type="desktop-id">io.github.Hexchat.desktop</launchable>
<developer_name>HexChat</developer_name> <developer_name>HexChat</developer_name>
<metadata_license>CC0-1.0</metadata_license> <metadata_license>CC0-1.0</metadata_license>
<project_license>GPL-2.0+</project_license> <project_license>GPL-2.0+</project_license>
@ -27,35 +26,6 @@
<id>hexchat.desktop</id> <id>hexchat.desktop</id>
</provides> </provides>
<releases> <releases>
<release date="2022-02-12" version="2.16.1">
<description>
<p>This is a minor release with mostly bug-fixes:</p>
<ul>
<li>Add `-NOOVERRIDE` flag to the `GUI COLOR` command</li>
<li>Add `-q` (quiet) flag to the `EXECWRITE` command</li>
<li>Rename installed icon to match app-id (Fixes notification icon)</li>
<li>Fix escaping already escaped URLs when opening them</li>
<li>Fix Python scripts not being opened as UTF-8</li>
<li>Fix `TIMER` command supporting decimals regardless of locale</li>
</ul>
</description>
</release>
<release date="2021-10-01" version="2.16.0">
<description>
<p>This is a feature release:</p>
<ul>
<li>Add support for IRCv3 SETNAME, invite-notify, account-tag, standard replies, and UTF8ONLY</li>
<li>Add support for strikethrough formatting</li>
<li>Fix text clipping issues by respecting font line height</li>
<li>Fix URLs not being escaped when opened</li>
<li>Fix possible hang when showing notifications</li>
<li>Print ChanServ notices in the front tab by default</li>
<li>Update network list</li>
<li>python: Rewrite plugin improving memory usage and compatibility</li>
<li>fishlim: Add support for CBC and other improvements</li>
</ul>
</description>
</release>
<release date="2019-12-20" version="2.14.3"> <release date="2019-12-20" version="2.14.3">
<description> <description>
<p>This is a bug-fix release:</p> <p>This is a bug-fix release:</p>

View File

@ -4,7 +4,7 @@ GenericName=IRC Client
Comment=Chat with other people online Comment=Chat with other people online
Keywords=IM;Chat; Keywords=IM;Chat;
Exec=@exec_command@ Exec=@exec_command@
Icon=io.github.Hexchat Icon=hexchat
Terminal=false Terminal=false
Type=Application Type=Application
Categories=GTK;Network;IRCClient; Categories=GTK;Network;IRCClient;

View File

@ -5,6 +5,7 @@
"runtime-version": "40", "runtime-version": "40",
"sdk": "org.gnome.Sdk", "sdk": "org.gnome.Sdk",
"command": "hexchat", "command": "hexchat",
"rename-icon": "hexchat",
"finish-args": [ "finish-args": [
"--share=ipc", "--share=ipc",
"--socket=x11", "--socket=x11",
@ -30,7 +31,7 @@
"modules": [ "modules": [
"shared-modules/gtk2/gtk2.json", "shared-modules/gtk2/gtk2.json",
"shared-modules/gtk2/gtk2-common-themes.json", "shared-modules/gtk2/gtk2-common-themes.json",
"shared-modules/dbus-glib/dbus-glib.json", "shared-modules/dbus-glib/dbus-glib-0.110.json",
"shared-modules/lua5.3/lua-5.3.5.json", "shared-modules/lua5.3/lua-5.3.5.json",
"shared-modules/libcanberra/libcanberra.json", "shared-modules/libcanberra/libcanberra.json",
"python3-cffi.json", "python3-cffi.json",

@ -1 +1 @@
Subproject commit 2c2f8fef2e926ff03158c0b3341526cce1b405ac Subproject commit 45cc381cdb43da1f22bc61baba4e390792eb5f8b

View File

@ -1,5 +1,5 @@
project('hexchat', 'c', project('hexchat', 'c',
version: '2.16.1', version: '2.14.3',
meson_version: '>= 0.47.0', meson_version: '>= 0.47.0',
default_options: [ default_options: [
'c_std=gnu89', 'c_std=gnu89',
@ -13,7 +13,7 @@ gnome = import('gnome')
cc = meson.get_compiler('c') cc = meson.get_compiler('c')
libgio_dep = dependency('gio-2.0', version: '>= 2.34.0') libgio_dep = dependency('gio-2.0', version: '>= 2.44.0')
libgmodule_dep = dependency('gmodule-2.0') libgmodule_dep = dependency('gmodule-2.0')
libcanberra_dep = dependency('libcanberra', version: '>= 0.22', libcanberra_dep = dependency('libcanberra', version: '>= 0.22',
@ -22,7 +22,7 @@ dbus_glib_dep = dependency('dbus-glib-1', required: get_option('dbus'))
global_deps = [] global_deps = []
if cc.get_id() == 'msvc' if cc.get_id() == 'msvc'
libssl_dep = cc.find_library('libssl') libssl_dep = cc.find_library('libeay32')
else else
libssl_dep = dependency('openssl', version: '>= 0.9.8', libssl_dep = dependency('openssl', version: '>= 0.9.8',
required: get_option('tls')) required: get_option('tls'))
@ -34,7 +34,6 @@ config_h.set_quoted('PACKAGE_NAME', meson.project_name())
config_h.set_quoted('GETTEXT_PACKAGE', 'hexchat') config_h.set_quoted('GETTEXT_PACKAGE', 'hexchat')
config_h.set_quoted('LOCALEDIR', join_paths(get_option('prefix'), config_h.set_quoted('LOCALEDIR', join_paths(get_option('prefix'),
get_option('datadir'), 'locale')) get_option('datadir'), 'locale'))
config_h.set_quoted('G_LOG_DOMAIN', 'hexchat')
config_h.set10('ENABLE_NLS', true) config_h.set10('ENABLE_NLS', true)
# Optional features # Optional features
@ -47,8 +46,8 @@ config_h.set('G_DISABLE_SINGLE_INCLUDES', true)
config_h.set('GTK_DISABLE_DEPRECATED', true) config_h.set('GTK_DISABLE_DEPRECATED', true)
config_h.set('GTK_DISABLE_SINGLE_INCLUDES', true) config_h.set('GTK_DISABLE_SINGLE_INCLUDES', true)
config_h.set('GDK_PIXBUF_DISABLE_SINGLE_INCLUDES', true) config_h.set('GDK_PIXBUF_DISABLE_SINGLE_INCLUDES', true)
config_h.set('GLIB_VERSION_MAX_ALLOWED', 'GLIB_VERSION_2_34') config_h.set('GLIB_VERSION_MAX_ALLOWED', 'GLIB_VERSION_2_44')
config_h.set('GLIB_VERSION_MIN_REQUIRED', 'GLIB_VERSION_2_34') config_h.set('GLIB_VERSION_MIN_REQUIRED', 'GLIB_VERSION_2_44')
# Detected features # Detected features
config_h.set('HAVE_MEMRCHR', cc.has_function('memrchr')) config_h.set('HAVE_MEMRCHR', cc.has_function('memrchr'))

View File

@ -3,5 +3,4 @@ shared_module('checksum', 'checksum.c',
install: true, install: true,
install_dir: plugindir, install_dir: plugindir,
name_prefix: '', name_prefix: '',
vs_module_defs: 'checksum.def',
) )

View File

@ -1,6 +1,5 @@
shared_module('exec', 'exec.c', shared_module('exec', 'exec.c',
dependencies: hexchat_plugin_dep, dependencies: hexchat_plugin_dep,
install: true, install: true,
install_dir: plugindir, install_dir: plugindir
vs_module_defs: 'exec.def',
) )

View File

@ -87,54 +87,6 @@ static const signed char fish_unbase64[256] = {
dest |= (uint8_t)*((source)++); \ dest |= (uint8_t)*((source)++); \
} while (0); } while (0);
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
#include <openssl/provider.h>
static OSSL_PROVIDER *legacy_provider;
static OSSL_PROVIDER *default_provider;
static OSSL_LIB_CTX *ossl_ctx;
#endif
int fish_init(void)
{
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
ossl_ctx = OSSL_LIB_CTX_new();
if (!ossl_ctx)
return 0;
legacy_provider = OSSL_PROVIDER_load(ossl_ctx, "legacy");
if (!legacy_provider) {
fish_deinit();
return 0;
}
default_provider = OSSL_PROVIDER_load(ossl_ctx, "default");
if (!default_provider) {
fish_deinit();
return 0;
}
#endif
return 1;
}
void fish_deinit(void)
{
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
if (legacy_provider) {
OSSL_PROVIDER_unload(legacy_provider);
legacy_provider = NULL;
}
if (default_provider) {
OSSL_PROVIDER_unload(default_provider);
default_provider = NULL;
}
if (ossl_ctx) {
OSSL_LIB_CTX_free(ossl_ctx);
ossl_ctx = NULL;
}
#endif
}
/** /**
* Encode ECB FiSH Base64 * Encode ECB FiSH Base64
@ -276,19 +228,9 @@ char *fish_cipher(const char *plaintext, size_t plaintext_len, const char *key,
plaintext_len -= 8; plaintext_len -= 8;
} }
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
cipher = EVP_CIPHER_fetch(ossl_ctx, "BF-CBC", NULL);
#else
cipher = (EVP_CIPHER *) EVP_bf_cbc(); cipher = (EVP_CIPHER *) EVP_bf_cbc();
#endif
} else if (mode == EVP_CIPH_ECB_MODE) { } else if (mode == EVP_CIPH_ECB_MODE) {
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
cipher = EVP_CIPHER_fetch(ossl_ctx, "BF-ECB", NULL);
#else
cipher = (EVP_CIPHER *) EVP_bf_ecb(); cipher = (EVP_CIPHER *) EVP_bf_ecb();
#endif
} }
/* Zero Padding */ /* Zero Padding */

View File

@ -35,8 +35,6 @@ enum fish_mode {
FISH_CBC_MODE = 0x2 FISH_CBC_MODE = 0x2
}; };
int fish_init(void);
void fish_deinit(void);
char *fish_base64_encode(const char *message, size_t message_len); char *fish_base64_encode(const char *message, size_t message_len);
char *fish_base64_decode(const char *message, size_t *final_len); char *fish_base64_decode(const char *message, size_t *final_len);
char *fish_encrypt(const char *key, size_t keylen, const char *message, size_t message_len, enum fish_mode mode); char *fish_encrypt(const char *key, size_t keylen, const char *message, size_t message_len, enum fish_mode mode);

View File

@ -29,7 +29,7 @@
</PropertyGroup> </PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile> <ClCompile>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;FISHLIM_EXPORTS;HAVE_DH_SET0_PQG;HAVE_DH_GET0_KEY;HAVE_DH_SET0_KEY;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;FISHLIM_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(DepsRoot)\include;$(Glib);..\..\src\common;$(HexChatLib);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>$(DepsRoot)\include;$(Glib);..\..\src\common;$(HexChatLib);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile> </ClCompile>
<Link> <Link>
@ -40,7 +40,7 @@
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile> <ClCompile>
<PreprocessorDefinitions>WIN32;_WIN64;_AMD64_;NDEBUG;_WINDOWS;_USRDLL;FISHLIM_EXPORTS;HAVE_DH_SET0_PQG;HAVE_DH_GET0_KEY;HAVE_DH_SET0_KEY;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>WIN32;_WIN64;_AMD64_;NDEBUG;_WINDOWS;_USRDLL;FISHLIM_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(DepsRoot)\include;$(Glib);..\..\src\common;$(HexChatLib);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>$(DepsRoot)\include;$(Glib);..\..\src\common;$(HexChatLib);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile> </ClCompile>
<Link> <Link>

View File

@ -19,5 +19,4 @@ shared_module('fishlim', fishlim_sources,
install: true, install: true,
install_dir: plugindir, install_dir: plugindir,
name_prefix: '', name_prefix: '',
vs_module_defs: 'fishlim.def',
) )

View File

@ -815,9 +815,6 @@ int hexchat_plugin_init(hexchat_plugin *plugin_handle,
hexchat_hook_server_attrs(ph, "TOPIC", HEXCHAT_PRI_NORM, handle_incoming, NULL); hexchat_hook_server_attrs(ph, "TOPIC", HEXCHAT_PRI_NORM, handle_incoming, NULL);
hexchat_hook_server_attrs(ph, "332", HEXCHAT_PRI_NORM, handle_incoming, NULL); hexchat_hook_server_attrs(ph, "332", HEXCHAT_PRI_NORM, handle_incoming, NULL);
if (!fish_init())
return 0;
if (!dh1080_init()) if (!dh1080_init())
return 0; return 0;
@ -831,7 +828,6 @@ int hexchat_plugin_init(hexchat_plugin *plugin_handle,
int hexchat_plugin_deinit(void) { int hexchat_plugin_deinit(void) {
g_clear_pointer(&pending_exchanges, g_hash_table_destroy); g_clear_pointer(&pending_exchanges, g_hash_table_destroy);
dh1080_deinit(); dh1080_deinit();
fish_deinit();
hexchat_printf(ph, "%s plugin unloaded\n", plugin_name); hexchat_printf(ph, "%s plugin unloaded\n", plugin_name);
return 1; return 1;

View File

@ -1,4 +1,5 @@
/* /*
Copyright (c) 2010 Samuel Lidén Borell <samuel@kodafritt.se> Copyright (c) 2010 Samuel Lidén Borell <samuel@kodafritt.se>
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
@ -21,31 +22,26 @@
*/ */
#include "fish.h" #include "../../fish.h"
/** /**
* Extracts a key from the key store file. * Extracts a key from the key store file.
*/ */
char * char *keystore_get_key(const char *nick, enum fish_mode *mode) {
keystore_get_key(const char *nick, enum fish_mode *mode)
{
return NULL; return NULL;
} }
/** /**
* Sets a key in the key store file. * Sets a key in the key store file.
*/ */
gboolean gboolean keystore_store_key(const char *nick, const char *key, enum fish_mode mode) {
keystore_store_key(const char *nick, const char *key, enum fish_mode mode)
{
return TRUE; return TRUE;
} }
/** /**
* Deletes a nick from the key store. * Deletes a nick from the key store.
*/ */
gboolean gboolean keystore_delete_nick(const char *nick) {
keystore_delete_nick(const char *nick)
{
return TRUE; return TRUE;
} }

View File

@ -1,16 +1,17 @@
subdir('old_version')
fishlim_test_sources = [ fishlim_test_sources = [
'tests.c', 'tests.c',
'mock-keystore.c', 'fake/keystore.c',
'../fish.c', '../fish.c',
'../utils.c', '../utils.c',
] ]
fishlim_tests = executable('fishlim_tests', fishlim_test_sources, fishlim_tests = executable('fishlim_tests', fishlim_test_sources,
dependencies: [libgio_dep, libssl_dep, hexchat_plugin_dep], dependencies: [libgio_dep, libssl_dep],
include_directories: include_directories('..'), link_with : fishlim_old_lib
) )
test('Fishlim Tests', fishlim_tests, test('Fishlim Tests', fishlim_tests,
protocol: 'tap', timeout: 90
timeout: 600,
) )

View File

@ -0,0 +1,155 @@
/*
Copyright (c) 2010 Samuel Lidén Borell <samuel@kodafritt.se>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifdef __APPLE__
#define __AVAILABILITYMACROS__
#define DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER
#endif
#include <stdlib.h>
#include <string.h>
#include <openssl/blowfish.h>
#include "fish.h"
#define IB 64
static const char fish_base64[64] = "./0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
static const signed char fish_unbase64[256] = {
IB,IB,IB,IB,IB,IB,IB,IB, IB,IB,IB,IB,IB,IB,IB,IB,
IB,IB,IB,IB,IB,IB,IB,IB, IB,IB,IB,IB,IB,IB,IB,IB,
/* ! " # $ % & ' ( ) * + , - . / */
IB,IB,IB,IB,IB,IB,IB,IB, IB,IB,IB,IB,IB,IB, 0, 1,
/* 0 1 2 3 4 5 6 7 8 9 : ; < = > ? */
2, 3, 4, 5, 6, 7, 8, 9, 10,11,IB,IB,IB,IB,IB,IB,
/* @ A B C D E F G H I J K L M N O */
IB,38,39,40,41,42,43,44, 45,46,47,48,49,50,51,52,
/* P Q R S T U V W X Y Z [ \ ] ^ _*/
53,54,55,56,57,58,59,60, 61,62,63,IB,IB,IB,IB,IB,
/* ` a b c d e f g h i j k l m n o */
IB,12,13,14,15,16,17,18, 19,20,21,22,23,24,25,26,
/* p q r s t u v w x y z { | } ~ <del> */
27,28,29,30,31,32,33,34, 35,36,37,IB,IB,IB,IB,IB,
};
#define GET_BYTES(dest, source) do { \
*((dest)++) = ((source) >> 24) & 0xFF; \
*((dest)++) = ((source) >> 16) & 0xFF; \
*((dest)++) = ((source) >> 8) & 0xFF; \
*((dest)++) = (source) & 0xFF; \
} while (0);
char *__old_fish_encrypt(const char *key, size_t keylen, const char *message) {
BF_KEY bfkey;
size_t messagelen;
size_t i;
int j;
char *encrypted;
char *end;
unsigned char bit;
unsigned char word;
unsigned char d;
BF_set_key(&bfkey, keylen, (const unsigned char*)key);
messagelen = strlen(message);
if (messagelen == 0) return NULL;
encrypted = g_malloc(((messagelen - 1) / 8) * 12 + 12 + 1); /* each 8-byte block becomes 12 bytes */
end = encrypted;
while (*message) {
/* Read 8 bytes (a Blowfish block) */
BF_LONG binary[2] = { 0, 0 };
unsigned char c;
for (i = 0; i < 8; i++) {
c = message[i];
binary[i >> 2] |= c << 8*(3 - (i&3));
if (c == '\0') break;
}
message += 8;
/* Encrypt block */
BF_encrypt(binary, &bfkey);
/* Emit FiSH-BASE64 */
bit = 0;
word = 1;
for (j = 0; j < 12; j++) {
d = fish_base64[(binary[word] >> bit) & 63];
*(end++) = d;
bit += 6;
if (j == 5) {
bit = 0;
word = 0;
}
}
/* Stop if a null terminator was found */
if (c == '\0') break;
}
*end = '\0';
return encrypted;
}
char *__old_fish_decrypt(const char *key, size_t keylen, const char *data) {
BF_KEY bfkey;
size_t i;
char *decrypted;
char *end;
unsigned char bit;
unsigned char word;
unsigned char d;
BF_set_key(&bfkey, keylen, (const unsigned char*)key);
decrypted = g_malloc(strlen(data) + 1);
end = decrypted;
while (*data) {
/* Convert from FiSH-BASE64 */
BF_LONG binary[2] = { 0, 0 };
bit = 0;
word = 1;
for (i = 0; i < 12; i++) {
d = fish_unbase64[(const unsigned char)*(data++)];
if (d == IB) goto decrypt_end;
binary[word] |= (unsigned long)d << bit;
bit += 6;
if (i == 5) {
bit = 0;
word = 0;
}
}
/* Decrypt block */
BF_decrypt(binary, &bfkey);
/* Copy to buffer */
GET_BYTES(end, binary[0]);
GET_BYTES(end, binary[1]);
}
decrypt_end:
*end = '\0';
return decrypted;
}

View File

@ -0,0 +1,37 @@
/*
Copyright (c) 2010 Samuel Lidén Borell <samuel@kodafritt.se>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef FISH_OLD_H
#define FISH_OLD_H
#include <stddef.h>
#include <glib.h>
char *__old_fish_encrypt(const char *key, size_t keylen, const char *message);
char *__old_fish_decrypt(const char *key, size_t keylen, const char *data);
#endif

View File

@ -0,0 +1,4 @@
fishlim_old_lib = shared_library('fishlim_old_lib',
['fish.c'],
dependencies: [libgio_dep, libssl_dep],
)

View File

@ -1,4 +1,5 @@
/* /*
Copyright (c) 2020 <bakasura@protonmail.ch> Copyright (c) 2020 <bakasura@protonmail.ch>
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
@ -21,20 +22,22 @@
*/ */
#include <string.h> #ifndef PLUGIN_HEXCHAT_FISHLIM_TEST_H
#include <glib.h> #define PLUGIN_HEXCHAT_FISHLIM_TEST_H
#include "fish.h" // Libs
#include "utils.h" #include <glib.h>
// Project Libs
#include "../fish.h"
#include "../utils.h"
#include "old_version/fish.h"
/** /**
* Auxiliary function: Generate a random string * Auxiliary function: Generate a random string
* @param out Preallocated string to fill * @param out Preallocated string to fill
* @param len Size of bytes to fill * @param len Size of bytes to fill
*/ */
static void void random_string(char *out, size_t len) {
random_string(char *out, size_t len)
{
GRand *rand = NULL; GRand *rand = NULL;
int i = 0; int i = 0;
@ -48,14 +51,13 @@ random_string(char *out, size_t len)
g_rand_free(rand); g_rand_free(rand);
} }
/** /**
* Check encrypt and decrypt in ECB mode * Check encrypt and decrypt in ECB mode and compare with old implementation
*/ */
static void void __ecb(void) {
test_ecb(void) char *bo64 = NULL, *b64 = NULL;
{ char *deo = NULL, *de = NULL;
char *b64 = NULL;
char *de = NULL;
int key_len, message_len = 0; int key_len, message_len = 0;
char key[57]; char key[57];
char message[1000]; char message[1000];
@ -69,20 +71,36 @@ test_ecb(void)
random_string(message, message_len); random_string(message, message_len);
/* Encrypt */ /* Encrypt */
bo64 = __old_fish_encrypt(key, key_len, message);
g_assert_nonnull(bo64);
b64 = fish_encrypt(key, key_len, message, message_len, FISH_ECB_MODE); b64 = fish_encrypt(key, key_len, message, message_len, FISH_ECB_MODE);
g_assert_nonnull(b64); g_assert_nonnull(b64);
g_assert_cmpuint(g_strcmp0(b64, bo64), == , 0);
/* Decrypt */ /* Decrypt */
/* Linear */ /* Linear */
deo = __old_fish_decrypt(key, key_len, bo64);
de = fish_decrypt_str(key, key_len, b64, FISH_ECB_MODE); de = fish_decrypt_str(key, key_len, b64, FISH_ECB_MODE);
g_assert_cmpstr (de, ==, message); g_assert_nonnull(deo);
g_assert_nonnull(de);
g_assert_cmpuint(g_strcmp0(de, message), == , 0);
g_assert_cmpuint(g_strcmp0(deo, message), == , 0);
g_assert_cmpuint(g_strcmp0(de, deo), == , 0);
g_free(deo);
g_free(de); g_free(de);
/* Mixed */ /* Mixed */
de = fish_decrypt_str(key, key_len, b64, FISH_ECB_MODE); deo = __old_fish_decrypt(key, key_len, b64);
g_assert_cmpstr (de, ==, message); de = fish_decrypt_str(key, key_len, bo64, FISH_ECB_MODE);
g_assert_nonnull(deo);
g_assert_nonnull(de);
g_assert_cmpuint(g_strcmp0(de, message), == , 0);
g_assert_cmpuint(g_strcmp0(deo, message), == , 0);
g_assert_cmpuint(g_strcmp0(de, deo), == , 0);
g_free(deo);
g_free(de); g_free(de);
/* Free */
g_free(bo64);
g_free(b64); g_free(b64);
} }
} }
@ -91,9 +109,7 @@ test_ecb(void)
/** /**
* Check encrypt and decrypt in CBC mode * Check encrypt and decrypt in CBC mode
*/ */
static void void __cbc(void) {
test_cbc(void)
{
char *b64 = NULL; char *b64 = NULL;
char *de = NULL; char *de = NULL;
int key_len, message_len = 0; int key_len, message_len = 0;
@ -115,9 +131,11 @@ test_cbc(void)
/* Decrypt */ /* Decrypt */
/* Linear */ /* Linear */
de = fish_decrypt_str(key, key_len, b64, FISH_CBC_MODE); de = fish_decrypt_str(key, key_len, b64, FISH_CBC_MODE);
g_assert_cmpstr (de, ==, message); g_assert_nonnull(de);
g_assert_cmpuint(g_strcmp0(de, message), == , 0);
g_free(de); g_free(de);
/* Free */
g_free(b64); g_free(b64);
} }
} }
@ -126,49 +144,48 @@ test_cbc(void)
/** /**
* Check the calculation of final length from an encoded string in Base64 * Check the calculation of final length from an encoded string in Base64
*/ */
static void void __base64_len(void) {
test_base64_len (void)
{
char *b64 = NULL; char *b64 = NULL;
int i, message_len = 0;
char message[1000]; char message[1000];
int message_end = sizeof (message) - 1;
random_string(message, message_end); for (i = 0; i < 10; ++i) {
for (; message_end >= 0; --message_end) { for (message_len = 1; message_len < 1000; ++message_len) {
message[message_end] = '\0'; /* Truncate instead of generating new strings */ random_string(message, message_len);
b64 = g_base64_encode((const unsigned char *) message, message_end); b64 = g_base64_encode((const unsigned char *) message, message_len);
g_assert_nonnull(b64); g_assert_nonnull(b64);
g_assert_cmpuint(strlen(b64), == , base64_len(message_end)); g_assert_cmpuint(strlen(b64), == , base64_len(message_len));
g_free(b64); g_free(b64);
}
} }
} }
/** /**
* Check the calculation of final length from an encoded string in BlowcryptBase64 * Check the calculation of final length from an encoded string in BlowcryptBase64
*/ */
static void void __base64_fish_len(void) {
test_base64_fish_len (void)
{
char *b64 = NULL; char *b64 = NULL;
int message_len = 0; int i, message_len = 0;
char message[1000]; char message[1000];
for (message_len = 1; message_len < 1000; ++message_len) { for (i = 0; i < 10; ++i) {
random_string(message, message_len);
b64 = fish_base64_encode(message, message_len); for (message_len = 1; message_len < 1000; ++message_len) {
g_assert_nonnull(b64); random_string(message, message_len);
g_assert_cmpuint(strlen(b64), == , base64_fish_len(message_len)); b64 = fish_base64_encode(message, message_len);
g_free(b64); g_assert_nonnull(b64);
g_assert_cmpuint(strlen(b64), == , base64_fish_len(message_len));
g_free(b64);
}
} }
} }
/** /**
* Check the calculation of final length from an encrypted string in ECB mode * Check the calculation of final length from an encrypted string in ECB mode
*/ */
static void void __base64_ecb_len(void) {
test_base64_ecb_len(void)
{
char *b64 = NULL; char *b64 = NULL;
int key_len, message_len = 0; int key_len, message_len = 0;
char key[57]; char key[57];
@ -192,9 +209,7 @@ test_base64_ecb_len(void)
/** /**
* Check the calculation of final length from an encrypted string in CBC mode * Check the calculation of final length from an encrypted string in CBC mode
*/ */
static void void __base64_cbc_len(void) {
test_base64_cbc_len(void)
{
char *b64 = NULL; char *b64 = NULL;
int key_len, message_len = 0; int key_len, message_len = 0;
char key[57]; char key[57];
@ -218,9 +233,7 @@ test_base64_cbc_len(void)
/** /**
* Check the calculation of length limit for a plaintext in each encryption mode * Check the calculation of length limit for a plaintext in each encryption mode
*/ */
static void void __max_text_command_len(void) {
test_max_text_command_len(void)
{
int max_encoded_len, plaintext_len; int max_encoded_len, plaintext_len;
enum fish_mode mode; enum fish_mode mode;
@ -235,51 +248,50 @@ test_max_text_command_len(void)
/** /**
* Check the calculation of length limit for a plaintext in each encryption mode * Check the calculation of length limit for a plaintext in each encryption mode
*/ */
static void void __foreach_utf8_data_chunks(void) {
test_foreach_utf8_data_chunks(void)
{
GRand *rand = NULL; GRand *rand = NULL;
GString *chunks = NULL; GString *chunks = NULL;
int max_chunks_len, chunks_len; int tests, max_chunks_len, chunks_len;
char ascii_message[1001]; char ascii_message[1001];
char *data_chunk = NULL; char *data_chunk = NULL;
rand = g_rand_new(); rand = g_rand_new();
max_chunks_len = g_rand_int_range(rand, 2, 301);
random_string(ascii_message, 1000);
data_chunk = ascii_message; for (tests = 0; tests < 1000; ++tests) {
chunks = g_string_new(NULL); max_chunks_len = g_rand_int_range(rand, 2, 301);
random_string(ascii_message, 1000);
while (foreach_utf8_data_chunks(data_chunk, max_chunks_len, &chunks_len)) { data_chunk = ascii_message;
g_string_append(chunks, g_strndup(data_chunk, chunks_len));
/* Next chunk */ chunks = g_string_new(NULL);
data_chunk += chunks_len;
while (foreach_utf8_data_chunks(data_chunk, max_chunks_len, &chunks_len)) {
g_string_append(chunks, g_strndup(data_chunk, chunks_len));
/* Next chunk */
data_chunk += chunks_len;
}
/* Check data loss */
g_assert_cmpstr(chunks->str, == , ascii_message);
g_string_free(chunks, TRUE);
} }
/* Check data loss */
g_assert_cmpstr(chunks->str, == , ascii_message);
g_string_free(chunks, TRUE);
g_rand_free (rand);
} }
int
main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
g_test_init(&argc, &argv, NULL); g_test_init(&argc, &argv, NULL);
g_test_add_func("/fishlim/ecb", test_ecb); g_test_add_func("/fishlim/__ecb", __ecb);
g_test_add_func("/fishlim/cbc", test_cbc); g_test_add_func("/fishlim/__cbc", __ecb);
g_test_add_func("/fishlim/base64_len", test_base64_len); g_test_add_func("/fishlim/__base64_len", __base64_len);
g_test_add_func("/fishlim/base64_fish_len", test_base64_fish_len); g_test_add_func("/fishlim/__base64_fish_len", __base64_fish_len);
g_test_add_func("/fishlim/base64_ecb_len", test_base64_ecb_len); g_test_add_func("/fishlim/__base64_ecb_len", __base64_ecb_len);
g_test_add_func("/fishlim/base64_cbc_len", test_base64_cbc_len); g_test_add_func("/fishlim/__base64_cbc_len", __base64_cbc_len);
g_test_add_func("/fishlim/max_text_command_len", test_max_text_command_len); g_test_add_func("/fishlim/__max_text_command_len", __max_text_command_len);
g_test_add_func("/fishlim/foreach_utf8_data_chunks", test_foreach_utf8_data_chunks); g_test_add_func("/fishlim/__foreach_utf8_data_chunks", __foreach_utf8_data_chunks);
fish_init(); return g_test_run();
int ret = g_test_run();
fish_deinit();
return ret;
} }
#endif //PLUGIN_HEXCHAT_FISHLIM_TEST_H

View File

@ -22,8 +22,6 @@
*/ */
#include <string.h>
#include "utils.h" #include "utils.h"
#include "fish.h" #include "fish.h"

View File

@ -957,21 +957,16 @@ static int api_hexchat_pluginprefs_meta_pairs(lua_State *L)
hexchat_plugin *h; hexchat_plugin *h;
if(!script->name) if(!script->name)
return luaL_error(L, "cannot use hexchat.pluginprefs before registering with hexchat.register"); return luaL_error(L, "cannot use hexchat.pluginprefs before registering with hexchat.register");
dest = lua_newuserdata(L, 4096); dest = lua_newuserdata(L, 4096);
h = script->handle; h = script->handle;
if(!hexchat_pluginpref_list(h, dest)) if(!hexchat_pluginpref_list(h, dest))
strcpy(dest, ""); strcpy(dest, "");
lua_pushlightuserdata(L, dest); lua_pushlightuserdata(L, dest);
lua_pushlightuserdata(L, dest); lua_pushlightuserdata(L, dest);
lua_pushcclosure(L, api_hexchat_pluginprefs_meta_pairs_closure, 2); lua_pushcclosure(L, api_hexchat_pluginprefs_meta_pairs_closure, 2);
lua_insert(L, -2); // Return the userdata (second return value from pairs), return 1;
// even though it's not used by the closure (first return
// value from pairs), so that Lua knows not to GC it.
return 2;
} }
static int api_attrs_meta_index(lua_State *L) static int api_attrs_meta_index(lua_State *L)
@ -1769,3 +1764,4 @@ G_MODULE_EXPORT int hexchat_plugin_deinit(hexchat_plugin *plugin_handle)
g_clear_pointer(&expand_buffer, g_free); g_clear_pointer(&expand_buffer, g_free);
return 1; return 1;
} }

View File

@ -88,5 +88,4 @@ shared_module('perl',
install_dir: plugindir, install_dir: plugindir,
install_rpath: perl_rpath, install_rpath: perl_rpath,
name_prefix: '', name_prefix: '',
vs_module_defs: 'perl.def',
) )

View File

@ -28,5 +28,4 @@ shared_module('python', python3_source,
install: true, install: true,
install_dir: plugindir, install_dir: plugindir,
name_prefix: '', name_prefix: '',
vs_module_defs: 'python.def'
) )

View File

@ -146,8 +146,8 @@ class Plugin:
def loadfile(self, filename): def loadfile(self, filename):
try: try:
self.filename = filename self.filename = filename
with open(filename, 'rb') as f: with open(filename) as f:
data = f.read().decode('utf-8') data = f.read()
compiled = compile_file(data, filename) compiled = compile_file(data, filename)
exec(compiled, self.globals) exec(compiled, self.globals)
@ -284,7 +284,7 @@ def _on_server_attrs_hook(word, word_eol, attrs, userdata):
@ffi.def_extern() @ffi.def_extern()
def _on_timer_hook(userdata): def _on_timer_hook(userdata):
hook = ffi.from_handle(userdata) hook = ffi.from_handle(userdata)
if hook.callback(hook.userdata) == True: if hook.callback(hook.userdata) is True:
return 1 return 1
hook.is_unload = True # Don't unhook hook.is_unload = True # Don't unhook

View File

@ -57,5 +57,4 @@ shared_module('sysinfo', sysinfo_sources,
install: true, install: true,
install_dir: plugindir, install_dir: plugindir,
name_prefix: '', name_prefix: '',
vs_module_defs: 'sysinfo.def',
) )

View File

@ -5,5 +5,4 @@ shared_module('upd', 'upd.c',
install: true, install: true,
install_dir: plugindir, install_dir: plugindir,
name_prefix: '', name_prefix: '',
vs_module_defs: 'upd.def',
) )

View File

@ -3,5 +3,4 @@ shared_module('winamp', 'winamp.c',
install: true, install: true,
install_dir: plugindir, install_dir: plugindir,
name_prefix: '', name_prefix: '',
vs_module_defs: 'winamp.def',
) )

View File

@ -18,7 +18,6 @@
# Aleksey <aleksdem@aleksdem.com>, 2016 # Aleksey <aleksdem@aleksdem.com>, 2016
# Артем Малофеев <79067635919@yandex.ru>, 2019 # Артем Малофеев <79067635919@yandex.ru>, 2019
# Магретов Никита <huku111a@gmail.com>, 2016 # Магретов Никита <huku111a@gmail.com>, 2016
# Alexander Popov <iiiypuk@fastmail.fm>, 2023
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: HexChat\n" "Project-Id-Version: HexChat\n"
@ -283,15 +282,15 @@ msgstr "Диалог"
#: src/common/hexchat.c:948 #: src/common/hexchat.c:948
msgid "WhoIs" msgid "WhoIs"
msgstr "WhoIs" msgstr "Кто "
#: src/common/hexchat.c:949 #: src/common/hexchat.c:949
msgid "Send" msgid "Send"
msgstr "Отправить файл" msgstr "Послать"
#: src/common/hexchat.c:950 #: src/common/hexchat.c:950
msgid "Chat" msgid "Chat"
msgstr "Чат" msgstr "Разговор"
#: src/common/hexchat.c:951 src/fe-gtk/banlist.c:847 src/fe-gtk/dccgui.c:889 #: src/common/hexchat.c:951 src/fe-gtk/banlist.c:847 src/fe-gtk/dccgui.c:889
#: src/fe-gtk/ignoregui.c:387 src/fe-gtk/urlgrab.c:214 #: src/fe-gtk/ignoregui.c:387 src/fe-gtk/urlgrab.c:214
@ -3260,7 +3259,7 @@ msgstr "Выберите файл для вывода"
#: src/fe-gtk/chanlist.c:624 src/fe-gtk/chanlist.c:812 #: src/fe-gtk/chanlist.c:624 src/fe-gtk/chanlist.c:812
msgid "_Join Channel" msgid "_Join Channel"
msgstr "_Войти на канал" msgstr "Зайти на канал"
#: src/fe-gtk/chanlist.c:626 #: src/fe-gtk/chanlist.c:626
msgid "_Copy Channel Name" msgid "_Copy Channel Name"
@ -3725,7 +3724,7 @@ msgstr "_Ничего, я войду на канал позднее."
#: src/fe-gtk/joind.c:191 #: src/fe-gtk/joind.c:191
msgid "_Join this channel:" msgid "_Join this channel:"
msgstr "Войти на канал:" msgstr "Зайти на канал:"
#: src/fe-gtk/joind.c:203 #: src/fe-gtk/joind.c:203
msgid "If you know the name of the channel you want to join, enter it here." msgid "If you know the name of the channel you want to join, enter it here."
@ -3854,11 +3853,11 @@ msgstr "Мерцание _окна"
#: src/fe-gtk/maingui.c:1566 src/fe-gtk/menu.c:2351 #: src/fe-gtk/maingui.c:1566 src/fe-gtk/menu.c:2351
msgid "_Detach" msgid "_Detach"
msgstr "Отсо_единить окно" msgstr "Отсо_единить"
#: src/fe-gtk/maingui.c:1568 src/fe-gtk/menu.c:2352 src/fe-gtk/menu.c:2357 #: src/fe-gtk/maingui.c:1568 src/fe-gtk/menu.c:2352 src/fe-gtk/menu.c:2357
msgid "_Close" msgid "_Close"
msgstr "_Закрыть" msgstr "Закрыть"
#: src/fe-gtk/maingui.c:1908 src/fe-gtk/maingui.c:2021 #: src/fe-gtk/maingui.c:1908 src/fe-gtk/maingui.c:2021
msgid "User limit must be a number!\n" msgid "User limit must be a number!\n"
@ -4193,35 +4192,35 @@ msgstr "He_xChat"
#: src/fe-gtk/menu.c:1758 #: src/fe-gtk/menu.c:1758
msgid "Network Li_st" msgid "Network Li_st"
msgstr "_Список сетей" msgstr ""
#: src/fe-gtk/menu.c:1761 #: src/fe-gtk/menu.c:1761
msgid "_New" msgid "_New"
msgstr "_Новое..." msgstr "Новая..."
#: src/fe-gtk/menu.c:1762 #: src/fe-gtk/menu.c:1762
msgid "Server Tab" msgid "Server Tab"
msgstr "Вкладка сервера" msgstr ""
#: src/fe-gtk/menu.c:1763 #: src/fe-gtk/menu.c:1763
msgid "Channel Tab" msgid "Channel Tab"
msgstr "Вкладка канала" msgstr ""
#: src/fe-gtk/menu.c:1764 #: src/fe-gtk/menu.c:1764
msgid "Server Window" msgid "Server Window"
msgstr "Окно сервера" msgstr ""
#: src/fe-gtk/menu.c:1765 #: src/fe-gtk/menu.c:1765
msgid "Channel Window" msgid "Channel Window"
msgstr "Окно канала" msgstr ""
#: src/fe-gtk/menu.c:1769 #: src/fe-gtk/menu.c:1769
msgid "_Load Plugin or Script" msgid "_Load Plugin or Script"
msgstr "Загрузить плагин или _скрипт" msgstr ""
#: src/fe-gtk/menu.c:1776 src/fe-gtk/plugin-tray.c:579 #: src/fe-gtk/menu.c:1776 src/fe-gtk/plugin-tray.c:579
msgid "_Quit" msgid "_Quit"
msgstr "_Выход" msgstr "Выход"
#. 15 #. 15
#: src/fe-gtk/menu.c:1778 #: src/fe-gtk/menu.c:1778
@ -4234,7 +4233,7 @@ msgstr "Панел_ь меню"
#: src/fe-gtk/menu.c:1781 #: src/fe-gtk/menu.c:1781
msgid "_Topic Bar" msgid "_Topic Bar"
msgstr "Т_ема канала" msgstr "Т_ема"
#: src/fe-gtk/menu.c:1782 #: src/fe-gtk/menu.c:1782
msgid "_User List" msgid "_User List"
@ -4242,7 +4241,7 @@ msgstr "Список _пользователей"
#: src/fe-gtk/menu.c:1783 #: src/fe-gtk/menu.c:1783
msgid "U_ser List Buttons" msgid "U_ser List Buttons"
msgstr "_Кнопки списка пользователей" msgstr ""
#: src/fe-gtk/menu.c:1784 #: src/fe-gtk/menu.c:1784
msgid "M_ode Buttons" msgid "M_ode Buttons"
@ -4270,11 +4269,11 @@ msgstr "Выключено"
#: src/fe-gtk/menu.c:1794 #: src/fe-gtk/menu.c:1794
msgid "Graph" msgid "Graph"
msgstr "График" msgstr "График:"
#: src/fe-gtk/menu.c:1799 #: src/fe-gtk/menu.c:1799
msgid "_Fullscreen" msgid "_Fullscreen"
msgstr "_Полноэкранный режим" msgstr "_Полноэкранка"
#: src/fe-gtk/menu.c:1801 #: src/fe-gtk/menu.c:1801
msgid "_Server" msgid "_Server"
@ -4286,19 +4285,19 @@ msgstr "Отключиться"
#: src/fe-gtk/menu.c:1803 #: src/fe-gtk/menu.c:1803
msgid "_Reconnect" msgid "_Reconnect"
msgstr "_Пересоединиться" msgstr "Пересоединиться"
#: src/fe-gtk/menu.c:1804 #: src/fe-gtk/menu.c:1804
msgid "_Join a Channel" msgid "_Join a Channel"
msgstr "_Войти на канал" msgstr ""
#: src/fe-gtk/menu.c:1805 #: src/fe-gtk/menu.c:1805
msgid "Channel _List" msgid "Channel _List"
msgstr "Список каналов" msgstr ""
#: src/fe-gtk/menu.c:1808 #: src/fe-gtk/menu.c:1808
msgid "Marked _Away" msgid "Marked _Away"
msgstr "Пометить как _Отошёл" msgstr "Помечен как _Отошёл"
#: src/fe-gtk/menu.c:1810 #: src/fe-gtk/menu.c:1810
msgid "_Usermenu" msgid "_Usermenu"
@ -4311,11 +4310,11 @@ msgstr "Настройка"
#: src/fe-gtk/menu.c:1813 src/fe-gtk/plugin-tray.c:577 #: src/fe-gtk/menu.c:1813 src/fe-gtk/plugin-tray.c:577
msgid "_Preferences" msgid "_Preferences"
msgstr "Параметры" msgstr "Установки"
#: src/fe-gtk/menu.c:1815 #: src/fe-gtk/menu.c:1815
msgid "Auto Replace" msgid "Auto Replace"
msgstr "Автозамена" msgstr ""
#: src/fe-gtk/menu.c:1816 #: src/fe-gtk/menu.c:1816
msgid "CTCP Replies" msgid "CTCP Replies"
@ -4335,7 +4334,7 @@ msgstr ""
#: src/fe-gtk/menu.c:1820 #: src/fe-gtk/menu.c:1820
msgid "URL Handlers" msgid "URL Handlers"
msgstr "Обработчики URL" msgstr ""
#: src/fe-gtk/menu.c:1821 #: src/fe-gtk/menu.c:1821
msgid "User Commands" msgid "User Commands"
@ -4793,7 +4792,7 @@ msgstr "Не показывать список сетей при запуске"
#: src/fe-gtk/servlistgui.c:2130 #: src/fe-gtk/servlistgui.c:2130
msgid "Show favorites only" msgid "Show favorites only"
msgstr "Показывать только избранные" msgstr "Показывать только фавориты"
#: src/fe-gtk/servlistgui.c:2160 #: src/fe-gtk/servlistgui.c:2160
msgid "_Edit..." msgid "_Edit..."
@ -4811,7 +4810,7 @@ msgstr ""
#: src/fe-gtk/servlistgui.c:2176 #: src/fe-gtk/servlistgui.c:2176
msgid "_Favor" msgid "_Favor"
msgstr "_В избранное" msgstr "_В фавориты"
#: src/fe-gtk/servlistgui.c:2177 #: src/fe-gtk/servlistgui.c:2177
msgid "Mark or unmark this network as a favorite." msgid "Mark or unmark this network as a favorite."
@ -5031,7 +5030,7 @@ msgstr "Валлонский"
#: src/fe-gtk/setup.c:149 src/fe-gtk/setup.c:1880 #: src/fe-gtk/setup.c:149 src/fe-gtk/setup.c:1880
msgid "General" msgid "General"
msgstr "Основные" msgstr "Главный"
#: src/fe-gtk/setup.c:151 #: src/fe-gtk/setup.c:151
msgid "Language:" msgid "Language:"
@ -5083,19 +5082,19 @@ msgstr "Настройки прозрачности"
#: src/fe-gtk/setup.c:164 #: src/fe-gtk/setup.c:164
msgid "Window opacity:" msgid "Window opacity:"
msgstr "Прозрачность окна:" msgstr ""
#: src/fe-gtk/setup.c:166 src/fe-gtk/setup.c:593 #: src/fe-gtk/setup.c:166 src/fe-gtk/setup.c:593
msgid "Timestamps" msgid "Timestamps"
msgstr "Временная метка" msgstr ""
#: src/fe-gtk/setup.c:167 #: src/fe-gtk/setup.c:167
msgid "Enable timestamps" msgid "Enable timestamps"
msgstr "Включить временные метки" msgstr ""
#: src/fe-gtk/setup.c:168 #: src/fe-gtk/setup.c:168
msgid "Timestamp format:" msgid "Timestamp format:"
msgstr "Формат временной метки:" msgstr ""
#: src/fe-gtk/setup.c:170 src/fe-gtk/setup.c:597 #: src/fe-gtk/setup.c:170 src/fe-gtk/setup.c:597
msgid "See the strftime MSDN article for details." msgid "See the strftime MSDN article for details."
@ -5107,7 +5106,7 @@ msgstr "См. страницу руководства по strftime."
#: src/fe-gtk/setup.c:175 #: src/fe-gtk/setup.c:175
msgid "Title Bar" msgid "Title Bar"
msgstr "Строка заголовка" msgstr ""
#: src/fe-gtk/setup.c:176 #: src/fe-gtk/setup.c:176
msgid "Show channel modes" msgid "Show channel modes"
@ -5709,7 +5708,7 @@ msgstr ""
#: src/fe-gtk/setup.c:561 #: src/fe-gtk/setup.c:561
msgid "Automatically include timestamps" msgid "Automatically include timestamps"
msgstr "Автоматически добавлять временные метки" msgstr ""
#: src/fe-gtk/setup.c:562 #: src/fe-gtk/setup.c:562
msgid "" msgid ""
@ -5767,7 +5766,7 @@ msgstr "Задержка авто восстановления соединен
#: src/fe-gtk/setup.c:578 #: src/fe-gtk/setup.c:578
msgid "Auto join delay:" msgid "Auto join delay:"
msgstr "Задержка автоматического входа:" msgstr ""
#: src/fe-gtk/setup.c:579 #: src/fe-gtk/setup.c:579
msgid "Ban Type:" msgid "Ban Type:"
@ -6090,7 +6089,7 @@ msgstr "Цвета"
#: src/fe-gtk/setup.c:1879 #: src/fe-gtk/setup.c:1879
msgid "Chatting" msgid "Chatting"
msgstr "Чат" msgstr "Общение"
#: src/fe-gtk/setup.c:1882 #: src/fe-gtk/setup.c:1882
msgid "Sounds" msgid "Sounds"

View File

@ -468,7 +468,6 @@ const struct prefs vars[] =
{"gui_win_fullscreen", P_OFFINT (hex_gui_win_fullscreen), TYPE_INT}, {"gui_win_fullscreen", P_OFFINT (hex_gui_win_fullscreen), TYPE_INT},
{"gui_win_left", P_OFFINT (hex_gui_win_left), TYPE_INT}, {"gui_win_left", P_OFFINT (hex_gui_win_left), TYPE_INT},
{"gui_win_modes", P_OFFINT (hex_gui_win_modes), TYPE_BOOL}, {"gui_win_modes", P_OFFINT (hex_gui_win_modes), TYPE_BOOL},
{"gui_win_nick", P_OFFINT (hex_gui_win_nick), TYPE_BOOL},
{"gui_win_save", P_OFFINT (hex_gui_win_save), TYPE_BOOL}, {"gui_win_save", P_OFFINT (hex_gui_win_save), TYPE_BOOL},
{"gui_win_state", P_OFFINT (hex_gui_win_state), TYPE_INT}, {"gui_win_state", P_OFFINT (hex_gui_win_state), TYPE_INT},
{"gui_win_swap", P_OFFINT (hex_gui_win_swap), TYPE_BOOL}, {"gui_win_swap", P_OFFINT (hex_gui_win_swap), TYPE_BOOL},
@ -773,7 +772,6 @@ load_default_config(void)
prefs.hex_gui_ulist_count = 1; prefs.hex_gui_ulist_count = 1;
prefs.hex_gui_ulist_icons = 1; prefs.hex_gui_ulist_icons = 1;
prefs.hex_gui_ulist_style = 1; prefs.hex_gui_ulist_style = 1;
prefs.hex_gui_win_nick = 1;
prefs.hex_gui_win_save = 1; prefs.hex_gui_win_save = 1;
prefs.hex_input_filter_beep = 1; prefs.hex_input_filter_beep = 1;
prefs.hex_input_flash_hilight = 1; prefs.hex_input_flash_hilight = 1;

View File

@ -487,6 +487,19 @@ dcc_notify_kill (struct server *serv)
} }
} }
static int
tcp_send_real (int sok, GIConv write_converter, char *buf, int len)
{
int ret;
gsize buf_encoded_len;
gchar *buf_encoded = text_convert_invalid (buf, len, write_converter, arbitrary_encoding_fallback_string, &buf_encoded_len);
ret = send (sok, buf_encoded, buf_encoded_len, 0);
g_free (buf_encoded);
return ret;
}
struct DCC * struct DCC *
dcc_write_chat (char *nick, char *text) dcc_write_chat (char *nick, char *text)
{ {
@ -499,7 +512,7 @@ dcc_write_chat (char *nick, char *text)
if (dcc && dcc->dccstat == STAT_ACTIVE) if (dcc && dcc->dccstat == STAT_ACTIVE)
{ {
len = strlen (text); len = strlen (text);
tcp_send_real (NULL, dcc->sok, dcc->serv->write_converter, text, len); tcp_send_real (dcc->sok, dcc->serv->write_converter, text, len);
send (dcc->sok, "\n", 1, 0); send (dcc->sok, "\n", 1, 0);
dcc->size += len; dcc->size += len;
fe_dcc_update (dcc); fe_dcc_update (dcc);
@ -1656,7 +1669,8 @@ dcc_listen_init (struct DCC *dcc, session *sess)
memset (&SAddr, 0, sizeof (struct sockaddr_in)); memset (&SAddr, 0, sizeof (struct sockaddr_in));
len = sizeof (SAddr); len = sizeof (SAddr);
getsockname (dcc->serv->sok, (struct sockaddr *) &SAddr, &len); /* TODO: Get rid of raw socket usage */
getsockname (g_socket_get_fd (dcc->serv->socket), (struct sockaddr *) &SAddr, &len);
SAddr.sin_family = AF_INET; SAddr.sin_family = AF_INET;

View File

@ -69,16 +69,7 @@ int fe_input_add (int sok, int flags, void *func, void *data);
void fe_input_remove (int tag); void fe_input_remove (int tag);
void fe_idle_add (void *func, void *data); void fe_idle_add (void *func, void *data);
void fe_set_topic (struct session *sess, char *topic, char *stripped_topic); void fe_set_topic (struct session *sess, char *topic, char *stripped_topic);
typedef enum void fe_set_tab_color (struct session *sess, int col);
{
FE_COLOR_NONE = 0,
FE_COLOR_NEW_DATA = 1,
FE_COLOR_NEW_MSG = 2,
FE_COLOR_NEW_HILIGHT = 3,
FE_COLOR_FLAG_NOOVERRIDE = 8,
} tabcolor;
#define FE_COLOR_ALLFLAGS (FE_COLOR_FLAG_NOOVERRIDE)
void fe_set_tab_color (struct session *sess, tabcolor col);
void fe_flash_window (struct session *sess); void fe_flash_window (struct session *sess);
void fe_update_mode_buttons (struct session *sess, char mode, char sign); void fe_update_mode_buttons (struct session *sess, char mode, char sign);
void fe_update_channel_key (struct session *sess); void fe_update_channel_key (struct session *sess);
@ -141,7 +132,6 @@ void fe_get_int (char *prompt, int def, void *callback, void *ud);
#define FRF_NOASKOVERWRITE 32 /* don't ask to overwrite existing files */ #define FRF_NOASKOVERWRITE 32 /* don't ask to overwrite existing files */
#define FRF_EXTENSIONS 64 /* specify file extensions to be displayed */ #define FRF_EXTENSIONS 64 /* specify file extensions to be displayed */
#define FRF_MIMETYPES 128 /* specify file mimetypes to be displayed */ #define FRF_MIMETYPES 128 /* specify file mimetypes to be displayed */
#define FRF_MODAL 256 /* dialog should be modal to parent */
void fe_get_file (const char *title, char *initial, void fe_get_file (const char *title, char *initial,
void (*callback) (void *userdata, char *file), void *userdata, void (*callback) (void *userdata, char *file), void *userdata,
int flags); int flags);

View File

@ -266,7 +266,7 @@ lag_check (void)
EMIT_SIGNAL (XP_TE_PINGTIMEOUT, serv->server_session, tbuf, NULL, EMIT_SIGNAL (XP_TE_PINGTIMEOUT, serv->server_session, tbuf, NULL,
NULL, NULL, 0); NULL, NULL, 0);
if (prefs.hex_net_auto_reconnect) if (prefs.hex_net_auto_reconnect)
serv->auto_reconnect (serv, FALSE, -1); serv->auto_reconnect (serv, FALSE, NULL);
} }
else else
{ {

View File

@ -39,10 +39,6 @@
#include "history.h" #include "history.h"
#include "tree.h" #include "tree.h"
#ifdef USE_OPENSSL
#include <openssl/ssl.h> /* SSL_() */
#endif
#ifdef __EMX__ /* for o/s 2 */ #ifdef __EMX__ /* for o/s 2 */
#define OFLAGS O_BINARY #define OFLAGS O_BINARY
#define g_ascii_strcasecmp stricmp #define g_ascii_strcasecmp stricmp
@ -150,7 +146,6 @@ struct hexchatprefs
unsigned int hex_gui_ulist_style; unsigned int hex_gui_ulist_style;
unsigned int hex_gui_usermenu; unsigned int hex_gui_usermenu;
unsigned int hex_gui_win_modes; unsigned int hex_gui_win_modes;
unsigned int hex_gui_win_nick;
unsigned int hex_gui_win_save; unsigned int hex_gui_win_save;
unsigned int hex_gui_win_swap; unsigned int hex_gui_win_swap;
unsigned int hex_gui_win_ucount; unsigned int hex_gui_win_ucount;
@ -435,10 +430,10 @@ typedef struct server
{ {
/* server control operations (in server*.c) */ /* server control operations (in server*.c) */
void (*connect)(struct server *, char *hostname, int port, int no_login); void (*connect)(struct server *, char *hostname, int port, int no_login);
void (*disconnect)(struct session *, int sendquit, int err); void (*disconnect)(struct session *, int sendquit, GError *err);
int (*cleanup)(struct server *); int (*cleanup)(struct server *);
void (*flush_queue)(struct server *); void (*flush_queue)(struct server *);
void (*auto_reconnect)(struct server *, int send_quit, int err); void (*auto_reconnect)(struct server *, int send_quit, GError *err);
/* irc protocol functions (in proto*.c) */ /* irc protocol functions (in proto*.c) */
void (*p_inline)(struct server *, char *buf, int len); void (*p_inline)(struct server *, char *buf, int len);
void (*p_invite)(struct server *, char *channel, char *nick); void (*p_invite)(struct server *, char *channel, char *nick);
@ -475,36 +470,25 @@ typedef struct server
int (*p_cmp)(const char *s1, const char *s2); int (*p_cmp)(const char *s1, const char *s2);
int port; int port;
int sok; /* is equal to sok4 or sok6 (the one we are using) */
int sok4; /* tcp4 socket */
int sok6; /* tcp6 socket */
int proxy_type;
int proxy_sok; /* Additional information for MS Proxy beast */
int proxy_sok4;
int proxy_sok6;
int id; /* unique ID number (for plugin API) */ int id; /* unique ID number (for plugin API) */
/* dcc_ip moved from hexchatprefs to make it per-server */ /* dcc_ip moved from hexchatprefs to make it per-server */
guint32 dcc_ip; guint32 dcc_ip;
#ifdef USE_OPENSSL GSocketClient *socket_client;
SSL_CTX *ctx; GSocketConnection *socket_conn;
SSL *ssl; GSocket *socket; /* Owned by socket_conn */
int ssl_do_connect_tag; GCancellable *connection_cancellable;
#else GTlsCertificate *client_cert;
void *ssl; GSource *socket_read_source;
#endif
int childread;
int childwrite;
int childpid;
int iotag;
int recondelay_tag; /* reconnect delay timeout */ int recondelay_tag; /* reconnect delay timeout */
int joindelay_tag; /* waiting before we send JOIN */ int joindelay_tag; /* waiting before we send JOIN */
char hostname[128]; /* real ip number */ char hostname[128]; /* real ip number */
char servername[128]; /* what the server says is its name */ char servername[128]; /* what the server says is its name */
char password[1024]; char password[86];
char nick[NICKLEN]; char nick[NICKLEN];
char linebuf[8704]; /* RFC says 512 chars including \r\n, IRCv3 message tags add 8191, plus the NUL byte */ char linebuf[2048]; /* RFC says 512 chars including \r\n */
char *last_away_reason; char *last_away_reason;
int pos; /* current position in linebuf */ int pos; /* current position in linebuf */
int nickcount; int nickcount;

View File

@ -1474,17 +1474,10 @@ inbound_user_info (session *sess, char *chan, char *user, char *host,
for (list = sess_list; list; list = list->next) for (list = sess_list; list; list = list->next)
{ {
sess = list->data; sess = list->data;
if (sess->server != serv) if (sess->type == SESS_CHANNEL && sess->server == serv)
continue;
if (sess->type == SESS_CHANNEL)
{ {
userlist_add_hostname (sess, nick, uhost, realname, servname, account, away); userlist_add_hostname (sess, nick, uhost, realname, servname, account, away);
} }
else if (sess->type == SESS_DIALOG && uhost && !serv->p_cmp (sess->channel, nick))
{
set_topic (sess, uhost, uhost);
}
} }
} }
@ -1735,7 +1728,6 @@ static const char * const supported_caps[] = {
"setname", "setname",
"invite-notify", "invite-notify",
"account-tag", "account-tag",
"extended-monitor",
/* ZNC */ /* ZNC */
"znc.in/server-time-iso", "znc.in/server-time-iso",
@ -1937,24 +1929,7 @@ inbound_sasl_authenticate (server *serv, char *data)
return; return;
} }
/* long SASL passwords must be split into 400-byte chunks tcp_sendf (serv, "AUTHENTICATE %s\r\n", pass);
https://ircv3.net/specs/extensions/sasl-3.1#the-authenticate-command */
size_t pass_len = strlen (pass);
if (pass_len <= 400)
tcp_sendf (serv, "AUTHENTICATE %s\r\n", pass);
else
{
size_t sent = 0;
while (sent < pass_len)
{
char *pass_chunk = g_strndup (pass + sent, 400);
tcp_sendf (serv, "AUTHENTICATE %s\r\n", pass_chunk);
sent += 400;
g_free (pass_chunk);
}
}
if (pass_len % 400 == 0)
tcp_sendf (serv, "AUTHENTICATE +\r\n");
g_free (pass); g_free (pass);

View File

@ -47,6 +47,7 @@ if host_machine.system() == 'windows'
] ]
common_sysinfo_deps += [ common_sysinfo_deps += [
cc.find_library('wbemuuid'), # sysinfo cc.find_library('wbemuuid'), # sysinfo
cc.find_library('wbemcore'),
] ]
common_sources += 'sysinfo/win32/backend.c' common_sources += 'sysinfo/win32/backend.c'
@ -73,7 +74,6 @@ textevents = custom_target('textevents',
# HAVE_GTK_MAC # HAVE_GTK_MAC
if libssl_dep.found() if libssl_dep.found()
common_sources += 'ssl.c'
common_deps += libssl_dep common_deps += libssl_dep
endif endif

View File

@ -67,8 +67,8 @@ send_channel_modes (session *sess, char *tbuf, char *word[], int wpos,
int usable_modes, orig_len, len, wlen, i, max; int usable_modes, orig_len, len, wlen, i, max;
server *serv = sess->server; server *serv = sess->server;
/* sanity check. IRC RFC says three per line but some servers may support less. */ /* sanity check. IRC RFC says three per line. */
if (serv->modes_per_line < 1) if (serv->modes_per_line < 3)
serv->modes_per_line = 3; serv->modes_per_line = 3;
if (modes_per_line < 1) if (modes_per_line < 1)
modes_per_line = serv->modes_per_line; modes_per_line = serv->modes_per_line;
@ -880,7 +880,7 @@ inbound_005 (server * serv, char *word[], const message_tags_data *tags_data)
g_free (serv->nick_prefixes); g_free (serv->nick_prefixes);
g_free (serv->nick_modes); g_free (serv->nick_modes);
serv->nick_prefixes = g_strdup (pre + 1); serv->nick_prefixes = g_strdup (pre + 1);
serv->nick_modes = g_strdup (tokvalue + 1); serv->nick_modes = g_strdup (tokvalue);
} else } else
{ {
/* bad! some ircds don't give us the modes. */ /* bad! some ircds don't give us the modes. */
@ -918,12 +918,8 @@ inbound_005 (server * serv, char *word[], const message_tags_data *tags_data)
server_set_encoding (serv, "UTF-8"); server_set_encoding (serv, "UTF-8");
} else if (g_strcmp0 (tokname, "NAMESX") == 0) } else if (g_strcmp0 (tokname, "NAMESX") == 0)
{ {
if (tokadding && !serv->have_namesx) /* 12345678901234567 */
{ tcp_send_len (serv, "PROTOCTL NAMESX\r\n", 17);
/* only use protoctl if the server doesn't have the equivalent cap */
tcp_send_len (serv, "PROTOCTL NAMESX\r\n", 17);
serv->have_namesx = TRUE;
}
} else if (g_strcmp0 (tokname, "WHOX") == 0) } else if (g_strcmp0 (tokname, "WHOX") == 0)
{ {
serv->have_whox = tokadding; serv->have_whox = tokadding;

View File

@ -123,11 +123,7 @@ notify_save (void)
{ {
int fh; int fh;
struct notify *notify; struct notify *notify;
// while reading the notify.conf file, elements are added by prepending to the GSList *list = notify_list;
// list. reverse the list before writing to disk to keep the original
// order of the list
GSList *list = g_slist_copy(notify_list);
list = g_slist_reverse(list);
fh = hexchat_open_file ("notify.conf", O_TRUNC | O_WRONLY | O_CREAT, 0600, XOF_DOMODE); fh = hexchat_open_file ("notify.conf", O_TRUNC | O_WRONLY | O_CREAT, 0600, XOF_DOMODE);
if (fh != -1) if (fh != -1)
@ -146,7 +142,6 @@ notify_save (void)
} }
close (fh); close (fh);
} }
g_slist_free(list);
} }
void void

View File

@ -903,8 +903,8 @@ cmd_debug (struct session *sess, char *tbuf, char *word[], char *word_eol[])
while (list) while (list)
{ {
v = (struct server *) list->data; v = (struct server *) list->data;
sprintf (tbuf, "%p %-5d %s\n", sprintf (tbuf, "%p %s\n",
v, v->sok, v->servername); v, v->servername);
PrintText (sess, tbuf); PrintText (sess, tbuf);
list = list->next; list = list->next;
} }
@ -1414,7 +1414,7 @@ cmd_devoice (struct session *sess, char *tbuf, char *word[], char *word_eol[])
static int static int
cmd_discon (struct session *sess, char *tbuf, char *word[], char *word_eol[]) cmd_discon (struct session *sess, char *tbuf, char *word[], char *word_eol[])
{ {
sess->server->disconnect (sess, TRUE, -1); sess->server->disconnect (sess, TRUE, NULL);
return TRUE; return TRUE;
} }
@ -1579,26 +1579,9 @@ cmd_execw (struct session *sess, char *tbuf, char *word[], char *word_eol[])
EMIT_SIGNAL (XP_TE_NOCHILD, sess, NULL, NULL, NULL, NULL, 0); EMIT_SIGNAL (XP_TE_NOCHILD, sess, NULL, NULL, NULL, NULL, 0);
return FALSE; return FALSE;
} }
if (strcmp (word[2], "--") == 0) len = strlen(word_eol[2]);
{ temp = g_strconcat (word_eol[2], "\n", NULL);
len = strlen(word_eol[3]); PrintText(sess, temp);
temp = g_strconcat (word_eol[3], "\n", NULL);
PrintText(sess, temp);
}
else
{
if (strcmp (word[2], "-q") == 0)
{
len = strlen(word_eol[3]);
temp = g_strconcat (word_eol[3], "\n", NULL);
}
else
{
len = strlen(word_eol[2]);
temp = g_strconcat (word_eol[2], "\n", NULL);
PrintText(sess, temp);
}
}
write(sess->running_exec->myfd, temp, len + 1); write(sess->running_exec->myfd, temp, len + 1);
g_free(temp); g_free(temp);
@ -1973,7 +1956,7 @@ cmd_quit (struct session *sess, char *tbuf, char *word[], char *word_eol[])
{ {
if (*word_eol[2]) if (*word_eol[2])
sess->quitreason = word_eol[2]; sess->quitreason = word_eol[2];
sess->server->disconnect (sess, TRUE, -1); sess->server->disconnect (sess, TRUE, NULL);
sess->quitreason = NULL; sess->quitreason = NULL;
return 2; return 2;
} }
@ -2169,6 +2152,7 @@ cmd_gui (struct session *sess, char *tbuf, char *word[], char *word_eol[])
{ {
case 0x058b836e: fe_ctrl_gui (sess, 8, 0); break; /* APPLY */ case 0x058b836e: fe_ctrl_gui (sess, 8, 0); break; /* APPLY */
case 0xac1eee45: fe_ctrl_gui (sess, 7, 2); break; /* ATTACH */ case 0xac1eee45: fe_ctrl_gui (sess, 7, 2); break; /* ATTACH */
case 0x05a72f63: fe_ctrl_gui (sess, 4, atoi (word[3])); break; /* COLOR */
case 0xb06a1793: fe_ctrl_gui (sess, 7, 1); break; /* DETACH */ case 0xb06a1793: fe_ctrl_gui (sess, 7, 1); break; /* DETACH */
case 0x05cfeff0: fe_ctrl_gui (sess, 3, 0); break; /* FLASH */ case 0x05cfeff0: fe_ctrl_gui (sess, 3, 0); break; /* FLASH */
case 0x05d154d8: fe_ctrl_gui (sess, 2, 0); break; /* FOCUS */ case 0x05d154d8: fe_ctrl_gui (sess, 2, 0); break; /* FOCUS */
@ -2182,12 +2166,6 @@ cmd_gui (struct session *sess, char *tbuf, char *word[], char *word_eol[])
else else
return FALSE; return FALSE;
break; break;
case 0x05a72f63: /* COLOR */
if (!g_ascii_strcasecmp (word[4], "-NOOVERRIDE"))
fe_ctrl_gui (sess, 4, FE_COLOR_FLAG_NOOVERRIDE | atoi (word[3]));
else
fe_ctrl_gui (sess, 4, atoi (word[3]));
break;
default: default:
return FALSE; return FALSE;
} }
@ -3238,7 +3216,7 @@ cmd_reconnect (struct session *sess, char *tbuf, char *word[], char *word_eol[])
{ {
serv = list->data; serv = list->data;
if (serv->connected) if (serv->connected)
serv->auto_reconnect (serv, TRUE, -1); serv->auto_reconnect (serv, TRUE, NULL);
list = list->next; list = list->next;
} }
} }
@ -3249,7 +3227,7 @@ cmd_reconnect (struct session *sess, char *tbuf, char *word[], char *word_eol[])
int offset = 0; int offset = 0;
#ifdef USE_OPENSSL #ifdef USE_OPENSSL
int use_ssl = TRUE; int use_ssl = FALSE;
int use_ssl_noverify = FALSE; int use_ssl_noverify = FALSE;
if (g_strcmp0 (word[2], "-ssl") == 0) if (g_strcmp0 (word[2], "-ssl") == 0)
{ {
@ -3261,11 +3239,6 @@ cmd_reconnect (struct session *sess, char *tbuf, char *word[], char *word_eol[])
use_ssl = TRUE; use_ssl = TRUE;
use_ssl_noverify = TRUE; use_ssl_noverify = TRUE;
offset++; /* args move up by 1 word */ offset++; /* args move up by 1 word */
} else if (g_strcmp0 (word[2], "-insecure") == 0)
{
use_ssl = FALSE;
use_ssl_noverify = FALSE;
offset++; /* args move up by 1 word */
} }
serv->use_ssl = use_ssl; serv->use_ssl = use_ssl;
serv->accept_invalid_cert = use_ssl_noverify; serv->accept_invalid_cert = use_ssl_noverify;
@ -3276,11 +3249,11 @@ cmd_reconnect (struct session *sess, char *tbuf, char *word[], char *word_eol[])
if (*word[3+offset]) if (*word[3+offset])
serv->port = atoi (word[3+offset]); serv->port = atoi (word[3+offset]);
safe_strcpy (serv->hostname, word[2+offset], sizeof (serv->hostname)); safe_strcpy (serv->hostname, word[2+offset], sizeof (serv->hostname));
serv->auto_reconnect (serv, TRUE, -1); serv->auto_reconnect (serv, TRUE, NULL);
} }
else else
{ {
serv->auto_reconnect (serv, TRUE, -1); serv->auto_reconnect (serv, TRUE, NULL);
} }
prefs.hex_net_reconnect_delay = tmp; prefs.hex_net_reconnect_delay = tmp;
@ -3321,6 +3294,7 @@ cmd_send (struct session *sess, char *tbuf, char *word[], char *word_eol[])
if (!word[2][0]) if (!word[2][0])
return FALSE; return FALSE;
#if 0
addr = dcc_get_my_address (sess); addr = dcc_get_my_address (sess);
if (addr == 0) if (addr == 0)
{ {
@ -3340,6 +3314,7 @@ cmd_send (struct session *sess, char *tbuf, char *word[], char *word_eol[])
g_snprintf (tbuf, 512, "DCC SEND %s", word_eol[2]); g_snprintf (tbuf, 512, "DCC SEND %s", word_eol[2]);
handle_command (sess, tbuf, FALSE); handle_command (sess, tbuf, FALSE);
#endif
return TRUE; return TRUE;
} }
@ -3455,10 +3430,8 @@ cmd_server (struct session *sess, char *tbuf, char *word[], char *word_eol[])
char *pass = NULL; char *pass = NULL;
char *channel = NULL; char *channel = NULL;
char *key = NULL; char *key = NULL;
#ifdef USE_OPENSSL int use_ssl = FALSE;
int use_ssl = TRUE;
int use_ssl_noverify = FALSE; int use_ssl_noverify = FALSE;
#endif
int is_url = TRUE; int is_url = TRUE;
server *serv = sess->server; server *serv = sess->server;
ircnet *net = NULL; ircnet *net = NULL;
@ -3476,11 +3449,6 @@ cmd_server (struct session *sess, char *tbuf, char *word[], char *word_eol[])
use_ssl_noverify = TRUE; use_ssl_noverify = TRUE;
offset++; /* args move up by 1 word */ offset++; /* args move up by 1 word */
} }
else if (g_strcmp0 (word[2], "-insecure") == 0)
{
use_ssl = FALSE;
offset++; /* args move up by 1 word */
}
#endif #endif
if (!parse_irc_url (word[2 + offset], &server_name, &port, &channel, &key, &use_ssl)) if (!parse_irc_url (word[2 + offset], &server_name, &port, &channel, &key, &use_ssl))
@ -3521,13 +3489,6 @@ cmd_server (struct session *sess, char *tbuf, char *word[], char *word_eol[])
use_ssl = TRUE; use_ssl = TRUE;
#endif #endif
} }
else if (port[0] == '-')
{
port++;
#ifdef USE_OPENSSL
use_ssl = FALSE;
#endif
}
if (*pass) if (*pass)
{ {
@ -3583,7 +3544,7 @@ cmd_servchan (struct session *sess, char *tbuf, char *word[],
int offset = 0; int offset = 0;
#ifdef USE_OPENSSL #ifdef USE_OPENSSL
if (g_strcmp0 (word[2], "-ssl") == 0 || g_strcmp0 (word[2], "-ssl-noverify") == 0 || g_strcmp0 (word[2], "-insecure") == 0) if (g_strcmp0 (word[2], "-ssl") == 0 || g_strcmp0 (word[2], "-ssl-noverify") == 0)
offset++; offset++;
#endif #endif
@ -3917,6 +3878,34 @@ cmd_wallchop (struct session *sess, char *tbuf, char *word[],
return TRUE; return TRUE;
} }
static int
cmd_wallchan (struct session *sess, char *tbuf, char *word[],
char *word_eol[])
{
GSList *list;
if (*word_eol[2])
{
list = sess_list;
while (list)
{
sess = list->data;
if (sess->type == SESS_CHANNEL)
{
message_tags_data no_tags = MESSAGE_TAGS_DATA_INIT;
inbound_chanmsg (sess->server, NULL, sess->channel,
sess->server->nick, word_eol[2], TRUE, FALSE,
&no_tags);
sess->server->p_message (sess->server, sess->channel, word_eol[2]);
}
list = list->next;
}
return TRUE;
}
return FALSE;
}
static int static int
cmd_hop (struct session *sess, char *tbuf, char *word[], char *word_eol[]) cmd_hop (struct session *sess, char *tbuf, char *word[], char *word_eol[])
{ {
@ -4013,7 +4002,7 @@ const struct commands xc_cmds[] = {
N_("EXECKILL [-9], kills a running exec in the current session. If -9 is given the process is SIGKILL'ed")}, N_("EXECKILL [-9], kills a running exec in the current session. If -9 is given the process is SIGKILL'ed")},
#ifndef __EMX__ #ifndef __EMX__
{"EXECSTOP", cmd_execs, 0, 0, 1, N_("EXECSTOP, sends the process SIGSTOP")}, {"EXECSTOP", cmd_execs, 0, 0, 1, N_("EXECSTOP, sends the process SIGSTOP")},
{"EXECWRITE", cmd_execw, 0, 0, 1, N_("EXECWRITE [-q|--], sends data to the processes stdin; use -q flag to quiet/suppress output at text box; use -- flag to stop interpreting arguments as flags, needed if -q itself would occur as data")}, {"EXECWRITE", cmd_execw, 0, 0, 1, N_("EXECWRITE, sends data to the processes stdin")},
#endif #endif
#endif #endif
#if 0 #if 0
@ -4028,9 +4017,8 @@ const struct commands xc_cmds[] = {
{"GETINT", cmd_getint, 0, 0, 1, "GETINT <default> <command> <prompt>"}, {"GETINT", cmd_getint, 0, 0, 1, "GETINT <default> <command> <prompt>"},
{"GETSTR", cmd_getstr, 0, 0, 1, "GETSTR <default> <command> <prompt>"}, {"GETSTR", cmd_getstr, 0, 0, 1, "GETSTR <default> <command> <prompt>"},
{"GHOST", cmd_ghost, 1, 0, 1, N_("GHOST <nick> [password], Kills a ghosted nickname")}, {"GHOST", cmd_ghost, 1, 0, 1, N_("GHOST <nick> [password], Kills a ghosted nickname")},
{"GUI", cmd_gui, 0, 0, 1, "GUI [APPLY|ATTACH|DETACH|SHOW|HIDE|FOCUS|FLASH|ICONIFY]\n" {"GUI", cmd_gui, 0, 0, 1, "GUI [APPLY|ATTACH|DETACH|SHOW|HIDE|FOCUS|FLASH|ICONIFY|COLOR <n>]\n"
" GUI [MSGBOX <text>|MENU TOGGLE]\n" " GUI [MSGBOX <text>|MENU TOGGLE]"},
" GUI COLOR <n> [-NOOVERRIDE]"},
{"HELP", cmd_help, 0, 0, 1, 0}, {"HELP", cmd_help, 0, 0, 1, 0},
{"HOP", cmd_hop, 1, 1, 1, {"HOP", cmd_hop, 1, 1, 1,
N_("HOP <nick>, gives chanhalf-op status to the nick (needs chanop)")}, N_("HOP <nick>, gives chanhalf-op status to the nick (needs chanop)")},
@ -4117,14 +4105,14 @@ const struct commands xc_cmds[] = {
{"SEND", cmd_send, 0, 0, 1, N_("SEND <nick> [<file>]")}, {"SEND", cmd_send, 0, 0, 1, N_("SEND <nick> [<file>]")},
#ifdef USE_OPENSSL #ifdef USE_OPENSSL
{"SERVCHAN", cmd_servchan, 0, 0, 1, {"SERVCHAN", cmd_servchan, 0, 0, 1,
N_("SERVCHAN [-insecure|-ssl|-ssl-noverify] <host> <port> <channel>, connects and joins a channel using ssl unless otherwise specified")}, N_("SERVCHAN [-ssl|-ssl-noverify] <host> <port> <channel>, connects and joins a channel")},
#else #else
{"SERVCHAN", cmd_servchan, 0, 0, 1, {"SERVCHAN", cmd_servchan, 0, 0, 1,
N_("SERVCHAN <host> <port> <channel>, connects and joins a channel")}, N_("SERVCHAN <host> <port> <channel>, connects and joins a channel")},
#endif #endif
#ifdef USE_OPENSSL #ifdef USE_OPENSSL
{"SERVER", cmd_server, 0, 0, 1, {"SERVER", cmd_server, 0, 0, 1,
N_("SERVER [-insecure|-ssl|-ssl-noverify] <host> [<port>] [<password>], connects to a server using ssl unless otherwise specified, the default port is 6697 for ssl connections and 6667 for insecure connections")}, N_("SERVER [-ssl|-ssl-noverify] <host> [<port>] [<password>], connects to a server, the default port is 6667 for normal connections, and 6697 for ssl connections")},
#else #else
{"SERVER", cmd_server, 0, 0, 1, {"SERVER", cmd_server, 0, 0, 1,
N_("SERVER <host> [<port>] [<password>], connects to a server, the default port is 6667")}, N_("SERVER <host> [<port>] [<password>], connects to a server, the default port is 6667")},
@ -4155,6 +4143,8 @@ const struct commands xc_cmds[] = {
{"USERLIST", cmd_userlist, 1, 1, 1, 0}, {"USERLIST", cmd_userlist, 1, 1, 1, 0},
{"VOICE", cmd_voice, 1, 1, 1, {"VOICE", cmd_voice, 1, 1, 1,
N_("VOICE <nick>, gives voice status to someone (needs chanop)")}, N_("VOICE <nick>, gives voice status to someone (needs chanop)")},
{"WALLCHAN", cmd_wallchan, 1, 1, 1,
N_("WALLCHAN <message>, writes the message to all channels")},
{"WALLCHOP", cmd_wallchop, 1, 1, 1, {"WALLCHOP", cmd_wallchop, 1, 1, 1,
N_("WALLCHOP <message>, sends the message to all chanops on the current channel")}, N_("WALLCHOP <message>, sends the message to all chanops on the current channel")},
{0, 0, 0, 0, 0, 0} {0, 0, 0, 0, 0, 0}

View File

@ -198,7 +198,7 @@ timer_cb (char *word[], char *word_eol[], void *userdata)
offset += 2; offset += 2;
} }
timeout = g_ascii_strtod (word[2 + offset], NULL); timeout = atof (word[2 + offset]);
command = word_eol[3 + offset]; command = word_eol[3 + offset];
if (timeout < 0.1 || timeout * 1000 > INT_MAX || !command[0]) if (timeout < 0.1 || timeout * 1000 > INT_MAX || !command[0])

View File

@ -461,7 +461,7 @@ channel_date (session *sess, char *chan, char *timestr,
} }
static int static int
trailing_index(char *word_eol[]) trailing_index(const char *word_eol[])
{ {
int param_index; int param_index;
for (param_index = 3; param_index < PDIWORDS; ++param_index) for (param_index = 3; param_index < PDIWORDS; ++param_index)
@ -503,6 +503,22 @@ process_numeric (session * sess, int n,
goto def; goto def;
case 4: /* check the ircd type */
serv->use_listargs = FALSE;
serv->modes_per_line = 3; /* default to IRC RFC */
if (strncmp (word[5], "bahamut", 7) == 0) /* DALNet */
{
serv->use_listargs = TRUE; /* use the /list args */
} else if (strncmp (word[5], "u2.10.", 6) == 0) /* Undernet */
{
serv->use_listargs = TRUE; /* use the /list args */
serv->modes_per_line = 6; /* allow 6 modes per line */
} else if (strncmp (word[5], "glx2", 4) == 0)
{
serv->use_listargs = TRUE; /* use the /list args */
}
goto def;
case 5: case 5:
inbound_005 (serv, word, tags_data); inbound_005 (serv, word, tags_data);
goto def; goto def;
@ -627,7 +643,7 @@ process_numeric (session * sess, int n,
case 320: /* :is an identified user */ case 320: /* :is an identified user */
if (!serv->skip_next_whois) if (!serv->skip_next_whois)
EMIT_SIGNAL_TIMESTAMP (XP_TE_WHOIS_ID, whois_sess, word[4], EMIT_SIGNAL_TIMESTAMP (XP_TE_WHOIS_ID, whois_sess, word[4],
word_eol[5][0] == ':' ? word_eol[5] + 1 : word_eol[5], NULL, NULL, 0, word_eol[5] + 1, NULL, NULL, 0,
tags_data->timestamp); tags_data->timestamp);
break; break;
@ -920,14 +936,6 @@ process_numeric (session * sess, int n,
notify_set_online (serv, word[4], tags_data); notify_set_online (serv, word[4], tags_data);
break; break;
case 524: // ERR_HELPNOTFOUND
case 704: // RPL_HELPSTART
case 705: // RPL_HELPTXT
case 706: // RPL_ENDOFHELP
EMIT_SIGNAL_TIMESTAMP (XP_TE_SERVTEXT, sess, STRIP_COLON(word, word_eol, 5), NULL, NULL, NULL,
0, tags_data->timestamp);
break;
case 728: /* +q-list entry */ case 728: /* +q-list entry */
/* NOTE: FREENODE returns these results inconsistent with e.g. +b */ /* NOTE: FREENODE returns these results inconsistent with e.g. +b */
/* Who else has imlemented MODE_QUIET, I wonder? */ /* Who else has imlemented MODE_QUIET, I wonder? */

File diff suppressed because it is too large Load Diff

View File

@ -25,7 +25,6 @@ extern GSList *serv_list;
/* eventually need to keep the tcp_* functions isolated to server.c */ /* eventually need to keep the tcp_* functions isolated to server.c */
int tcp_send_len (server *serv, char *buf, int len); int tcp_send_len (server *serv, char *buf, int len);
void tcp_sendf (server *serv, const char *fmt, ...) G_GNUC_PRINTF (2, 3); void tcp_sendf (server *serv, const char *fmt, ...) G_GNUC_PRINTF (2, 3);
int tcp_send_real (void *ssl, int sok, GIConv write_converter, char *buf, int len);
server *server_new (void); server *server_new (void);
int is_server (server *serv); int is_server (server *serv);
@ -39,6 +38,4 @@ void server_free (server *serv);
void server_away_save_message (server *serv, char *nick, char *msg); void server_away_save_message (server *serv, char *nick, char *msg);
struct away_msg *server_away_find_message (server *serv, char *nick); struct away_msg *server_away_find_message (server *serv, char *nick);
void base64_encode (char *to, char *from, unsigned int len);
#endif #endif

View File

@ -54,6 +54,8 @@ static const struct defaultserver def[] =
/* Invalid hostname in cert */ /* Invalid hostname in cert */
{0, "irc.2600.net"}, {0, "irc.2600.net"},
{"ACN", 0, 0, 0, LOGIN_SASL, 0, TRUE},
{0, "global.acn.gr"},
{"AfterNET", 0, 0, 0, LOGIN_SASL, 0, TRUE}, {"AfterNET", 0, 0, 0, LOGIN_SASL, 0, TRUE},
{0, "irc.afternet.org"}, {0, "irc.afternet.org"},
@ -185,12 +187,12 @@ static const struct defaultserver def[] =
{"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},
{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"},
{"IRCHighWay", 0, 0, 0, 0, 0, TRUE},
{0, "irc.irchighway.net"},
{"IRCNet", 0}, {"IRCNet", 0},
{0, "open.ircnet.net"}, {0, "open.ircnet.net"},
@ -305,9 +307,6 @@ 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"},
{"TechNet", 0, 0, 0, LOGIN_SASL, 0, TRUE},
{0, "irc.technet.chat"},
{"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"},

View File

@ -1,566 +0,0 @@
/*
* ssl.c v0.0.3
* Copyright (C) 2000 -- DaP <profeta@freemail.c3.hu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifdef __APPLE__
#define __AVAILABILITYMACROS__
#define DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER
#endif
#include "inet.h" /* make it first to avoid macro redefinitions */
#include <openssl/ssl.h> /* SSL_() */
#include <openssl/err.h> /* ERR_() */
#include <openssl/x509v3.h>
#ifdef WIN32
#include <openssl/rand.h> /* RAND_seed() */
#endif
#include "config.h"
#include <time.h> /* asctime() */
#include <string.h> /* strncpy() */
#include "ssl.h" /* struct cert_info */
#include <glib.h>
#include <glib/gprintf.h>
#include <gio/gio.h>
#include "util.h"
/* If openssl was built without ec */
#ifndef SSL_OP_SINGLE_ECDH_USE
#define SSL_OP_SINGLE_ECDH_USE 0
#endif
#ifndef SSL_OP_NO_COMPRESSION
#define SSL_OP_NO_COMPRESSION 0
#endif
/* globals */
static struct chiper_info chiper_info; /* static buffer for _SSL_get_cipher_info() */
static char err_buf[256]; /* generic error buffer */
/* +++++ Internal functions +++++ */
static void
__SSL_fill_err_buf (char *funcname)
{
int err;
char buf[256];
err = ERR_get_error ();
ERR_error_string (err, buf);
g_snprintf (err_buf, sizeof (err_buf), "%s: %s (%d)\n", funcname, buf, err);
}
static void
__SSL_critical_error (char *funcname)
{
__SSL_fill_err_buf (funcname);
fprintf (stderr, "%s\n", err_buf);
exit (1);
}
/* +++++ SSL functions +++++ */
SSL_CTX *
_SSL_context_init (void (*info_cb_func))
{
SSL_CTX *ctx;
SSLeay_add_ssl_algorithms ();
SSL_load_error_strings ();
ctx = SSL_CTX_new (SSLv23_client_method ());
SSL_CTX_set_session_cache_mode (ctx, SSL_SESS_CACHE_BOTH);
SSL_CTX_set_timeout (ctx, 300);
SSL_CTX_set_options (ctx, SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3
|SSL_OP_NO_COMPRESSION
|SSL_OP_SINGLE_DH_USE|SSL_OP_SINGLE_ECDH_USE
|SSL_OP_NO_TICKET
|SSL_OP_CIPHER_SERVER_PREFERENCE);
#if OPENSSL_VERSION_NUMBER >= 0x00908000L && !defined (OPENSSL_NO_COMP) /* workaround for OpenSSL 0.9.8 */
sk_SSL_COMP_zero(SSL_COMP_get_compression_methods());
#endif
/* used in SSL_connect(), SSL_accept() */
SSL_CTX_set_info_callback (ctx, info_cb_func);
return(ctx);
}
static void
ASN1_TIME_snprintf (char *buf, int buf_len, ASN1_TIME * tm)
{
char *expires = NULL;
BIO *inMem = BIO_new (BIO_s_mem ());
ASN1_TIME_print (inMem, tm);
BIO_get_mem_data (inMem, &expires);
buf[0] = 0;
if (expires != NULL)
{
/* expires is not \0 terminated */
safe_strcpy (buf, expires, MIN(24, buf_len));
}
BIO_free (inMem);
}
static void
broke_oneline (char *oneline, char *parray[])
{
char *pt, *ppt;
int i;
i = 0;
ppt = pt = oneline + 1;
while ((pt = strchr (pt, '/')))
{
*pt = 0;
parray[i++] = ppt;
ppt = ++pt;
}
parray[i++] = ppt;
parray[i] = NULL;
}
/*
FIXME: Master-Key, Extensions, CA bits
(openssl x509 -text -in servcert.pem)
*/
int
_SSL_get_cert_info (struct cert_info *cert_info, SSL * ssl)
{
X509 *peer_cert;
X509_PUBKEY *key;
X509_ALGOR *algor = NULL;
EVP_PKEY *peer_pkey;
char notBefore[64];
char notAfter[64];
int alg;
int sign_alg;
if (!(peer_cert = SSL_get_peer_certificate (ssl)))
return (1); /* FATAL? */
X509_NAME_oneline (X509_get_subject_name (peer_cert), cert_info->subject,
sizeof (cert_info->subject));
X509_NAME_oneline (X509_get_issuer_name (peer_cert), cert_info->issuer,
sizeof (cert_info->issuer));
broke_oneline (cert_info->subject, cert_info->subject_word);
broke_oneline (cert_info->issuer, cert_info->issuer_word);
key = X509_get_X509_PUBKEY(peer_cert);
if (!X509_PUBKEY_get0_param(NULL, NULL, 0, &algor, key))
return 1;
alg = OBJ_obj2nid (algor->algorithm);
#ifndef HAVE_X509_GET_SIGNATURE_NID
sign_alg = OBJ_obj2nid (peer_cert->sig_alg->algorithm);
#else
sign_alg = X509_get_signature_nid (peer_cert);
#endif
ASN1_TIME_snprintf (notBefore, sizeof (notBefore),
X509_get_notBefore (peer_cert));
ASN1_TIME_snprintf (notAfter, sizeof (notAfter),
X509_get_notAfter (peer_cert));
peer_pkey = X509_get_pubkey (peer_cert);
safe_strcpy (cert_info->algorithm,
(alg == NID_undef) ? "Unknown" : OBJ_nid2ln (alg),
sizeof (cert_info->algorithm));
cert_info->algorithm_bits = EVP_PKEY_bits (peer_pkey);
safe_strcpy (cert_info->sign_algorithm,
(sign_alg == NID_undef) ? "Unknown" : OBJ_nid2ln (sign_alg),
sizeof (cert_info->sign_algorithm));
/* EVP_PKEY_bits(ca_pkey)); */
cert_info->sign_algorithm_bits = 0;
safe_strcpy (cert_info->notbefore, notBefore, sizeof (cert_info->notbefore));
safe_strcpy (cert_info->notafter, notAfter, sizeof (cert_info->notafter));
EVP_PKEY_free (peer_pkey);
/* SSL_SESSION_print_fp(stdout, SSL_get_session(ssl)); */
/*
if (ssl->session->sess_cert->peer_rsa_tmp) {
tmp_pkey = EVP_PKEY_new();
EVP_PKEY_assign_RSA(tmp_pkey, ssl->session->sess_cert->peer_rsa_tmp);
cert_info->rsa_tmp_bits = EVP_PKEY_bits (tmp_pkey);
EVP_PKEY_free(tmp_pkey);
} else
fprintf(stderr, "REMOTE SIDE DOESN'T PROVIDES ->peer_rsa_tmp\n");
*/
cert_info->rsa_tmp_bits = 0;
X509_free (peer_cert);
return (0);
}
struct chiper_info *
_SSL_get_cipher_info (SSL * ssl)
{
const SSL_CIPHER *c;
c = SSL_get_current_cipher (ssl);
safe_strcpy (chiper_info.version, SSL_CIPHER_get_version (c),
sizeof (chiper_info.version));
safe_strcpy (chiper_info.chiper, SSL_CIPHER_get_name (c),
sizeof (chiper_info.chiper));
SSL_CIPHER_get_bits (c, &chiper_info.chiper_bits);
return (&chiper_info);
}
int
_SSL_send (SSL * ssl, char *buf, int len)
{
int num;
num = SSL_write (ssl, buf, len);
switch (SSL_get_error (ssl, num))
{
case SSL_ERROR_SSL: /* setup errno! */
/* ??? */
__SSL_fill_err_buf ("SSL_write");
fprintf (stderr, "%s\n", err_buf);
break;
case SSL_ERROR_SYSCALL:
/* ??? */
perror ("SSL_write/write");
break;
case SSL_ERROR_ZERO_RETURN:
/* fprintf(stderr, "SSL closed on write\n"); */
break;
}
return (num);
}
int
_SSL_recv (SSL * ssl, char *buf, int len)
{
int num;
num = SSL_read (ssl, buf, len);
switch (SSL_get_error (ssl, num))
{
case SSL_ERROR_SSL:
/* ??? */
__SSL_fill_err_buf ("SSL_read");
fprintf (stderr, "%s\n", err_buf);
break;
case SSL_ERROR_SYSCALL:
/* ??? */
if (!would_block ())
perror ("SSL_read/read");
break;
case SSL_ERROR_ZERO_RETURN:
/* fprintf(stdeerr, "SSL closed on read\n"); */
break;
}
return (num);
}
SSL *
_SSL_socket (SSL_CTX *ctx, int sd)
{
SSL *ssl;
const SSL_METHOD *method;
if (!(ssl = SSL_new (ctx)))
/* FATAL */
__SSL_critical_error ("SSL_new");
SSL_set_fd (ssl, sd);
#ifndef HAVE_SSL_CTX_GET_SSL_METHOD
method = ctx->method;
#else
method = SSL_CTX_get_ssl_method (ctx);
#endif
if (method == SSLv23_client_method())
SSL_set_connect_state (ssl);
else
SSL_set_accept_state(ssl);
return (ssl);
}
char *
_SSL_set_verify (SSL_CTX *ctx, void *verify_callback)
{
#ifdef DEFAULT_CERT_FILE
if (!SSL_CTX_load_verify_locations (ctx, DEFAULT_CERT_FILE, NULL))
{
__SSL_fill_err_buf ("SSL_CTX_load_verify_locations");
return (err_buf);
}
#else
if (!SSL_CTX_set_default_verify_paths (ctx))
{
__SSL_fill_err_buf ("SSL_CTX_set_default_verify_paths");
return (err_buf);
}
#endif
SSL_CTX_set_verify (ctx, SSL_VERIFY_PEER, verify_callback);
return (NULL);
}
void
_SSL_close (SSL * ssl)
{
SSL_set_shutdown (ssl, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);
SSL_free (ssl);
#ifdef HAVE_ERR_REMOVE_THREAD_STATE
#if OPENSSL_VERSION_NUMBER >= 0x10000000L && OPENSSL_VERSION_NUMBER < 0x10100000L
/* OpenSSL handles this itself in 1.1+ and this is a no-op */
ERR_remove_thread_state (NULL);
#endif
#else
ERR_remove_state (0);
#endif
}
/* Hostname validation code based on OpenBSD's libtls. */
static int
_SSL_match_hostname (const char *cert_hostname, const char *hostname)
{
const char *cert_domain, *domain, *next_dot;
if (g_ascii_strcasecmp (cert_hostname, hostname) == 0)
return 0;
/* Wildcard match? */
if (cert_hostname[0] == '*')
{
/*
* Valid wildcards:
* - "*.domain.tld"
* - "*.sub.domain.tld"
* - etc.
* Reject "*.tld".
* No attempt to prevent the use of eg. "*.co.uk".
*/
cert_domain = &cert_hostname[1];
/* Disallow "*" */
if (cert_domain[0] == '\0')
return -1;
/* Disallow "*foo" */
if (cert_domain[0] != '.')
return -1;
/* Disallow "*.." */
if (cert_domain[1] == '.')
return -1;
next_dot = strchr (&cert_domain[1], '.');
/* Disallow "*.bar" */
if (next_dot == NULL)
return -1;
/* Disallow "*.bar.." */
if (next_dot[1] == '.')
return -1;
domain = strchr (hostname, '.');
/* No wildcard match against a hostname with no domain part. */
if (domain == NULL || strlen(domain) == 1)
return -1;
if (g_ascii_strcasecmp (cert_domain, domain) == 0)
return 0;
}
return -1;
}
static int
_SSL_check_subject_altname (X509 *cert, const char *host)
{
STACK_OF(GENERAL_NAME) *altname_stack = NULL;
GInetAddress *addr;
GSocketFamily family;
int type = GEN_DNS;
int count, i;
int rv = -1;
altname_stack = X509_get_ext_d2i (cert, NID_subject_alt_name, NULL, NULL);
if (altname_stack == NULL)
return -1;
addr = g_inet_address_new_from_string (host);
if (addr != NULL)
{
family = g_inet_address_get_family (addr);
if (family == G_SOCKET_FAMILY_IPV4 || family == G_SOCKET_FAMILY_IPV6)
type = GEN_IPADD;
}
count = sk_GENERAL_NAME_num(altname_stack);
for (i = 0; i < count; i++)
{
GENERAL_NAME *altname;
altname = sk_GENERAL_NAME_value (altname_stack, i);
if (altname->type != type)
continue;
if (type == GEN_DNS)
{
const unsigned char *data;
int format;
format = ASN1_STRING_type (altname->d.dNSName);
if (format == V_ASN1_IA5STRING)
{
#ifdef HAVE_ASN1_STRING_GET0_DATA
data = ASN1_STRING_get0_data (altname->d.dNSName);
#else
data = ASN1_STRING_data (altname->d.dNSName);
#endif
if (ASN1_STRING_length (altname->d.dNSName) != (int)strlen(data))
{
g_warning("NUL byte in subjectAltName, probably a malicious certificate.\n");
rv = -2;
break;
}
if (_SSL_match_hostname (data, host) == 0)
{
rv = 0;
break;
}
}
else
g_warning ("unhandled subjectAltName dNSName encoding (%d)\n", format);
}
else if (type == GEN_IPADD)
{
const unsigned char *data;
const guint8 *addr_bytes;
int datalen, addr_len;
datalen = ASN1_STRING_length (altname->d.iPAddress);
#ifdef HAVE_ASN1_STRING_GET0_DATA
data = ASN1_STRING_get0_data (altname->d.iPAddress);
#else
data = ASN1_STRING_data (altname->d.iPAddress);
#endif
addr_bytes = g_inet_address_to_bytes (addr);
addr_len = (int)g_inet_address_get_native_size (addr);
if (datalen == addr_len && memcmp (data, addr_bytes, addr_len) == 0)
{
rv = 0;
break;
}
}
}
if (addr != NULL)
g_object_unref (addr);
sk_GENERAL_NAME_pop_free (altname_stack, GENERAL_NAME_free);
return rv;
}
static int
_SSL_check_common_name (X509 *cert, const char *host)
{
X509_NAME *name;
char *common_name = NULL;
int common_name_len;
int rv = -1;
GInetAddress *addr;
name = X509_get_subject_name (cert);
if (name == NULL)
return -1;
common_name_len = X509_NAME_get_text_by_NID (name, NID_commonName, NULL, 0);
if (common_name_len < 0)
return -1;
common_name = g_malloc0 (common_name_len + 1);
X509_NAME_get_text_by_NID (name, NID_commonName, common_name, common_name_len + 1);
/* NUL bytes in CN? */
if (common_name_len != (int)strlen(common_name))
{
g_warning ("NUL byte in Common Name field, probably a malicious certificate.\n");
rv = -2;
goto out;
}
if ((addr = g_inet_address_new_from_string (host)) != NULL)
{
/*
* We don't want to attempt wildcard matching against IP
* addresses, so perform a simple comparison here.
*/
if (g_strcmp0 (common_name, host) == 0)
rv = 0;
else
rv = -1;
g_object_unref (addr);
}
else if (_SSL_match_hostname (common_name, host) == 0)
rv = 0;
out:
g_free(common_name);
return rv;
}
int
_SSL_check_hostname (X509 *cert, const char *host)
{
int rv;
rv = _SSL_check_subject_altname (cert, host);
if (rv == 0 || rv == -2)
return rv;
return _SSL_check_common_name (cert, host);
}

View File

@ -1,85 +0,0 @@
/* HexChat
* Copyright (C) 1998-2010 Peter Zelezny.
* Copyright (C) 2009-2013 Berke Viktor.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef HEXCHAT_SSL_H
#define HEXCHAT_SSL_H
struct cert_info {
char subject[256];
char *subject_word[12];
char issuer[256];
char *issuer_word[12];
char algorithm[32];
int algorithm_bits;
char sign_algorithm[32];
int sign_algorithm_bits;
char notbefore[32];
char notafter[32];
int rsa_tmp_bits;
};
struct chiper_info {
char version[16];
char chiper[48];
int chiper_bits;
};
SSL_CTX *_SSL_context_init (void (*info_cb_func));
#define _SSL_context_free(a) SSL_CTX_free(a);
SSL *_SSL_socket (SSL_CTX *ctx, int sd);
char *_SSL_set_verify (SSL_CTX *ctx, void *(verify_callback));
/*
int SSL_connect(SSL *);
int SSL_accept(SSL *);
int SSL_get_fd(SSL *);
*/
void _SSL_close (SSL * ssl);
int _SSL_check_hostname(X509 *cert, const char *host);
int _SSL_get_cert_info (struct cert_info *cert_info, SSL * ssl);
struct chiper_info *_SSL_get_cipher_info (SSL * ssl);
/*char *_SSL_add_keypair (SSL_CTX *ctx, char *privkey, char *cert);*/
/*void _SSL_add_random_keypair(SSL_CTX *ctx, int bits);*/
int _SSL_send (SSL * ssl, char *buf, int len);
int _SSL_recv (SSL * ssl, char *buf, int len);
/* misc */
/*void broke_oneline (char *oneline, char *parray[]);*/
/*char *_SSL_do_cipher_base64(char *buf, int buf_len, char *key, int operation);*/ /* must be freed */
/*void *_SSL_get_sess_obj(SSL *ssl, int type);*/ /* NOT must be freed */
#define _SSL_get_sess_pkey(a) _SSL_get_sess_obj(a, 0)
#define _SSL_get_sess_prkey(a) _SSL_get_sess_obj(a, 1)
#define _SSL_get_sess_x509(a) _SSL_get_sess_obj(a, 2)
/*char *_SSL_get_obj_base64(void *s, int type);*/ /* must be freed */
#define _SSL_get_pkey_base64(a) _SSL_get_obj_base64(a, 0)
#define _SSL_get_prkey_base64(a) _SSL_get_obj_base64(a, 1)
#define _SSL_get_x509_base64(a) _SSL_get_obj_base64(a, 2)
/*char *_SSL_get_ctx_obj_base64(SSL_CTX *ctx, int type);*/ /* must be freed */
#define _SSL_get_ctx_pkey_base64(a) _SSL_get_ctx_obj_base64(a, 0)
#define _SSL_get_ctx_prkey_base64(a) _SSL_get_ctx_obj_base64(a, 1)
#define _SSL_get_ctx_x509_base64(a) _SSL_get_ctx_obj_base64(a, 2)
/*int _SSL_verify_x509(X509 *x509);*/
#endif

View File

@ -84,8 +84,7 @@ sysinfo_get_cpu_arch (void)
GetNativeSystemInfo (&si); GetNativeSystemInfo (&si);
if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64 || if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_ARM64)
{ {
return cpu_arch = 64; return cpu_arch = 64;
} }
@ -107,8 +106,7 @@ sysinfo_get_build_arch (void)
GetSystemInfo (&si); GetSystemInfo (&si);
if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64 || if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_ARM64)
{ {
return build_arch = 64; return build_arch = 64;
} }
@ -356,8 +354,6 @@ static char *read_cpu_info (IWbemClassObject *object)
VariantClear (&max_clock_speed_variant); VariantClear (&max_clock_speed_variant);
g_strchomp (name_utf8);
if (cpu_freq_mhz > 1000) if (cpu_freq_mhz > 1000)
{ {
result = g_strdup_printf ("%s (%.2fGHz)", name_utf8, cpu_freq_mhz / 1000.f); result = g_strdup_printf ("%s (%.2fGHz)", name_utf8, cpu_freq_mhz / 1000.f);

View File

@ -1323,7 +1323,6 @@ static char * const pevt_connect_help[] = {
}; };
static char * const pevt_sconnect_help[] = { static char * const pevt_sconnect_help[] = {
"PID"
}; };
static char * const pevt_generic_nick_help[] = { static char * const pevt_generic_nick_help[] = {

View File

@ -787,8 +787,8 @@ n2
Stop Connection Stop Connection
XP_TE_STOPCONNECT XP_TE_STOPCONNECT
pevt_sconnect_help pevt_sconnect_help
%C23*%O$tStopped previous connection attempt (%C24$1%O) %C23*%O$tStopped previous connection attempt
1 0
Topic Topic
XP_TE_TOPIC XP_TE_TOPIC

View File

@ -56,6 +56,9 @@
#ifdef USE_OPENSSL #ifdef USE_OPENSSL
#include <openssl/bn.h> #include <openssl/bn.h>
#include <openssl/rand.h> #include <openssl/rand.h>
#include <openssl/sha.h>
#include <openssl/evp.h>
#include <openssl/hmac.h>
#ifndef WIN32 #ifndef WIN32
#include <netinet/in.h> #include <netinet/in.h>
#endif #endif
@ -1375,16 +1378,11 @@ str_sha256hash (char *string)
int i; int i;
unsigned char hash[SHA256_DIGEST_LENGTH]; unsigned char hash[SHA256_DIGEST_LENGTH];
char buf[SHA256_DIGEST_LENGTH * 2 + 1]; /* 64 digit hash + '\0' */ char buf[SHA256_DIGEST_LENGTH * 2 + 1]; /* 64 digit hash + '\0' */
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
SHA256 (string, strlen (string), hash);
#else
SHA256_CTX sha256; SHA256_CTX sha256;
SHA256_Init (&sha256); SHA256_Init (&sha256);
SHA256_Update (&sha256, string, strlen (string)); SHA256_Update (&sha256, string, strlen (string));
SHA256_Final (hash, &sha256); SHA256_Final (hash, &sha256);
#endif
for (i = 0; i < SHA256_DIGEST_LENGTH; i++) for (i = 0; i < SHA256_DIGEST_LENGTH; i++)
{ {
@ -1555,3 +1553,52 @@ strftime_utf8 (char *dest, gsize destsize, const char *format, time_t time)
g_date_free (date); g_date_free (date);
return result; return result;
} }
static void
three_to_four (char *from, char *to)
{
static const char tab64[64]=
{
'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/'
};
to[0] = tab64 [ (from[0] >> 2) & 63 ];
to[1] = tab64 [ ((from[0] << 4) | (from[1] >> 4)) & 63 ];
to[2] = tab64 [ ((from[1] << 2) | (from[2] >> 6)) & 63 ];
to[3] = tab64 [ from[2] & 63 ];
};
void
base64_encode (char *to, char *from, unsigned int len)
{
while (len >= 3)
{
three_to_four (from, to);
len -= 3;
from += 3;
to += 4;
}
if (len)
{
char three[3] = {0,0,0};
unsigned int i;
for (i = 0; i < len; i++)
{
three[i] = *from++;
}
three_to_four (three, to);
if (len == 1)
{
to[2] = to[3] = '=';
}
else if (len == 2)
{
to[3] = '=';
}
to += 4;
};
to[0] = 0;
}

View File

@ -80,4 +80,6 @@ char *encode_sasl_pass_plain (char *user, char *pass);
char *challengeauth_response (const char *username, const char *password, const char *challenge); char *challengeauth_response (const char *username, const char *password, const char *challenge);
size_t strftime_validated (char *dest, size_t destsize, const char *format, const struct tm *time); size_t strftime_validated (char *dest, size_t destsize, const char *format, const struct tm *time);
gsize strftime_utf8 (char *dest, gsize destsize, const char *format, time_t time); gsize strftime_utf8 (char *dest, gsize destsize, const char *format, time_t time);
void base64_encode (char *to, char *from, unsigned int len);
#endif #endif

View File

@ -512,7 +512,7 @@ chanlist_save (GtkWidget * wid, server *serv)
GtkTreeModel *model = GET_MODEL (serv); GtkTreeModel *model = GET_MODEL (serv);
if (gtk_tree_model_get_iter_first (model, &iter)) if (gtk_tree_model_get_iter_first (model, &iter))
gtkutil_file_req (NULL, _("Select an output filename"), chanlist_filereq_done, gtkutil_file_req (_("Select an output filename"), chanlist_filereq_done,
serv, NULL, NULL, FRF_WRITE); serv, NULL, NULL, FRF_WRITE);
} }

View File

@ -146,7 +146,7 @@ fe_dcc_send_filereq (struct session *sess, char *nick, int maxcps, int passive)
mdc->maxcps = maxcps; mdc->maxcps = maxcps;
mdc->passive = passive; mdc->passive = passive;
gtkutil_file_req (NULL, tbuf, dcc_send_filereq_file, mdc, prefs.hex_dcc_dir, NULL, FRF_MULTIPLE|FRF_FILTERISINITIAL); gtkutil_file_req (tbuf, dcc_send_filereq_file, mdc, prefs.hex_dcc_dir, NULL, FRF_MULTIPLE|FRF_FILTERISINITIAL);
g_free (tbuf); g_free (tbuf);
} }

View File

@ -664,13 +664,13 @@ fe_print_text (struct session *sess, char *text, time_t stamp,
return; return;
if (sess == current_tab) if (sess == current_tab)
fe_set_tab_color (sess, FE_COLOR_NONE); fe_set_tab_color (sess, 0);
else if (sess->tab_state & TAB_STATE_NEW_HILIGHT) else if (sess->tab_state & TAB_STATE_NEW_HILIGHT)
fe_set_tab_color (sess, FE_COLOR_NEW_HILIGHT); fe_set_tab_color (sess, 3);
else if (sess->tab_state & TAB_STATE_NEW_MSG) else if (sess->tab_state & TAB_STATE_NEW_MSG)
fe_set_tab_color (sess, FE_COLOR_NEW_MSG); fe_set_tab_color (sess, 2);
else else
fe_set_tab_color (sess, FE_COLOR_NEW_DATA); fe_set_tab_color (sess, 1);
} }
void void
@ -903,7 +903,7 @@ fe_confirm (const char *message, void (*yesproc)(void *), void (*noproc)(void *)
if (dcc->file) if (dcc->file)
{ {
char *filepath = g_build_filename (prefs.hex_dcc_dir, dcc->file, NULL); char *filepath = g_build_filename (prefs.hex_dcc_dir, dcc->file, NULL);
gtkutil_file_req (NULL, message, dcc_saveas_cb, ud, filepath, NULL, gtkutil_file_req (message, dcc_saveas_cb, ud, filepath, NULL,
FRF_WRITE|FRF_NOASKOVERWRITE|FRF_FILTERISINITIAL); FRF_WRITE|FRF_NOASKOVERWRITE|FRF_FILTERISINITIAL);
g_free (filepath); g_free (filepath);
} }
@ -1054,45 +1054,6 @@ osx_show_uri (const char *url)
#endif #endif
static inline char *
escape_uri (const char *uri)
{
return g_uri_escape_string(uri, G_URI_RESERVED_CHARS_GENERIC_DELIMITERS G_URI_RESERVED_CHARS_SUBCOMPONENT_DELIMITERS, FALSE);
}
static inline gboolean
uri_contains_forbidden_characters (const char *uri)
{
while (*uri)
{
if (!g_ascii_isalnum (*uri) && !strchr ("-._~:/?#[]@!$&'()*+,;=", *uri))
return TRUE;
uri++;
}
return FALSE;
}
static char *
maybe_escape_uri (const char *uri)
{
/* The only way to know if a string has already been escaped or not
* is by fulling parsing each segement but we can try some more simple heuristics. */
/* If we find characters that should clearly be escaped. */
if (uri_contains_forbidden_characters (uri))
return escape_uri (uri);
/* If it fails to be unescaped then it was not escaped. */
char *unescaped = g_uri_unescape_string (uri, NULL);
if (!unescaped)
return escape_uri (uri);
g_free (unescaped);
/* At this point it is probably safe to pass through as-is. */
return g_strdup (uri);
}
static void static void
fe_open_url_inner (const char *url) fe_open_url_inner (const char *url)
{ {
@ -1110,8 +1071,8 @@ fe_open_url_inner (const char *url)
#elif defined(__APPLE__) #elif defined(__APPLE__)
osx_show_uri (url); osx_show_uri (url);
#else #else
char *escaped_url = maybe_escape_uri (url); char *escaped_url = g_uri_escape_string (url, G_URI_RESERVED_CHARS_GENERIC_DELIMITERS G_URI_RESERVED_CHARS_SUBCOMPONENT_DELIMITERS,
g_debug ("Opening URL \"%s\" (%s)", escaped_url, url); FALSE);
gtk_show_uri (NULL, escaped_url, GDK_CURRENT_TIME, NULL); gtk_show_uri (NULL, escaped_url, GDK_CURRENT_TIME, NULL);
g_free (escaped_url); g_free (escaped_url);
#endif #endif
@ -1215,7 +1176,7 @@ fe_get_file (const char *title, char *initial,
{ {
/* OK: Call callback once per file, then once more with file=NULL. */ /* OK: Call callback once per file, then once more with file=NULL. */
/* CANCEL: Call callback once with file=NULL. */ /* CANCEL: Call callback once with file=NULL. */
gtkutil_file_req (NULL, title, callback, userdata, initial, NULL, flags | FRF_FILTERISINITIAL); gtkutil_file_req (title, callback, userdata, initial, NULL, flags | FRF_FILTERISINITIAL);
} }
void void

View File

@ -894,7 +894,7 @@ key_save_kbs (void)
#define STRIP_WHITESPACE \ #define STRIP_WHITESPACE \
while (buf[0] == ' ' || buf[0] == '\t') \ while (buf[0] == ' ' || buf[0] == '\t') \
buf++; \ buf++; \
len = strlen (buf); \ len = strlen (buf); \
while (buf[len] == ' ' || buf[len] == '\t') \ while (buf[len] == ' ' || buf[len] == '\t') \
{ \ { \
buf[len] = 0; \ buf[len] = 0; \

View File

@ -190,7 +190,7 @@ gtkutil_file_req_response (GtkWidget *dialog, gint res, struct file_req *freq)
} }
void void
gtkutil_file_req (GtkWindow *parent, const char *title, void *callback, void *userdata, char *filter, char *extensions, gtkutil_file_req (const char *title, void *callback, void *userdata, char *filter, char *extensions,
int flags) int flags)
{ {
struct file_req *freq; struct file_req *freq;
@ -269,16 +269,6 @@ gtkutil_file_req (GtkWindow *parent, const char *title, void *callback, void *us
G_CALLBACK (gtkutil_file_req_response), freq); G_CALLBACK (gtkutil_file_req_response), freq);
g_signal_connect (G_OBJECT (dialog), "destroy", g_signal_connect (G_OBJECT (dialog), "destroy",
G_CALLBACK (gtkutil_file_req_destroy), (gpointer) freq); G_CALLBACK (gtkutil_file_req_destroy), (gpointer) freq);
if (parent)
gtk_window_set_transient_for (GTK_WINDOW (dialog), parent);
if (flags & FRF_MODAL)
{
g_assert (parent);
gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
}
gtk_widget_show (dialog); gtk_widget_show (dialog);
} }

View File

@ -25,7 +25,7 @@
typedef void (*filereqcallback) (void *, char *file); typedef void (*filereqcallback) (void *, char *file);
void gtkutil_file_req (GtkWindow *parent, const char *title, void *callback, void *userdata, char *filter, char *extensions, int flags); void gtkutil_file_req (const char *title, void *callback, void *userdata, char *filter, char *extensions, int flags);
void gtkutil_destroy (GtkWidget * igad, GtkWidget * dgad); void gtkutil_destroy (GtkWidget * igad, GtkWidget * dgad);
void gtkutil_destroy_on_esc (GtkWidget *win); void gtkutil_destroy_on_esc (GtkWidget *win);
GtkWidget *gtkutil_button (GtkWidget *box, char *stock, char *tip, void *callback, GtkWidget *gtkutil_button (GtkWidget *box, char *stock, char *tip, void *callback,

View File

@ -175,26 +175,20 @@ fe_flash_window (session *sess)
/* set a tab plain, red, light-red, or blue */ /* set a tab plain, red, light-red, or blue */
void void
fe_set_tab_color (struct session *sess, tabcolor col) fe_set_tab_color (struct session *sess, int col)
{ {
struct session *server_sess = sess->server->server_session; struct session *server_sess = sess->server->server_session;
int col_noflags = (col & ~FE_COLOR_ALLFLAGS);
int col_shouldoverride = !(col & FE_COLOR_FLAG_NOOVERRIDE);
if (sess->res->tab && sess->gui->is_tab && (col == 0 || sess != current_tab)) if (sess->res->tab && sess->gui->is_tab && (col == 0 || sess != current_tab))
{ {
switch (col_noflags) switch (col)
{ {
case 0: /* no particular color (theme default) */ case 0: /* no particular color (theme default) */
sess->tab_state = TAB_STATE_NONE; sess->tab_state = TAB_STATE_NONE;
chan_set_color (sess->res->tab, plain_list); chan_set_color (sess->res->tab, plain_list);
break; break;
case 1: /* new data has been displayed (dark red) */ case 1: /* new data has been displayed (dark red) */
if (col_shouldoverride || !((sess->tab_state & TAB_STATE_NEW_MSG) sess->tab_state = TAB_STATE_NEW_DATA;
|| (sess->tab_state & TAB_STATE_NEW_HILIGHT))) { chan_set_color (sess->res->tab, newdata_list);
sess->tab_state = TAB_STATE_NEW_DATA;
chan_set_color (sess->res->tab, newdata_list);
}
if (chan_is_collapsed (sess->res->tab) if (chan_is_collapsed (sess->res->tab)
&& !((server_sess->tab_state & TAB_STATE_NEW_MSG) && !((server_sess->tab_state & TAB_STATE_NEW_MSG)
@ -207,10 +201,8 @@ fe_set_tab_color (struct session *sess, tabcolor col)
break; break;
case 2: /* new message arrived in channel (light red) */ case 2: /* new message arrived in channel (light red) */
if (col_shouldoverride || !(sess->tab_state & TAB_STATE_NEW_HILIGHT)) { sess->tab_state = TAB_STATE_NEW_MSG;
sess->tab_state = TAB_STATE_NEW_MSG; chan_set_color (sess->res->tab, newmsg_list);
chan_set_color (sess->res->tab, newmsg_list);
}
if (chan_is_collapsed (sess->res->tab) if (chan_is_collapsed (sess->res->tab)
&& !(server_sess->tab_state & TAB_STATE_NEW_HILIGHT) && !(server_sess->tab_state & TAB_STATE_NEW_HILIGHT)
@ -399,22 +391,27 @@ fe_set_title (session *sess)
_(DISPLAY_NAME)); _(DISPLAY_NAME));
break; break;
case SESS_SERVER: case SESS_SERVER:
g_snprintf (tbuf, sizeof (tbuf), "%s%s%s - %s", g_snprintf (tbuf, sizeof (tbuf), "%s @ %s - %s",
prefs.hex_gui_win_nick ? sess->server->nick : "", sess->server->nick, server_get_network (sess->server, TRUE),
prefs.hex_gui_win_nick ? " @ " : "", server_get_network (sess->server, TRUE),
_(DISPLAY_NAME)); _(DISPLAY_NAME));
break; break;
case SESS_CHANNEL: case SESS_CHANNEL:
/* don't display keys in the titlebar */ /* don't display keys in the titlebar */
if (prefs.hex_gui_win_modes)
{
g_snprintf (tbuf, sizeof (tbuf), g_snprintf (tbuf, sizeof (tbuf),
"%s%s%s / %s%s%s%s - %s", "%s @ %s / %s (%s) - %s",
prefs.hex_gui_win_nick ? sess->server->nick : "", sess->server->nick, server_get_network (sess->server, TRUE),
prefs.hex_gui_win_nick ? " @ " : "", sess->channel, sess->current_modes ? sess->current_modes : "",
server_get_network (sess->server, TRUE), sess->channel, _(DISPLAY_NAME));
prefs.hex_gui_win_modes && sess->current_modes ? " (" : "", }
prefs.hex_gui_win_modes && sess->current_modes ? sess->current_modes : "", else
prefs.hex_gui_win_modes && sess->current_modes ? ")" : "", {
_(DISPLAY_NAME)); g_snprintf (tbuf, sizeof (tbuf),
"%s @ %s / %s - %s",
sess->server->nick, server_get_network (sess->server, TRUE),
sess->channel, _(DISPLAY_NAME));
}
if (prefs.hex_gui_win_ucount) if (prefs.hex_gui_win_ucount)
{ {
g_snprintf (tbuf + strlen (tbuf), 9, " (%d)", sess->total); g_snprintf (tbuf + strlen (tbuf), 9, " (%d)", sess->total);
@ -422,9 +419,8 @@ fe_set_title (session *sess)
break; break;
case SESS_NOTICES: case SESS_NOTICES:
case SESS_SNOTICES: case SESS_SNOTICES:
g_snprintf (tbuf, sizeof (tbuf), "%s%s%s (notices) - %s", g_snprintf (tbuf, sizeof (tbuf), "%s @ %s (notices) - %s",
prefs.hex_gui_win_nick ? sess->server->nick : "", sess->server->nick, server_get_network (sess->server, TRUE),
prefs.hex_gui_win_nick ? " @ " : "", server_get_network (sess->server, TRUE),
_(DISPLAY_NAME)); _(DISPLAY_NAME));
break; break;
default: default:
@ -544,7 +540,7 @@ mg_focus (session *sess)
/* when called via mg_changui_new, is_tab might be true, but /* when called via mg_changui_new, is_tab might be true, but
sess->res->tab is still NULL. */ sess->res->tab is still NULL. */
if (sess->res->tab) if (sess->res->tab)
fe_set_tab_color (sess, FE_COLOR_NONE); fe_set_tab_color (sess, 0);
} }
static int static int

View File

@ -1362,7 +1362,7 @@ savebuffer_req_done (session *sess, char *file)
static void static void
menu_savebuffer (GtkWidget * wid, gpointer none) menu_savebuffer (GtkWidget * wid, gpointer none)
{ {
gtkutil_file_req (NULL, _("Select an output filename"), savebuffer_req_done, gtkutil_file_req (_("Select an output filename"), savebuffer_req_done,
current_sess, NULL, NULL, FRF_WRITE); current_sess, NULL, NULL, FRF_WRITE);
} }

View File

@ -18,7 +18,6 @@
#include "config.h" #include "config.h"
#include <string.h>
#include <gio/gio.h> #include <gio/gio.h>
static GDBusProxy *fdo_notifications; static GDBusProxy *fdo_notifications;
@ -56,7 +55,7 @@ notification_backend_show (const char *title, const char *text)
g_variant_builder_init (&params, G_VARIANT_TYPE ("(susssasa{sv}i)")); g_variant_builder_init (&params, G_VARIANT_TYPE ("(susssasa{sv}i)"));
g_variant_builder_add (&params, "s", "hexchat"); /* App name */ g_variant_builder_add (&params, "s", "hexchat"); /* App name */
g_variant_builder_add (&params, "u", 0); /* ID, 0 means don't replace */ g_variant_builder_add (&params, "u", 0); /* ID, 0 means don't replace */
g_variant_builder_add (&params, "s", "io.github.Hexchat"); /* App icon */ g_variant_builder_add (&params, "s", ""); /* App icon (set from hints instead) */
g_variant_builder_add (&params, "s", title); g_variant_builder_add (&params, "s", title);
g_variant_builder_add (&params, "s", text); g_variant_builder_add (&params, "s", text);
g_variant_builder_add (&params, "as", NULL); /* Actions */ g_variant_builder_add (&params, "as", NULL); /* Actions */

View File

@ -218,7 +218,7 @@ notification_plugin_init (hexchat_plugin *plugin_handle, char **plugin_name, cha
if (!notification_backend_init (&error)) if (!notification_backend_init (&error))
{ {
if (error) if (error)
g_debug("Failed loading notification plugin: %s\n", error); hexchat_printf(plugin_handle, "Failed loading notification plugin: %s\n", error);
return 0; return 0;
} }
@ -246,7 +246,7 @@ notification_plugin_init (hexchat_plugin *plugin_handle, char **plugin_name, cha
int int
notification_plugin_deinit (void *unused_param) notification_plugin_deinit (void)
{ {
notification_backend_deinit (); notification_backend_deinit ();
return 1; return 1;

View File

@ -161,7 +161,7 @@ plugingui_load (void)
{ {
char *sub_dir = g_build_filename (get_xdir(), "addons", NULL); char *sub_dir = g_build_filename (get_xdir(), "addons", NULL);
gtkutil_file_req (NULL, _("Select a Plugin or Script to load"), plugingui_load_cb, current_sess, gtkutil_file_req (_("Select a Plugin or Script to load"), plugingui_load_cb, current_sess,
sub_dir, "*."PLUGIN_SUFFIX";*.lua;*.pl;*.py;*.tcl;*.js", FRF_FILTERISINITIAL|FRF_EXTENSIONS); sub_dir, "*."PLUGIN_SUFFIX";*.lua;*.pl;*.py;*.tcl;*.js", FRF_FILTERISINITIAL|FRF_EXTENSIONS);
g_free (sub_dir); g_free (sub_dir);

View File

@ -77,7 +77,7 @@ rawlog_clearbutton (GtkWidget * wid, server *serv)
static int static int
rawlog_savebutton (GtkWidget * wid, server *serv) rawlog_savebutton (GtkWidget * wid, server *serv)
{ {
gtkutil_file_req (NULL, _("Save As..."), rawlog_save, serv, NULL, NULL, FRF_WRITE); gtkutil_file_req (_("Save As..."), rawlog_save, serv, NULL, NULL, FRF_WRITE);
return FALSE; return FALSE;
} }

View File

@ -48,7 +48,6 @@ GtkStyle *create_input_style (GtkStyle *);
#define LABEL_INDENT 12 #define LABEL_INDENT 12
static GtkWidget *setup_window = NULL;
static int last_selected_page = 0; static int last_selected_page = 0;
static int last_selected_row = 0; /* sound row */ static int last_selected_row = 0; /* sound row */
static gboolean color_change; static gboolean color_change;
@ -176,7 +175,6 @@ static const setting appearance_settings[] =
{ST_HEADER, N_("Title Bar"),0,0,0}, {ST_HEADER, N_("Title Bar"),0,0,0},
{ST_TOGGLE, N_("Show channel modes"), P_OFFINTNL(hex_gui_win_modes),0,0,0}, {ST_TOGGLE, N_("Show channel modes"), P_OFFINTNL(hex_gui_win_modes),0,0,0},
{ST_TOGGLR, N_("Show number of users"), P_OFFINTNL(hex_gui_win_ucount),0,0,0}, {ST_TOGGLR, N_("Show number of users"), P_OFFINTNL(hex_gui_win_ucount),0,0,0},
{ST_TOGGLE, N_("Show nickname"), P_OFFINTNL(hex_gui_win_nick),0,0,0},
{ST_END, 0, 0, 0, 0, 0} {ST_END, 0, 0, 0, 0, 0}
}; };
@ -1107,8 +1105,8 @@ setup_browsefile_cb (GtkWidget *button, GtkWidget *entry)
filter = "image/*"; filter = "image/*";
filter_type = FRF_MIMETYPES; filter_type = FRF_MIMETYPES;
#endif #endif
gtkutil_file_req (GTK_WINDOW (setup_window), _("Select an Image File"), setup_filereq_cb, gtkutil_file_req (_("Select an Image File"), setup_filereq_cb,
entry, NULL, filter, filter_type|FRF_RECENTLYUSED|FRF_MODAL); entry, NULL, filter, filter_type|FRF_RECENTLYUSED);
} }
static void static void
@ -1143,7 +1141,7 @@ setup_fontsel_cancel (GtkWidget *button, GtkFontSelectionDialog *dialog)
static void static void
setup_browsefolder_cb (GtkWidget *button, GtkEntry *entry) setup_browsefolder_cb (GtkWidget *button, GtkEntry *entry)
{ {
gtkutil_file_req (GTK_WINDOW (setup_window), _("Select Download Folder"), setup_filereq_cb, entry, (char*)gtk_entry_get_text (entry), NULL, FRF_CHOOSEFOLDER|FRF_MODAL); gtkutil_file_req (_("Select Download Folder"), setup_filereq_cb, entry, (char*)gtk_entry_get_text (entry), NULL, FRF_CHOOSEFOLDER);
} }
static void static void
@ -1156,9 +1154,6 @@ setup_browsefont_cb (GtkWidget *button, GtkWidget *entry)
dialog = (GtkFontSelectionDialog *) gtk_font_selection_dialog_new (_("Select font")); dialog = (GtkFontSelectionDialog *) gtk_font_selection_dialog_new (_("Select font"));
font_dialog = (GtkWidget *)dialog; /* global var */ font_dialog = (GtkWidget *)dialog; /* global var */
gtk_window_set_transient_for (GTK_WINDOW (font_dialog), GTK_WINDOW (setup_window));
gtk_window_set_modal (GTK_WINDOW (font_dialog), TRUE);
sel = (GtkFontSelection *) gtk_font_selection_dialog_get_font_selection (dialog); sel = (GtkFontSelection *) gtk_font_selection_dialog_get_font_selection (dialog);
if (gtk_entry_get_text (GTK_ENTRY (entry))[0]) if (gtk_entry_get_text (GTK_ENTRY (entry))[0])
@ -1462,8 +1457,6 @@ setup_color_cb (GtkWidget *button, gpointer userdata)
g_object_set_data (G_OBJECT (ok_button), "b", button); g_object_set_data (G_OBJECT (ok_button), "b", button);
gtk_widget_set_sensitive (help_button, FALSE); gtk_widget_set_sensitive (help_button, FALSE);
gtk_color_selection_set_current_color (GTK_COLOR_SELECTION (gtk_color_selection_dialog_get_color_selection (cdialog)), color); gtk_color_selection_set_current_color (GTK_COLOR_SELECTION (gtk_color_selection_dialog_get_color_selection (cdialog)), color);
gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (setup_window));
gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
gtk_widget_show (dialog); gtk_widget_show (dialog);
g_object_unref (cancel_button); g_object_unref (cancel_button);
@ -1718,8 +1711,8 @@ setup_snd_browse_cb (GtkWidget *button, GtkEntry *entry)
filter_type = FRF_MIMETYPES; filter_type = FRF_MIMETYPES;
#endif #endif
gtkutil_file_req (GTK_WINDOW (setup_window), _("Select a sound file"), setup_snd_filereq_cb, entry, gtkutil_file_req (_("Select a sound file"), setup_snd_filereq_cb, entry,
sounds_dir, filter, FRF_MODAL|FRF_FILTERISINITIAL|filter_type); sounds_dir, filter, FRF_FILTERISINITIAL|filter_type);
g_free (sounds_dir); g_free (sounds_dir);
} }
@ -2343,6 +2336,8 @@ setup_close_cb (GtkWidget *win, GtkWidget **swin)
void void
setup_open (void) setup_open (void)
{ {
static GtkWidget *setup_window = NULL;
if (setup_window) if (setup_window)
{ {
gtk_window_present (GTK_WINDOW (setup_window)); gtk_window_present (GTK_WINDOW (setup_window));

View File

@ -1255,7 +1255,7 @@ void
sexy_spell_entry_activate_default_languages(SexySpellEntry *entry) sexy_spell_entry_activate_default_languages(SexySpellEntry *entry)
{ {
GSList *enchant_langs; GSList *enchant_langs;
char *lang, **i, **langs; char *lang, *langs;
if (!have_enchant) if (!have_enchant)
return; return;
@ -1265,21 +1265,21 @@ sexy_spell_entry_activate_default_languages(SexySpellEntry *entry)
enchant_langs = sexy_spell_entry_get_languages(entry); enchant_langs = sexy_spell_entry_get_languages(entry);
langs = g_strsplit_set (prefs.hex_text_spell_langs, ", \t", 0); langs = g_strdup (prefs.hex_text_spell_langs);
for (i = langs; *i; i++) lang = strtok (langs, ",");
while (lang != NULL)
{ {
lang = *i;
if (enchant_has_lang (lang, enchant_langs)) if (enchant_has_lang (lang, enchant_langs))
{ {
sexy_spell_entry_activate_language_internal (entry, lang, NULL); sexy_spell_entry_activate_language_internal (entry, lang, NULL);
} }
lang = strtok (NULL, ",");
} }
g_slist_foreach(enchant_langs, (GFunc) g_free, NULL); g_slist_foreach(enchant_langs, (GFunc) g_free, NULL);
g_slist_free(enchant_langs); g_slist_free(enchant_langs);
g_strfreev (langs); g_free (langs);
/* If we don't have any languages activated, use "en" */ /* If we don't have any languages activated, use "en" */
if (entry->priv->dict_list == NULL) if (entry->priv->dict_list == NULL)

View File

@ -282,7 +282,7 @@ pevent_save_cb (GtkWidget * wid, void *data)
{ {
if (data) if (data)
{ {
gtkutil_file_req (NULL, _("Print Texts File"), pevent_save_req_cb, NULL, gtkutil_file_req (_("Print Texts File"), pevent_save_req_cb, NULL,
NULL, NULL, FRF_WRITE); NULL, NULL, FRF_WRITE);
return; return;
} }
@ -304,7 +304,7 @@ pevent_load_req_cb (void *arg1, char *file)
static void static void
pevent_load_cb (GtkWidget * wid, void *data) pevent_load_cb (GtkWidget * wid, void *data)
{ {
gtkutil_file_req (NULL, _("Print Texts File"), pevent_load_req_cb, NULL, NULL, NULL, 0); gtkutil_file_req (_("Print Texts File"), pevent_load_req_cb, NULL, NULL, NULL, 0);
} }
static void static void

View File

@ -145,7 +145,7 @@ url_save_callback (void *arg1, char *file)
static void static void
url_button_save (void) url_button_save (void)
{ {
gtkutil_file_req (NULL, _("Select an output filename"), gtkutil_file_req (_("Select an output filename"),
url_save_callback, NULL, NULL, NULL, FRF_WRITE); url_save_callback, NULL, NULL, NULL, FRF_WRITE);
} }

View File

@ -947,7 +947,7 @@ gtk_xtext_find_char (GtkXText * xtext, int x, int y, int *off, int *out_of_bound
textentry *ent; textentry *ent;
int line; int line;
int subline; int subline;
int outofbounds = FALSE; int outofbounds;
/* Adjust y value for negative rounding, double to int */ /* Adjust y value for negative rounding, double to int */
if (y < 0) if (y < 0)

View File

@ -623,7 +623,7 @@ fe_cleanup (void)
{ {
} }
void void
fe_set_tab_color (struct session *sess, tabcolor col) fe_set_tab_color (struct session *sess, int col)
{ {
} }
void void

View File

@ -40,8 +40,7 @@
<None Include="$(DepsRoot)\bin\gthread-2.0-0.dll" /> <None Include="$(DepsRoot)\bin\gthread-2.0-0.dll" />
<None Include="$(DepsRoot)\bin\gtk-win32-2.0.dll" /> <None Include="$(DepsRoot)\bin\gtk-win32-2.0.dll" />
<None Include="$(DepsRoot)\bin\iconv.dll" /> <None Include="$(DepsRoot)\bin\iconv.dll" />
<None Include="$(DepsRoot)\bin\libcrypto*.dll" /> <None Include="$(DepsRoot)\bin\libeay32.dll" />
<None Include="$(DepsRoot)\bin\libssl*.dll" />
<None Include="$(DepsRoot)\bin\libenchant.dll" /> <None Include="$(DepsRoot)\bin\libenchant.dll" />
<None Include="$(DepsRoot)\bin\ffi-7.dll" /> <None Include="$(DepsRoot)\bin\ffi-7.dll" />
<None Include="$(DepsRoot)\bin\intl.dll" /> <None Include="$(DepsRoot)\bin\intl.dll" />
@ -51,6 +50,7 @@
<None Include="$(DepsRoot)\bin\pangocairo-1.0-0.dll" /> <None Include="$(DepsRoot)\bin\pangocairo-1.0-0.dll" />
<None Include="$(DepsRoot)\bin\pangoft2-1.0-0.dll" /> <None Include="$(DepsRoot)\bin\pangoft2-1.0-0.dll" />
<None Include="$(DepsRoot)\bin\pangowin32-1.0-0.dll" /> <None Include="$(DepsRoot)\bin\pangowin32-1.0-0.dll" />
<None Include="$(DepsRoot)\bin\ssleay32.dll" />
<None Include="$(DepsRoot)\bin\zlib1.dll" /> <None Include="$(DepsRoot)\bin\zlib1.dll" />
<None Include="$(WinSparklePath)\WinSparkle.dll" /> <None Include="$(WinSparklePath)\WinSparkle.dll" />
<None Include="$(HexChatBin)thememan.exe" /> <None Include="$(HexChatBin)thememan.exe" />

View File

@ -8,14 +8,14 @@
<YourGendefPath>c:\gtk-build\gendef</YourGendefPath> <YourGendefPath>c:\gtk-build\gendef</YourGendefPath>
<YourPerlPath>c:\gtk-build\perl-5.20</YourPerlPath> <YourPerlPath>c:\gtk-build\perl-5.20</YourPerlPath>
<YourPython2Path>c:\gtk-build\python-2.7</YourPython2Path> <YourPython2Path>c:\gtk-build\python-2.7</YourPython2Path>
<YourPython3Path>c:\gtk-build\python-3.8</YourPython3Path> <YourPython3Path>c:\gtk-build\python-3.6</YourPython3Path>
<YourWinSparklePath>c:\gtk-build\WinSparkle</YourWinSparklePath> <YourWinSparklePath>c:\gtk-build\WinSparkle</YourWinSparklePath>
<!-- YOU SHOULDN'T TOUCH ANYTHING BELOW --> <!-- YOU SHOULDN'T TOUCH ANYTHING BELOW -->
<!-- G_DISABLE_DEPRECATED is unfeasible due to g_completion_* --> <!-- G_DISABLE_DEPRECATED is unfeasible due to g_completion_* -->
<!-- must be buildable with GSEAL_ENABLE in the future, xtext, setup, and chanview-tabs stand in the way --> <!-- must be buildable with GSEAL_ENABLE in the future, xtext, setup, and chanview-tabs stand in the way -->
<OwnFlags>GTK_DISABLE_DEPRECATED;GDK_PIXBUF_DISABLE_DEPRECATED;G_DISABLE_SINGLE_INCLUDES;GDK_PIXBUF_DISABLE_SINGLE_INCLUDES;GTK_DISABLE_SINGLE_INCLUDES;HAVE_X509_GET_SIGNATURE_NID;HAVE_SSL_CTX_GET_SSL_METHOD;DEFAULT_CERT_FILE="cert.pem";HAVE_STRTOULL;strtoull=_strtoui64;strcasecmp=stricmp;strncasecmp=strnicmp;__inline__=__inline</OwnFlags> <OwnFlags>GTK_DISABLE_DEPRECATED;GDK_PIXBUF_DISABLE_DEPRECATED;G_DISABLE_SINGLE_INCLUDES;GDK_PIXBUF_DISABLE_SINGLE_INCLUDES;GTK_DISABLE_SINGLE_INCLUDES;HAVE_STRTOULL;strtoull=_strtoui64;strcasecmp=stricmp;strncasecmp=strnicmp;__inline__=__inline</OwnFlags>
<!-- FIXME: Add ability to use debug builds --> <!-- FIXME: Add ability to use debug builds -->
<DepsRoot>$(YourDepsPath)\$(PlatformName)\release</DepsRoot> <DepsRoot>$(YourDepsPath)\$(PlatformName)\release</DepsRoot>
<GendefPath>$(YourGendefPath)</GendefPath> <GendefPath>$(YourGendefPath)</GendefPath>
@ -26,14 +26,14 @@
<Python2Lib>python27</Python2Lib> <Python2Lib>python27</Python2Lib>
<Python2Output>hcpython2</Python2Output> <Python2Output>hcpython2</Python2Output>
<Python3Path>$(YourPython3Path)\$(PlatformName)</Python3Path> <Python3Path>$(YourPython3Path)\$(PlatformName)</Python3Path>
<Python3Lib>python38</Python3Lib> <Python3Lib>python36</Python3Lib>
<Python3Output>hcpython3</Python3Output> <Python3Output>hcpython3</Python3Output>
<LuaInclude>$(DepsRoot)\include\luajit-2.1</LuaInclude> <LuaInclude>$(DepsRoot)\include\luajit-2.1</LuaInclude>
<LuaOutput>hclua</LuaOutput> <LuaOutput>hclua</LuaOutput>
<LuaLib>lua51</LuaLib> <LuaLib>lua51</LuaLib>
<Glib>$(DepsRoot)\include\glib-2.0;$(DepsRoot)\lib\glib-2.0\include;$(DepsRoot)\include\libxml2</Glib> <Glib>$(DepsRoot)\include\glib-2.0;$(DepsRoot)\lib\glib-2.0\include;$(DepsRoot)\include\libxml2</Glib>
<Gtk>$(DepsRoot)\include\gtk-2.0;$(DepsRoot)\lib\gtk-2.0\include;$(DepsRoot)\include\atk-1.0;$(DepsRoot)\include\cairo;$(DepsRoot)\include\pango-1.0;$(DepsRoot)\include\gdk-pixbuf-2.0</Gtk> <Gtk>$(DepsRoot)\include\gtk-2.0;$(DepsRoot)\lib\gtk-2.0\include;$(DepsRoot)\include\atk-1.0;$(DepsRoot)\include\cairo;$(DepsRoot)\include\pango-1.0;$(DepsRoot)\include\gdk-pixbuf-2.0</Gtk>
<DepLibs>gtk-win32-2.0.lib;gdk-win32-2.0.lib;atk-1.0.lib;gio-2.0.lib;gdk_pixbuf-2.0.lib;pangowin32-1.0.lib;pangocairo-1.0.lib;pango-1.0.lib;cairo.lib;gobject-2.0.lib;gmodule-2.0.lib;glib-2.0.lib;intl.lib;libxml2.lib;libcrypto.lib;libssl.lib;ssleay32.lib;wininet.lib;winmm.lib;ws2_32.lib</DepLibs> <DepLibs>gtk-win32-2.0.lib;gdk-win32-2.0.lib;atk-1.0.lib;gio-2.0.lib;gdk_pixbuf-2.0.lib;pangowin32-1.0.lib;pangocairo-1.0.lib;pango-1.0.lib;cairo.lib;gobject-2.0.lib;gmodule-2.0.lib;glib-2.0.lib;intl.lib;libxml2.lib;libeay32.lib;ssleay32.lib;wininet.lib;winmm.lib;ws2_32.lib</DepLibs>
<DataDir>$(SolutionDir)..\data\\</DataDir> <DataDir>$(SolutionDir)..\data\\</DataDir>
<HexChatBuild>$(SolutionDir)..\..\hexchat-build</HexChatBuild> <HexChatBuild>$(SolutionDir)..\..\hexchat-build</HexChatBuild>
<HexChatBin>$(HexChatBuild)\$(PlatformName)\bin\</HexChatBin> <HexChatBin>$(HexChatBuild)\$(PlatformName)\bin\</HexChatBin>

View File

@ -25,7 +25,7 @@ DefaultDirName={pf64}\HexChat
DefaultDirName={pf32}\HexChat DefaultDirName={pf32}\HexChat
#endif #endif
DefaultGroupName=HexChat DefaultGroupName=HexChat
AllowNoIcons=yes DisableProgramGroupPage=yes
SolidCompression=yes SolidCompression=yes
Compression=lzma2/ultra64 Compression=lzma2/ultra64
SourceDir=..\rel SourceDir=..\rel
@ -60,9 +60,6 @@ Name: "custom"; Description: "Custom Installation"; Flags: iscustom
Name: "libs"; Description: "HexChat"; Types: normal minimal custom; Flags: fixed Name: "libs"; Description: "HexChat"; Types: normal minimal custom; Flags: fixed
Name: "xctext"; Description: "HexChat-Text"; Types: custom; Flags: disablenouninstallwarning Name: "xctext"; Description: "HexChat-Text"; Types: custom; Flags: disablenouninstallwarning
Name: "xtm"; Description: "HexChat Theme Manager"; Types: normal custom; Flags: disablenouninstallwarning Name: "xtm"; Description: "HexChat Theme Manager"; Types: normal custom; Flags: disablenouninstallwarning
Name: "icons"; Description: "Create Shortcuts"; Types: custom; Flags: disablenouninstallwarning
Name: "icons\desktopicon"; Description: "Create Desktop Shortcut"; Types: custom; Flags: disablenouninstallwarning
Name: "icons\quicklaunchicon"; Description: "Create Quick Launch Shortcut"; Types: custom; Flags: disablenouninstallwarning
Name: "translations"; Description: "Translations"; Types: normal custom; Flags: disablenouninstallwarning Name: "translations"; Description: "Translations"; Types: normal custom; Flags: disablenouninstallwarning
Name: "spell"; Description: "Spelling Dictionaries"; Types: custom; Flags: disablenouninstallwarning Name: "spell"; Description: "Spelling Dictionaries"; Types: custom; Flags: disablenouninstallwarning
Name: "plugins"; Description: "Plugins"; Types: custom; Flags: disablenouninstallwarning Name: "plugins"; Description: "Plugins"; Types: custom; Flags: disablenouninstallwarning
@ -77,7 +74,7 @@ Name: "langs\lua"; Description: "Lua"; Types: normal custom; Flags: disablenouni
Name: "langs\perl"; Description: "Perl (requires Perl 5.20)"; Types: custom; Flags: disablenouninstallwarning Name: "langs\perl"; Description: "Perl (requires Perl 5.20)"; Types: custom; Flags: disablenouninstallwarning
Name: "langs\python"; Description: "Python Interface"; Types: custom; Flags: disablenouninstallwarning Name: "langs\python"; Description: "Python Interface"; Types: custom; Flags: disablenouninstallwarning
Name: "langs\python\python2"; Description: "Python (requires Python 2.7)"; Types: custom; Flags: disablenouninstallwarning exclusive Name: "langs\python\python2"; Description: "Python (requires Python 2.7)"; Types: custom; Flags: disablenouninstallwarning exclusive
Name: "langs\python\python3"; Description: "Python (requires Python 3.8)"; Types: custom; Flags: disablenouninstallwarning exclusive Name: "langs\python\python3"; Description: "Python (requires Python 3.6)"; Types: custom; Flags: disablenouninstallwarning exclusive
[Tasks] [Tasks]
Name: portable; Description: "Yes"; GroupDescription: "Portable Mode: Stores configuration files within install directory for portable drives."; Flags: unchecked Name: portable; Description: "Yes"; GroupDescription: "Portable Mode: Stores configuration files within install directory for portable drives."; Flags: unchecked
@ -141,13 +138,7 @@ Source: "gspawn-win32-helper-console.exe"; DestDir: "{app}"; Flags: ignoreversio
Source: "gthread-2.0-0.dll"; DestDir: "{app}"; Flags: ignoreversion; Components: libs Source: "gthread-2.0-0.dll"; DestDir: "{app}"; Flags: ignoreversion; Components: libs
Source: "gtk-win32-2.0.dll"; DestDir: "{app}"; Flags: ignoreversion; Components: libs Source: "gtk-win32-2.0.dll"; DestDir: "{app}"; Flags: ignoreversion; Components: libs
Source: "iconv.dll"; DestDir: "{app}"; Flags: ignoreversion; Components: libs Source: "iconv.dll"; DestDir: "{app}"; Flags: ignoreversion; Components: libs
#if APPARCH == "x64" Source: "libeay32.dll"; DestDir: "{app}"; Flags: ignoreversion; Components: libs
Source: "libcrypto-1_1-x64.dll"; DestDir: "{app}"; Flags: ignoreversion; Components: libs
Source: "libssl-1_1-x64.dll"; DestDir: "{app}"; Flags: ignoreversion; Components: libs
#else
Source: "libcrypto-1_1.dll"; DestDir: "{app}"; Flags: ignoreversion; Components: libs
Source: "libssl-1_1.dll"; DestDir: "{app}"; Flags: ignoreversion; Components: libs
#endif
Source: "libenchant.dll"; DestDir: "{app}"; Flags: ignoreversion; Components: libs Source: "libenchant.dll"; DestDir: "{app}"; Flags: ignoreversion; Components: libs
Source: "ffi-7.dll"; DestDir: "{app}"; Flags: ignoreversion; Components: libs Source: "ffi-7.dll"; DestDir: "{app}"; Flags: ignoreversion; Components: libs
Source: "intl.dll"; DestDir: "{app}"; Flags: ignoreversion; Components: libs Source: "intl.dll"; DestDir: "{app}"; Flags: ignoreversion; Components: libs
@ -157,6 +148,7 @@ Source: "pango-1.0-0.dll"; DestDir: "{app}"; Flags: ignoreversion; Components: l
Source: "pangocairo-1.0-0.dll"; DestDir: "{app}"; Flags: ignoreversion; Components: libs Source: "pangocairo-1.0-0.dll"; DestDir: "{app}"; Flags: ignoreversion; Components: libs
Source: "pangoft2-1.0-0.dll"; DestDir: "{app}"; Flags: ignoreversion; Components: libs Source: "pangoft2-1.0-0.dll"; DestDir: "{app}"; Flags: ignoreversion; Components: libs
Source: "pangowin32-1.0-0.dll"; DestDir: "{app}"; Flags: ignoreversion; Components: libs Source: "pangowin32-1.0-0.dll"; DestDir: "{app}"; Flags: ignoreversion; Components: libs
Source: "ssleay32.dll"; DestDir: "{app}"; Flags: ignoreversion; Components: libs
Source: "zlib1.dll"; DestDir: "{app}"; Flags: ignoreversion; Components: libs Source: "zlib1.dll"; DestDir: "{app}"; Flags: ignoreversion; Components: libs
Source: "plugins\hcnotifications-winrt.dll"; DestDir: "{app}\plugins"; Flags: ignoreversion; Components: libs Source: "plugins\hcnotifications-winrt.dll"; DestDir: "{app}\plugins"; Flags: ignoreversion; Components: libs
@ -199,16 +191,14 @@ Source: "hexchat-text.exe"; DestDir: "{app}"; Flags: ignoreversion; Components:
Source: "thememan.exe"; DestDir: "{app}"; Flags: ignoreversion; Components: xtm Source: "thememan.exe"; DestDir: "{app}"; Flags: ignoreversion; Components: xtm
[Icons] [Icons]
Name: "{group}\HexChat"; Filename: "{app}\hexchat.exe"; AppUserModelID: "HexChat.Desktop.Notify"; Tasks: not portable; Check: not WizardNoIcons Name: "{group}\HexChat"; Filename: "{app}\hexchat.exe"; AppUserModelID: "HexChat.Desktop.Notify"; Tasks: not portable
Name: "{group}\HexChat Safe Mode"; Filename: "{app}\hexchat.exe"; Parameters: "--no-auto --no-plugins"; Tasks: not portable; Check: not WizardNoIcons Name: "{group}\HexChat Safe Mode"; Filename: "{app}\hexchat.exe"; Parameters: "--no-auto --no-plugins"; Tasks: not portable
Name: "{group}\HexChat ChangeLog"; Filename: "{app}\changelog.url"; IconFilename: "{sys}\shell32.dll"; IconIndex: 165; Tasks: not portable; Check: not WizardNoIcons Name: "{group}\HexChat ChangeLog"; Filename: "{app}\changelog.url"; IconFilename: "{sys}\shell32.dll"; IconIndex: 165; Tasks: not portable
Name: "{group}\HexChat ReadMe"; Filename: "{app}\readme.url"; IconFilename: "{sys}\shell32.dll"; IconIndex: 23; Tasks: not portable; Check: not WizardNoIcons Name: "{group}\HexChat ReadMe"; Filename: "{app}\readme.url"; IconFilename: "{sys}\shell32.dll"; IconIndex: 23; Tasks: not portable
Name: "{group}\HexChat Config Folder"; Filename: "%APPDATA%\HexChat\"; Tasks: not portable; Check: not WizardNoIcons Name: "{group}\HexChat Config Folder"; Filename: "%APPDATA%\HexChat\"; Tasks: not portable
Name: "{group}\HexChat-Text"; Filename: "{app}\hexchat-text.exe"; Components: xctext; Tasks: not portable; Check: not WizardNoIcons Name: "{group}\HexChat-Text"; Filename: "{app}\hexchat-text.exe"; Components: xctext; Tasks: not portable
Name: "{group}\HexChat Theme Manager"; Filename: "{app}\thememan.exe"; Components: xtm; Tasks: not portable; Check: not WizardNoIcons Name: "{group}\HexChat Theme Manager"; Filename: "{app}\thememan.exe"; Components: xtm; Tasks: not portable
Name: "{group}\Uninstall HexChat"; Filename: "{uninstallexe}"; Tasks: not portable; Check: not WizardNoIcons Name: "{group}\Uninstall HexChat"; Filename: "{uninstallexe}"; Tasks: not portable
Name: "{commondesktop}\HexChat"; Filename: "{app}\hexchat.exe"; AppUserModelID: "HexChat.Desktop.Notify"; Components: icons\desktopicon; Tasks: not portable
Name: "{commonappdata}\Microsoft\Internet Explorer\Quick Launch\HexChat"; Filename: "{app}\hexchat.exe"; Components: icons\quicklaunchicon; Tasks: not portable
[Messages] [Messages]
BeveledLabel= {#APPNAM} BeveledLabel= {#APPNAM}
@ -303,14 +293,14 @@ begin
REDIST := 'https://dl.hexchat.net/misc/vcredist_2015_x64.exe'; REDIST := 'https://dl.hexchat.net/misc/vcredist_2015_x64.exe';
REDIST_2013 := 'https://dl.hexchat.net/misc/vcredist_2013_x64.exe'; REDIST_2013 := 'https://dl.hexchat.net/misc/vcredist_2013_x64.exe';
PERL := 'https://dl.hexchat.net/misc/perl/Perl%205.20.0%20x64.msi'; PERL := 'https://dl.hexchat.net/misc/perl/Perl%205.20.0%20x64.msi';
PY2 := 'https://www.python.org/ftp/python/2.7.18/python-2.7.18.amd64.msi'; PY2 := 'https://www.python.org/ftp/python/2.7.14/python-2.7.14.amd64.msi';
PY3 := 'https://www.python.org/ftp/python/3.8.10/python-3.8.10-amd64.exe'; PY3 := 'https://www.python.org/ftp/python/3.6.4/python-3.6.4-amd64.exe';
#else #else
REDIST := 'https://dl.hexchat.net/misc/vcredist_2015_x86.exe'; REDIST := 'https://dl.hexchat.net/misc/vcredist_2015_x86.exe';
REDIST_2013 := 'https://dl.hexchat.net/misc/vcredist_2013_x86.exe'; REDIST_2013 := 'https://dl.hexchat.net/misc/vcredist_2013_x86.exe';
PERL := 'https://dl.hexchat.net/misc/perl/Perl%205.20.0%20x86.msi'; PERL := 'https://dl.hexchat.net/misc/perl/Perl%205.20.0%20x86.msi';
PY2 := 'https://www.python.org/ftp/python/2.7.18/python-2.7.18.msi'; PY2 := 'https://www.python.org/ftp/python/2.7.14/python-2.7.14.msi';
PY3 := 'https://www.python.org/ftp/python/3.8.10/python-3.8.10.exe'; PY3 := 'https://www.python.org/ftp/python/3.6.4/python-3.6.4.exe';
#endif #endif
DOTNET := 'https://dl.hexchat.net/misc/dotnet_40.exe'; DOTNET := 'https://dl.hexchat.net/misc/dotnet_40.exe';
SPELL := 'https://dl.hexchat.net/hexchat/HexChat%20Spelling%20Dictionaries%20r2.exe'; SPELL := 'https://dl.hexchat.net/hexchat/HexChat%20Spelling%20Dictionaries%20r2.exe';
@ -337,7 +327,7 @@ begin
if IsComponentSelected('langs\python\python2') and not CheckDLL('python27.dll') then if IsComponentSelected('langs\python\python2') and not CheckDLL('python27.dll') then
idpAddFile(PY2, ExpandConstant('{tmp}\python.msi')); idpAddFile(PY2, ExpandConstant('{tmp}\python.msi'));
if IsComponentSelected('langs\python\python3') and not CheckDLL('python38.dll') then if IsComponentSelected('langs\python\python3') and not CheckDLL('python36.dll') then
idpAddFile(PY3, ExpandConstant('{tmp}\python.exe')); idpAddFile(PY3, ExpandConstant('{tmp}\python.exe'));
end; end;
end; end;