Compare commits

..

1 Commits

Author SHA1 Message Date
Patrick Griffis
36f2528b78 checksum: Move checksum operation to a thread 2022-10-24 20:42:30 -05:00
12 changed files with 157 additions and 247 deletions

View File

@@ -19,7 +19,6 @@ jobs:
mingw-w64-x86_64-python3-cffi mingw-w64-x86_64-python3-cffi
mingw-w64-x86_64-meson mingw-w64-x86_64-meson
mingw-w64-x86_64-gtk2 mingw-w64-x86_64-gtk2
mingw-w64-x86_64-gtk-update-icon-cache
mingw-w64-x86_64-luajit mingw-w64-x86_64-luajit
mingw-w64-x86_64-desktop-file-utils mingw-w64-x86_64-desktop-file-utils

View File

@@ -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.36.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',
@@ -47,8 +47,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_36')
config_h.set('GLIB_VERSION_MIN_REQUIRED', 'GLIB_VERSION_2_34') config_h.set('GLIB_VERSION_MIN_REQUIRED', 'GLIB_VERSION_2_36')
# Detected features # Detected features
config_h.set('HAVE_MEMRCHR', cc.has_function('memrchr')) config_h.set('HAVE_MEMRCHR', cc.has_function('memrchr'))

View File

@@ -22,218 +22,152 @@
#include "config.h" #include "config.h"
#include <stdlib.h>
#include <glib.h>
#include <glib/gstdio.h>
#include <gio/gio.h> #include <gio/gio.h>
#include "hexchat-plugin.h" #include "hexchat-plugin.h"
#define BUFSIZE 32768
#define DEFAULT_LIMIT 256 /* default size is 256 MiB */
#define SHA256_DIGEST_LENGTH 32
#define SHA256_BUFFER_LENGTH 65
static hexchat_plugin *ph; /* plugin handle */ static hexchat_plugin *ph; /* plugin handle */
static char name[] = "Checksum"; static char name[] = "Checksum";
static char desc[] = "Calculate checksum for DCC file transfers"; static char desc[] = "Calculate checksum for DCC file transfers";
static char version[] = "3.1"; static char version[] = "4.0";
static void static void
set_limit (char *size) print_sha256_result (hexchat_context *ctx, gboolean send_message, const char *checksum, const char *filename, GError *error)
{ {
int limit = atoi (size); /* Context may have been destroyed. */
/* FIXME: This could still send the PRIVMSG even if the context was closed. */
if (!hexchat_set_context (ph, ctx))
return;
if (limit > 0 && limit < INT_MAX) if (error)
{ hexchat_printf (ph, "Failed to create checksum for %s: %s", filename, error->message);
if (hexchat_pluginpref_set_int (ph, "limit", limit)) else if (send_message)
hexchat_printf (ph, "Checksum: File size limit has successfully been set to: %d MiB\n", limit); hexchat_commandf (ph, "quote PRIVMSG %s :SHA-256 checksum for %s (remote): %s", hexchat_get_info (ph, "channel"), filename, checksum);
else
hexchat_printf (ph, "Checksum: File access error while saving!\n");
}
else else
{ hexchat_printf (ph, "SHA-256 checksum for %s (local): %s\n", filename, checksum);
hexchat_printf (ph, "Checksum: Invalid input!\n");
}
} }
static int /* TODO: We could put more info in task data and share the same callback. */
get_limit (void) static void
on_received_file_sha256_complete (GFile *file, GAsyncResult *result, gpointer user_data)
{ {
int size = hexchat_pluginpref_get_int (ph, "limit"); hexchat_context *ctx = user_data;
GError *error = NULL;
char *sha256 = NULL;
const char *filename = g_task_get_task_data (G_TASK (result));
if (size <= 0 || size >= INT_MAX) sha256 = g_task_propagate_pointer (G_TASK (result), &error);
return DEFAULT_LIMIT; print_sha256_result (ctx, FALSE, sha256, filename, error);
else
return size; g_free (sha256);
g_clear_error (&error);
} }
static gboolean static void
check_limit (GFile *file) on_sent_file_sha256_complete (GFile *file, GAsyncResult *result, gpointer user_data)
{ {
GFileInfo *file_info; hexchat_context *ctx = user_data;
goffset file_size; GError *error = NULL;
char *sha256 = NULL;
const char *filename = g_task_get_task_data (G_TASK (result));
file_info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_SIZE, G_FILE_QUERY_INFO_NONE, sha256 = g_task_propagate_pointer (G_TASK (result), &error);
NULL, NULL); print_sha256_result (ctx, TRUE, sha256, filename, error);
if (!file_info) g_free (sha256);
return FALSE; g_clear_error (&error);
file_size = g_file_info_get_size (file_info);
g_object_unref (file_info);
if (file_size > get_limit () * 1048576ll)
return FALSE;
return TRUE;
} }
static gboolean static void
sha256_from_stream (GFileInputStream *file_stream, char out_buf[]) thread_sha256_file (GTask *task, GFile *file, gpointer task_data, GCancellable *cancellable)
{ {
GChecksum *checksum; GChecksum *checksum;
gssize bytes_read; GFileInputStream *istream;
guint8 digest[SHA256_DIGEST_LENGTH]; guint8 buffer[32768];
gsize digest_len = sizeof(digest); GError *error = NULL;
guchar buffer[BUFSIZE]; gssize ret;
gsize i;
istream = g_file_read (file, cancellable, &error);
if (error) {
g_task_return_error (task, error);
return;
}
checksum = g_checksum_new (G_CHECKSUM_SHA256); checksum = g_checksum_new (G_CHECKSUM_SHA256);
while ((bytes_read = g_input_stream_read (G_INPUT_STREAM (file_stream), buffer, sizeof (buffer), NULL, NULL))) while ((ret = g_input_stream_read (G_INPUT_STREAM (istream), buffer, sizeof(buffer), cancellable, &error)) > 0)
{ g_checksum_update (checksum, buffer, ret);
if (bytes_read == -1)
{
g_checksum_free (checksum);
return FALSE;
}
g_checksum_update (checksum, buffer, bytes_read); if (error) {
g_checksum_free (checksum);
g_task_return_error (task, error);
return;
} }
g_checksum_get_digest (checksum, digest, &digest_len); g_task_return_pointer (task, g_strdup (g_checksum_get_string (checksum)), g_free);
g_checksum_free (checksum); g_checksum_free (checksum);
for (i = 0; i < SHA256_DIGEST_LENGTH; i++)
{
/* out_buf will be exactly SHA256_BUFFER_LENGTH including null */
g_sprintf (out_buf + (i * 2), "%02x", digest[i]);
}
return TRUE;
}
static gboolean
sha256_from_file (char *filename, char out_buf[])
{
GFileInputStream *file_stream;
char *filename_fs;
GFile *file;
filename_fs = g_filename_from_utf8 (filename, -1, NULL, NULL, NULL);
if (!filename_fs)
{
hexchat_printf (ph, "Checksum: Invalid filename (%s)\n", filename);
return FALSE;
}
file = g_file_new_for_path (filename_fs);
g_free (filename_fs);
if (!file)
{
hexchat_printf (ph, "Checksum: Failed to open %s\n", filename);
return FALSE;
}
if (!check_limit (file))
{
hexchat_printf (ph, "Checksum: %s is larger than size limit. You can increase it with /CHECKSUM SET.\n", filename);
g_object_unref (file);
return FALSE;
}
file_stream = g_file_read (file, NULL, NULL);
if (!file_stream)
{
hexchat_printf (ph, "Checksum: Failed to read file %s\n", filename);
g_object_unref (file);
return FALSE;
}
if (!sha256_from_stream (file_stream, out_buf))
{
hexchat_printf (ph, "Checksum: Failed to generate checksum for %s\n", filename);
g_object_unref (file_stream);
g_object_unref (file);
return FALSE;
}
g_object_unref (file_stream);
g_object_unref (file);
return TRUE;
} }
static int static int
dccrecv_cb (char *word[], void *userdata) dccrecv_cb (char *word[], void *userdata)
{ {
GTask *task;
char *filename_fs;
GFile *file;
hexchat_context *ctx;
const char *dcc_completed_dir; const char *dcc_completed_dir;
char *filename, checksum[SHA256_BUFFER_LENGTH]; char *filename;
/* Print in the privmsg tab of the sender */
hexchat_set_context (ph, hexchat_find_context (ph, NULL, word[3]));
if (hexchat_get_prefs (ph, "dcc_completed_dir", &dcc_completed_dir, NULL) == 1 && dcc_completed_dir[0] != '\0') if (hexchat_get_prefs (ph, "dcc_completed_dir", &dcc_completed_dir, NULL) == 1 && dcc_completed_dir[0] != '\0')
filename = g_build_filename (dcc_completed_dir, word[1], NULL); filename = g_build_filename (dcc_completed_dir, word[1], NULL);
else else
filename = g_strdup (word[2]); filename = g_strdup (word[2]);
if (sha256_from_file (filename, checksum)) filename_fs = g_filename_from_utf8 (filename, -1, NULL, NULL, NULL);
{ if (!filename_fs) {
hexchat_printf (ph, "SHA-256 checksum for %s (local): %s\n", word[1], checksum); hexchat_printf (ph, "Checksum: Invalid filename (%s)\n", filename);
g_free (filename);
return HEXCHAT_EAT_NONE;
} }
g_free (filename); /* Print in the privmsg tab of the sender */
ctx = hexchat_find_context (ph, NULL, word[3]);
file = g_file_new_for_path (filename_fs);
task = g_task_new (file, NULL, (GAsyncReadyCallback) on_received_file_sha256_complete, ctx);
g_task_set_task_data (task, filename, g_free);
g_task_run_in_thread (task, (GTaskThreadFunc) thread_sha256_file);
g_free (filename_fs);
g_object_unref (file);
g_object_unref (task);
return HEXCHAT_EAT_NONE; return HEXCHAT_EAT_NONE;
} }
static int static int
dccoffer_cb (char *word[], void *userdata) dccoffer_cb (char *word[], void *userdata)
{ {
char checksum[SHA256_BUFFER_LENGTH]; GFile *file;
GTask *task;
hexchat_context *ctx;
char *filename;
/* Print in the privmsg tab of the receiver */ /* Print in the privmsg tab of the receiver */
hexchat_set_context (ph, hexchat_find_context (ph, NULL, word[3])); ctx = hexchat_find_context (ph, NULL, word[3]);
if (sha256_from_file (word[3], checksum)) filename = g_strdup (word[3]);
{ file = g_file_new_for_path (filename);
hexchat_commandf (ph, "quote PRIVMSG %s :SHA-256 checksum for %s (remote): %s", word[2], word[1], checksum); task = g_task_new (file, NULL, (GAsyncReadyCallback) on_sent_file_sha256_complete, ctx);
} g_task_set_task_data (task, filename, g_free);
g_task_run_in_thread (task, (GTaskThreadFunc) thread_sha256_file);
g_object_unref (file);
g_object_unref (task);
return HEXCHAT_EAT_NONE; return HEXCHAT_EAT_NONE;
} }
static int
checksum (char *word[], char *word_eol[], void *userdata)
{
if (!g_ascii_strcasecmp ("GET", word[2]))
{
hexchat_printf (ph, "File size limit for checksums: %d MiB", get_limit ());
}
else if (!g_ascii_strcasecmp ("SET", word[2]))
{
set_limit (word[3]);
}
else
{
hexchat_printf (ph, "Usage: /CHECKSUM GET|SET\n");
hexchat_printf (ph, " GET - print the maximum file size (in MiB) to be hashed\n");
hexchat_printf (ph, " SET <filesize> - set the maximum file size (in MiB) to be hashed\n");
}
return HEXCHAT_EAT_ALL;
}
int int
hexchat_plugin_init (hexchat_plugin *plugin_handle, char **plugin_name, char **plugin_desc, char **plugin_version, char *arg) hexchat_plugin_init (hexchat_plugin *plugin_handle, char **plugin_name, char **plugin_desc, char **plugin_version, char *arg)
{ {
@@ -243,13 +177,6 @@ hexchat_plugin_init (hexchat_plugin *plugin_handle, char **plugin_name, char **p
*plugin_desc = desc; *plugin_desc = desc;
*plugin_version = version; *plugin_version = version;
/* this is required for the very first run */
if (hexchat_pluginpref_get_int (ph, "limit") == -1)
{
hexchat_pluginpref_set_int (ph, "limit", DEFAULT_LIMIT);
}
hexchat_hook_command (ph, "CHECKSUM", HEXCHAT_PRI_NORM, checksum, "Usage: /CHECKSUM GET|SET", NULL);
hexchat_hook_print (ph, "DCC RECV Complete", HEXCHAT_PRI_NORM, dccrecv_cb, NULL); hexchat_hook_print (ph, "DCC RECV Complete", HEXCHAT_PRI_NORM, dccrecv_cb, NULL);
hexchat_hook_print (ph, "DCC Offer", HEXCHAT_PRI_NORM, dccoffer_cb, NULL); hexchat_hook_print (ph, "DCC Offer", HEXCHAT_PRI_NORM, dccoffer_cb, NULL);

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

@@ -150,7 +150,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;

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",

View File

@@ -305,9 +305,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

@@ -1065,7 +1065,8 @@ uri_contains_forbidden_characters (const char *uri)
{ {
while (*uri) while (*uri)
{ {
if (!g_ascii_isalnum (*uri) && !strchr ("-._~:/?#[]@!$&'()*+,;=", *uri)) /* This is not an exhaustive list, the full URI has segments that allow characters like "[]:" for example. */
if (strchr ("`<> ${}\"+", *uri) != NULL || (*uri & 0x80) /* non-ascii */)
return TRUE; return TRUE;
uri++; uri++;
} }

View File

@@ -399,22 +399,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 +427,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:

View File

@@ -176,7 +176,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}
}; };

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
@@ -199,16 +196,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}