Compare commits
70 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ba143b4260 | |||
| 232096801b | |||
| c0769397d5 | |||
| c9b63f7f9b | |||
| ebaaf466bf | |||
| 4b6215051f | |||
| f83d78dd28 | |||
| 9fb4eb5107 | |||
| 3c89de48a8 | |||
| 6653582f0a | |||
| abaed2bda4 | |||
| e8fb2dde56 | |||
| 25c6638ce4 | |||
| ce4e129849 | |||
| ecd1aa226a | |||
| 760d18b6e7 | |||
| f389257403 | |||
| 84df81f336 | |||
| a9a6cbda4e | |||
| 7a4a0243bd | |||
| e209e55e59 | |||
| ad2300f236 | |||
| 80bdd9ce11 | |||
| 5f99d34c3b | |||
| 2aa3eb8cfb | |||
| d1b9118056 | |||
| fd95c729d5 | |||
| d1c40196e3 | |||
| 9716185edf | |||
| a38892ff3b | |||
| dc18e3da07 | |||
| 9127b510f2 | |||
| 8f9ed6d942 | |||
| 422edd8812 | |||
| 345c8a29ad | |||
| a854234c1f | |||
| 4b549eeac8 | |||
| 7c2c8b1403 | |||
| c2ecb4c68c | |||
| ea9dafcd43 | |||
| 7a7b9c682d | |||
| 0d3706e2ee | |||
| 3c584e2cd5 | |||
| 9372972ad4 | |||
| 121cb8b88d | |||
| 93caf4c7b4 | |||
| 21c0e47869 | |||
| f1e853c1cb | |||
| aa7291fc9c | |||
| 3de79bca10 | |||
| 466646f84a | |||
| e0f80e41bf | |||
| 9a5977a9c9 | |||
| c3c6b46230 | |||
| 47b4b0da8a | |||
| 45526205ab | |||
| 3342af4185 | |||
| 7374637d34 | |||
| 62209618e1 | |||
| 7bfa2ee8a7 | |||
| 73c914cca9 | |||
| 77d9d421fb | |||
| 59f3a65911 | |||
| 9181ea068a | |||
| c1d9aad546 | |||
| 3cd8556c54 | |||
| 9c981cfc6b | |||
| 11e3ecc739 | |||
| 5849a0588e | |||
| b8c02f71d9 |
@@ -7,6 +7,7 @@ Makefile.in
|
||||
aclocal.m4
|
||||
autom4te.cache/
|
||||
compile
|
||||
ar-lib
|
||||
confdefs.h
|
||||
conftest
|
||||
conftest.c
|
||||
|
||||
+7
-2
@@ -1,14 +1,19 @@
|
||||
language: c
|
||||
compiler: gcc
|
||||
compiler:
|
||||
- gcc
|
||||
- clang
|
||||
before_script:
|
||||
- sudo apt-get update
|
||||
- sudo apt-get build-dep -qq xchat
|
||||
- sudo apt-get install -qq libnotify-dev libproxy-dev libpci-dev libcanberra-dev monodevelop gnome-common
|
||||
script:
|
||||
- ./autogen.sh
|
||||
- ./configure --enable-textfe --with-theme-manager
|
||||
- make V=1
|
||||
- make V=1 -j$(nproc)
|
||||
notifications:
|
||||
irc:
|
||||
channels: "chat.freenode.net#hexchat-devel"
|
||||
template: "Build #%{build_number} (%{commit}) by %{author}: %{message}"
|
||||
on_success: change
|
||||
matrix:
|
||||
fast_finish: true
|
||||
|
||||
+26
-12
@@ -1,6 +1,6 @@
|
||||
dnl Process this file with autoconf to produce a configure script.
|
||||
|
||||
AC_INIT([HexChat],[2.10.0])
|
||||
AC_INIT([HexChat],[2.11.0])
|
||||
|
||||
AC_PREREQ([2.60])
|
||||
AC_COPYRIGHT([Copyright (C) 1998-2010 Peter Zelezny])
|
||||
@@ -19,6 +19,7 @@ AC_PROG_CC
|
||||
AM_PROG_CC_C_O
|
||||
AC_PROG_CPP
|
||||
AM_PROG_AS
|
||||
AM_PROG_AR
|
||||
AM_DISABLE_STATIC
|
||||
AC_PROG_LIBTOOL
|
||||
AC_PATH_PROG(MDTOOL, mdtool, no)
|
||||
@@ -215,7 +216,7 @@ dnl *********************************************************************
|
||||
|
||||
_gdk_tgt=`$PKG_CONFIG --variable=target gdk-2.0`
|
||||
if test "x$_gdk_tgt" = xquartz; then
|
||||
PKG_CHECK_MODULES(GTK_MAC, gtk-mac-integration, [
|
||||
PKG_CHECK_MODULES(GTK_MAC, gtk-mac-integration-gtk2, [
|
||||
GUI_LIBS="$GUI_LIBS $GTK_MAC_LIBS"
|
||||
GUI_CFLAGS="$GUI_CFLAGS $GTK_MAC_CFLAGS"
|
||||
AC_DEFINE(HAVE_GTK_MAC)
|
||||
@@ -254,8 +255,11 @@ if test "$perl" = yes; then
|
||||
original_ldflags="$LDFLAGS"
|
||||
CFLAGS="$PERL_CFLAGS"
|
||||
LDFLAGS="$PERL_LDFLAGS"
|
||||
AC_TRY_LINK([#include <EXTERN.h>
|
||||
#include <perl.h>], [], perl_is_usable=yes, perl_is_usable=no)
|
||||
AC_TRY_LINK([
|
||||
#define PERL_NO_INLINE_FUNCTIONS
|
||||
#include <EXTERN.h>
|
||||
#include <perl.h>
|
||||
], [], perl_is_usable=yes, perl_is_usable=no)
|
||||
CFLAGS="$original_cflags"
|
||||
LDFLAGS="$original_ldflags"
|
||||
if test x$perl_is_usable = xno ; then
|
||||
@@ -294,19 +298,30 @@ if test "x$python" != xno ; then
|
||||
case $python in
|
||||
dnl set python2 default here
|
||||
python2)
|
||||
PKG_CHECK_MODULES([PY], [python-2.7], [], [AC_MSG_WARN(Cannot find python-2.7!)])
|
||||
PY_VER="`$PKG_CONFIG --modversion python-2.7`";;
|
||||
PKG_CHECK_MODULES([PY], [python-2.7],
|
||||
[PY_VER="`$PKG_CONFIG --modversion python-2.7`"],
|
||||
[true])
|
||||
;;
|
||||
dnl set python3 default here
|
||||
python3)
|
||||
PKG_CHECK_MODULES([PY], [python-3.3], [], [AC_MSG_WARN(Cannot find python-3.3!)])
|
||||
PY_VER="`$PKG_CONFIG --modversion python-3.3`";;
|
||||
PKG_CHECK_MODULES([PY], [python-3.4],
|
||||
[PY_VER="`$PKG_CONFIG --modversion python-3.4`"],
|
||||
[true])
|
||||
if test "$PY_VER" = "" ; then
|
||||
PKG_CHECK_MODULES([PY], [python-3.3],
|
||||
[PY_VER="`$PKG_CONFIG --modversion python-3.3`"],
|
||||
[true])
|
||||
fi
|
||||
;;
|
||||
dnl add broken versions here
|
||||
python2.5|python2.6|python3.1|python3.2)
|
||||
AC_MSG_ERROR(Unsupported Python version ${python}!);;
|
||||
AC_MSG_WARN(Unsupported Python version ${python}!);;
|
||||
python*)
|
||||
python="python-${python#python}" # stay posix compliant
|
||||
PKG_CHECK_MODULES([PY], [${python}], [], [AC_MSG_WARN(Cannot find "${python}.pc"!)])
|
||||
PY_VER="`$PKG_CONFIG --modversion ${python}`";;
|
||||
PKG_CHECK_MODULES([PY], [${python}],
|
||||
[PY_VER="`$PKG_CONFIG --modversion ${python}`"],
|
||||
[AC_MSG_WARN(Cannot find "${python}.pc"!)])
|
||||
;;
|
||||
*)
|
||||
AC_MSG_WARN(Unsupported Python ${python}!)
|
||||
esac
|
||||
@@ -843,7 +858,6 @@ echo D-Bus support ......... : $dbus
|
||||
echo libnotify support ..... : $libnotify
|
||||
echo libcanberra support ... : $libcanberra
|
||||
echo Plugin interface ...... : $plugin
|
||||
echo NLS/gettext ........... : $USE_NLS
|
||||
echo IPv6 support .......... : $ipv6
|
||||
echo MS Proxy NTLM \(ISA\) ... : $have_ntlm
|
||||
echo libproxy support ...... : $libproxy
|
||||
|
||||
+5
-20
@@ -2,7 +2,8 @@
|
||||
<app-bundle>
|
||||
|
||||
<meta>
|
||||
<prefix name="default">${env:JHBUILD_PREFIX}</prefix>
|
||||
<prefix name="default">/usr/local</prefix>
|
||||
<prefix name="enchant">/usr/local/opt/enchant-applespell</prefix>
|
||||
<destination overwrite="yes">${project}</destination>
|
||||
|
||||
<run-install-name-tool/>
|
||||
@@ -21,25 +22,12 @@
|
||||
</binary>
|
||||
|
||||
<binary>
|
||||
${prefix}/lib/libenchant.dylib
|
||||
${prefix:enchant}/lib/libenchant.dylib
|
||||
</binary>
|
||||
<binary>
|
||||
${prefix}/lib/enchant/libenchant_applespell.so
|
||||
${prefix:enchant}/lib/enchant/libenchant_applespell.so
|
||||
</binary>
|
||||
|
||||
<binary dest="${bundle}/Contents/MacOS">
|
||||
${prefix}/bin/python
|
||||
</binary>
|
||||
<binary>
|
||||
${prefix}/lib/libpython2.7.dylib
|
||||
</binary>
|
||||
<data>
|
||||
${prefix}/lib/python2.7/
|
||||
</data>
|
||||
<data>
|
||||
${prefix}/include/python2.7/pyconfig.h
|
||||
</data>
|
||||
|
||||
<binary>
|
||||
${prefix}/lib/${gtkdir}/modules/*.so
|
||||
</binary>
|
||||
@@ -59,7 +47,7 @@
|
||||
${prefix}/lib/pango/${pkg:pango:pango_module_version}/modules/
|
||||
</binary>
|
||||
<data>
|
||||
${prefix}/share/themes/Mac/
|
||||
${prefix}/share/themes/Mac/gtk-2.0-key/gtkrc
|
||||
</data>
|
||||
|
||||
<translations name="gtk20">
|
||||
@@ -77,7 +65,4 @@
|
||||
${project}/hexchat.icns
|
||||
</data>
|
||||
|
||||
<!-- icon-theme icons="none">
|
||||
</icon-theme -->
|
||||
|
||||
</app-bundle>
|
||||
|
||||
@@ -36,10 +36,6 @@ export GDK_PIXBUF_MODULE_FILE="$bundle_etc/gtk-2.0/gdk-pixbuf.loaders"
|
||||
export PANGO_LIBDIR="$bundle_lib"
|
||||
export PANGO_SYSCONFDIR="$bundle_etc"
|
||||
|
||||
export PYTHON="$bundle_contents/MacOS/python"
|
||||
export PYTHONHOME="$bundle_res"
|
||||
export PYTHONPATH="$bundle_lib/python2.7:$bundle_lib/python2.7/site-packages"
|
||||
|
||||
export OPENSSL_CONF="/System/Library/OpenSSL/openssl.cnf"
|
||||
|
||||
export HEXCHAT_LIBDIR="$bundle_lib/hexchat/plugins"
|
||||
|
||||
+1
-16
@@ -1,24 +1,9 @@
|
||||
#!/bin/sh
|
||||
|
||||
if [ -z "$JHBUILD_PREFIX" ]; then
|
||||
echo "You must run this within a jhbuild shell."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f $JHBUILD_PREFIX/bin/python ]; then
|
||||
echo "You must install python with jhbuild."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
rm -rf HexChat.app
|
||||
rm -f *.app.zip
|
||||
|
||||
$JHBUILD_PREFIX/bin/python $HOME/.local/bin/gtk-mac-bundler hexchat.bundle
|
||||
|
||||
# These take up a lot of space in the bundle
|
||||
echo "Cleaning up python files"
|
||||
find ./HexChat.app/Contents/Resources/lib/python2.7 -name "*.pyc" -delete
|
||||
find ./HexChat.app/Contents/Resources/lib/python2.7 -name "*.pyo" -delete
|
||||
python $HOME/.local/bin/gtk-mac-bundler hexchat.bundle
|
||||
|
||||
echo "Compressing bundle"
|
||||
#hdiutil create -format UDBZ -srcdir HexChat.app -quiet HexChat-2.9.6.1-$(git rev-parse --short master).dmg
|
||||
|
||||
@@ -221,7 +221,7 @@ static int handle_setkey(char *word[], char *word_eol[], void *userdata) {
|
||||
if (keystore_store_key(nick, key)) {
|
||||
hexchat_printf(ph, "Stored key for %s\n", nick);
|
||||
} else {
|
||||
hexchat_printf(ph, "\00305Failed to store key in addon_fishlim.conf\n", nick, key);
|
||||
hexchat_printf(ph, "\00305Failed to store key in addon_fishlim.conf\n");
|
||||
}
|
||||
|
||||
return HEXCHAT_EAT_HEXCHAT;
|
||||
@@ -245,7 +245,7 @@ static int handle_delkey(char *word[], char *word_eol[], void *userdata) {
|
||||
if (keystore_delete_nick(nick)) {
|
||||
hexchat_printf(ph, "Deleted key for %s\n", nick);
|
||||
} else {
|
||||
hexchat_printf(ph, "\00305Failed to delete key in addon_fishlim.conf!\n", nick);
|
||||
hexchat_printf(ph, "\00305Failed to delete key in addon_fishlim.conf!\n");
|
||||
}
|
||||
|
||||
return HEXCHAT_EAT_HEXCHAT;
|
||||
|
||||
@@ -15,4 +15,4 @@ CLEANFILES = hexchat.pm.h irc.pm.h
|
||||
hexchat.pm.h irc.pm.h: lib/HexChat.pm lib/Xchat.pm lib/HexChat/Embed.pm \
|
||||
lib/HexChat/List/Network.pm lib/HexChat/List/Network/Entry.pm \
|
||||
lib/HexChat/List/Network/AutoJoin.pm lib/IRC.pm
|
||||
perl generate_header
|
||||
cd $(srcdir); perl generate_header
|
||||
|
||||
+1
-4
@@ -32,11 +32,8 @@
|
||||
#endif
|
||||
|
||||
#undef PACKAGE
|
||||
#ifdef WIN32
|
||||
#include "../../config-win32.h" /* for #define OLD_PERL */
|
||||
#else
|
||||
#include "../../config.h"
|
||||
#endif
|
||||
|
||||
#include "hexchat-plugin.h"
|
||||
|
||||
static hexchat_plugin *ph; /* plugin handle */
|
||||
|
||||
+30
-24
@@ -52,20 +52,19 @@
|
||||
*/
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib/gstdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef WIN32
|
||||
#include <direct.h>
|
||||
#include <glib/gstdio.h>
|
||||
#include "../../src/dirent/dirent-win32.h"
|
||||
#include "../../config-win32.h"
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
#endif
|
||||
|
||||
#include "../../config.h"
|
||||
#include "hexchat-plugin.h"
|
||||
#undef _POSIX_C_SOURCE /* Avoid warning: also in /usr/include/features.h from glib.h */
|
||||
#include <Python.h>
|
||||
@@ -415,6 +414,9 @@ Util_BuildEOLList(char *word[])
|
||||
PyObject *list;
|
||||
int listsize = 31;
|
||||
int i;
|
||||
char *accum = NULL;
|
||||
char *last = NULL;
|
||||
|
||||
/* Find the last valid array member; there may be intermediate NULLs that
|
||||
* would otherwise cause us to drop some members. */
|
||||
while (listsize > 0 &&
|
||||
@@ -425,10 +427,9 @@ Util_BuildEOLList(char *word[])
|
||||
PyErr_Print();
|
||||
return NULL;
|
||||
}
|
||||
char *accum = NULL;
|
||||
char *last = NULL;
|
||||
for (i = listsize; i > 0; i--) {
|
||||
char *part = word[i];
|
||||
PyObject *uni_part;
|
||||
if (accum == NULL) {
|
||||
accum = g_strdup (part);
|
||||
} else if (part != NULL && part[0] != 0) {
|
||||
@@ -444,7 +445,7 @@ Util_BuildEOLList(char *word[])
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
PyObject *uni_part = PyUnicode_FromString(accum);
|
||||
uni_part = PyUnicode_FromString(accum);
|
||||
PyList_SetItem(list, i - 1, uni_part);
|
||||
}
|
||||
|
||||
@@ -459,26 +460,31 @@ Util_BuildEOLList(char *word[])
|
||||
static void
|
||||
Util_Autoload_from (const char *dir_name)
|
||||
{
|
||||
#ifndef PATH_MAX
|
||||
#define PATH_MAX 1024 /* Hurd doesn't define it */
|
||||
#endif
|
||||
char oldcwd[PATH_MAX];
|
||||
struct dirent *ent;
|
||||
DIR *dir;
|
||||
if (getcwd(oldcwd, PATH_MAX) == NULL)
|
||||
gchar *oldcwd;
|
||||
const char *entry_name;
|
||||
GDir *dir;
|
||||
|
||||
oldcwd = g_get_current_dir ();
|
||||
if (oldcwd == NULL)
|
||||
return;
|
||||
if (chdir(dir_name) != 0)
|
||||
if (g_chdir(dir_name) != 0)
|
||||
{
|
||||
g_free (oldcwd);
|
||||
return;
|
||||
dir = opendir(".");
|
||||
if (dir == NULL)
|
||||
return;
|
||||
while ((ent = readdir(dir))) {
|
||||
int len = strlen(ent->d_name);
|
||||
if (len > 3 && strcmp(".py", ent->d_name+len-3) == 0)
|
||||
Command_PyLoad(ent->d_name);
|
||||
}
|
||||
closedir(dir);
|
||||
chdir(oldcwd);
|
||||
dir = g_dir_open (".", 0, NULL);
|
||||
if (dir == NULL)
|
||||
{
|
||||
g_free (oldcwd);
|
||||
return;
|
||||
}
|
||||
while ((entry_name = g_dir_read_name (dir)))
|
||||
{
|
||||
if (g_str_has_suffix (entry_name, ".py"))
|
||||
Command_PyLoad((char*)entry_name);
|
||||
}
|
||||
g_dir_close (dir);
|
||||
g_chdir (oldcwd);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -486,7 +492,7 @@ Util_Autoload()
|
||||
{
|
||||
const char *xdir;
|
||||
char *sub_dir;
|
||||
/* we need local filesystem encoding for chdir, opendir etc */
|
||||
/* we need local filesystem encoding for g_chdir, g_dir_open etc */
|
||||
|
||||
xdir = hexchat_get_info(ph, "configdir");
|
||||
|
||||
|
||||
@@ -53,8 +53,9 @@ void get_hwmon_chip_name(char *name)
|
||||
void get_hwmon_temp(unsigned int *value, unsigned int *sensor)
|
||||
{
|
||||
char buffer[bsize];
|
||||
FILE *fp;
|
||||
snprintf(buffer, bsize, "/sys/class/hwmon/hwmon0/device/temp%i_input", *sensor);
|
||||
FILE *fp = fopen(buffer, "r");
|
||||
fp = fopen(buffer, "r");
|
||||
if(fp != NULL) {
|
||||
if(fgets(buffer, bsize, fp) != NULL)
|
||||
*value = atoi(buffer);
|
||||
|
||||
@@ -32,12 +32,12 @@ float percentage(unsigned long long *free, unsigned long long *total)
|
||||
|
||||
char *pretty_freespace(const char *desc, unsigned long long *free_k, unsigned long long *total_k)
|
||||
{
|
||||
char *result, **quantity;
|
||||
char *quantities[] = { "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB", 0 };
|
||||
char *result, **quantity;
|
||||
double free_space, total_space;
|
||||
free_space = *free_k;
|
||||
total_space = *total_k;
|
||||
result = malloc(bsize * sizeof(char));
|
||||
char *quantities[] = { "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB", 0 };
|
||||
if (total_space == 0)
|
||||
{
|
||||
snprintf(result, bsize, "%s: none", desc);
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "match.h"
|
||||
#include "hwmon.h"
|
||||
#include "xsys.h"
|
||||
#include "parse.h"
|
||||
|
||||
int xs_parse_cpu(char *model, char *vendor, double *freq, char *cache, unsigned int *count)
|
||||
{
|
||||
|
||||
@@ -115,9 +115,10 @@ void pci_find_fullname(char *fullname, char *vendor, char *device)
|
||||
char devicename[bsize/2] = "";
|
||||
char *position;
|
||||
int cardfound = 0;
|
||||
FILE *fp;
|
||||
|
||||
sysinfo_get_pciids (buffer);
|
||||
FILE *fp = fopen (buffer, "r");
|
||||
fp = fopen (buffer, "r");
|
||||
|
||||
if(fp == NULL) {
|
||||
snprintf(fullname, bsize, "%s:%s", vendor, device);
|
||||
|
||||
@@ -750,7 +750,7 @@ sysinfo_cb (char *word[], char *word_eol[], void *userdata)
|
||||
|
||||
if (!g_ascii_strcasecmp ("HELP", word[2+offset]))
|
||||
{
|
||||
hexchat_printf (ph, sysinfo_help);
|
||||
hexchat_printf (ph, "%s", sysinfo_help);
|
||||
return HEXCHAT_EAT_ALL;
|
||||
}
|
||||
else if (!g_ascii_strcasecmp ("LIST", word[2+offset]))
|
||||
@@ -870,7 +870,7 @@ sysinfo_cb (char *word[], char *word_eol[], void *userdata)
|
||||
}
|
||||
else
|
||||
{
|
||||
hexchat_printf (ph, sysinfo_help);
|
||||
hexchat_printf (ph, "%s", sysinfo_help);
|
||||
return HEXCHAT_EAT_ALL;
|
||||
}
|
||||
}
|
||||
@@ -878,11 +878,11 @@ sysinfo_cb (char *word[], char *word_eol[], void *userdata)
|
||||
int
|
||||
hexchat_plugin_init (hexchat_plugin *plugin_handle, char **plugin_name, char **plugin_desc, char **plugin_version, char *arg)
|
||||
{
|
||||
char buffer[bsize];
|
||||
ph = plugin_handle;
|
||||
*plugin_name = name;
|
||||
*plugin_desc = desc;
|
||||
*plugin_version = version;
|
||||
char buffer[bsize];
|
||||
|
||||
hexchat_hook_command (ph, "SYSINFO", HEXCHAT_PRI_NORM, sysinfo_cb, sysinfo_help, NULL);
|
||||
hexchat_hook_command (ph, "NETDATA", HEXCHAT_PRI_NORM, netdata_cb, NULL, NULL);
|
||||
|
||||
+2
-2
@@ -128,7 +128,7 @@ print_version (char *word[], char *word_eol[], void *userdata)
|
||||
|
||||
if (!g_ascii_strcasecmp ("HELP", word[2]))
|
||||
{
|
||||
hexchat_printf (ph, upd_help);
|
||||
hexchat_printf (ph, "%s", upd_help);
|
||||
return HEXCHAT_EAT_HEXCHAT;
|
||||
}
|
||||
else if (!g_ascii_strcasecmp ("SET", word[2]))
|
||||
@@ -200,7 +200,7 @@ print_version (char *word[], char *word_eol[], void *userdata)
|
||||
}
|
||||
else
|
||||
{
|
||||
hexchat_printf (ph, upd_help);
|
||||
hexchat_printf (ph, "%s", upd_help);
|
||||
return HEXCHAT_EAT_HEXCHAT;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ src/common/inbound.c
|
||||
src/common/notify.c
|
||||
src/common/outbound.c
|
||||
src/common/plugin.c
|
||||
src/common/plugin-timer.c
|
||||
src/common/server.c
|
||||
src/common/servlist.c
|
||||
src/common/textevents.h
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# HexChat [](https://travis-ci.org/hexchat/hexchat) [](http://nekomimi.cloudapp.net:8080/job/hexchat/) [](https://bitdeli.com/free "Bitdeli Badge")
|
||||
# HexChat [](https://travis-ci.org/hexchat/hexchat) [](http://nekomimi.cloudapp.net:8080/job/hexchat/)
|
||||
|
||||
HexChat is an IRC client for Windows and UNIX-like operating systems.
|
||||
See [IRCHelp.org](http://irchelp.org) for information about IRC in general.
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
noinst_LIBRARIES = libhexchatcommon.a
|
||||
|
||||
AM_CPPFLAGS = $(COMMON_CFLAGS)
|
||||
AM_CPPFLAGS = $(COMMON_CFLAGS) -I$(top_srcdir)
|
||||
|
||||
EXTRA_DIST = \
|
||||
cfgfiles.h \
|
||||
@@ -69,14 +69,14 @@ libhexchatcommon_a_CFLAGS = $(LIBPROXY_CFLAGS)
|
||||
|
||||
textenums.h: textevents.h
|
||||
|
||||
textevents.h: textevents.in make-te
|
||||
$(AM_V_GEN) ./make-te < textevents.in > textevents.h 2> textenums.h
|
||||
textevents.h: $(srcdir)/textevents.in make-te
|
||||
$(AM_V_GEN) ./make-te < $< > $@ 2> textenums.h
|
||||
|
||||
marshal.h: marshalers.list
|
||||
$(AM_V_GEN) $(GLIB_GENMARSHAL) --prefix=_hexchat_marshal --header $(srcdir)/marshalers.list > $@
|
||||
marshal.h: $(srcdir)/marshalers.list
|
||||
$(AM_V_GEN) $(GLIB_GENMARSHAL) --prefix=_hexchat_marshal --header $< > $@
|
||||
|
||||
marshal.c: marshalers.list
|
||||
$(AM_V_GEN) $(GLIB_GENMARSHAL) --prefix=_hexchat_marshal --body $(srcdir)/marshalers.list > $@
|
||||
marshal.c: $(srcdir)/marshalers.list
|
||||
$(AM_V_GEN) $(GLIB_GENMARSHAL) --prefix=_hexchat_marshal --body $< > $@
|
||||
|
||||
|
||||
BUILT_SOURCES = textenums.h textevents.h marshal.c marshal.h
|
||||
|
||||
+5
-11
@@ -57,10 +57,6 @@ list_addentry (GSList ** list, char *cmd, char *name)
|
||||
size_t name_len;
|
||||
size_t cmd_len = 1;
|
||||
|
||||
/* remove <2.8.0 stuff */
|
||||
if (!strcmp (cmd, "away") && !strcmp (name, "BACK"))
|
||||
return;
|
||||
|
||||
if (cmd)
|
||||
cmd_len = strlen (cmd) + 1;
|
||||
name_len = strlen (name) + 1;
|
||||
@@ -313,13 +309,10 @@ get_xdir (void)
|
||||
if (portable_mode () || SHGetKnownFolderPath (&FOLDERID_RoamingAppData, 0, NULL, &roaming_path_wide) != S_OK)
|
||||
{
|
||||
char *path;
|
||||
char file[MAX_PATH];
|
||||
HMODULE hModule;
|
||||
|
||||
hModule = GetModuleHandle (NULL);
|
||||
if (GetModuleFileName (hModule, file, sizeof(file)))
|
||||
|
||||
path = g_win32_get_package_installation_directory_of_module (NULL);
|
||||
if (path)
|
||||
{
|
||||
path = g_path_get_dirname (file);
|
||||
xdir = g_build_filename (path, "config", NULL);
|
||||
g_free (path);
|
||||
}
|
||||
@@ -785,6 +778,7 @@ load_default_config(void)
|
||||
prefs.hex_input_tray_hilight = 1;
|
||||
prefs.hex_input_tray_priv = 1;
|
||||
prefs.hex_irc_cap_server_time = 1;
|
||||
prefs.hex_irc_logging = 1;
|
||||
prefs.hex_irc_who_join = 1; /* Can kick with inordinate amount of channels, required for some of our features though, TODO: add cap like away check? */
|
||||
prefs.hex_irc_whois_front = 1;
|
||||
prefs.hex_net_auto_reconnect = 1;
|
||||
@@ -1317,7 +1311,7 @@ cmd_set (struct session *sess, char *tbuf, char *word[], char *word_eol[])
|
||||
}
|
||||
|
||||
int
|
||||
hexchat_open_file (char *file, int flags, int mode, int xof_flags)
|
||||
hexchat_open_file (const char *file, int flags, int mode, int xof_flags)
|
||||
{
|
||||
char *buf;
|
||||
int fd;
|
||||
|
||||
@@ -48,7 +48,7 @@ void list_loadconf (char *file, GSList ** list, char *defaultconf);
|
||||
int list_delentry (GSList ** list, char *name);
|
||||
void list_addentry (GSList ** list, char *cmd, char *name);
|
||||
int cmd_set (session *sess, char *tbuf, char *word[], char *word_eol[]);
|
||||
int hexchat_open_file (char *file, int flags, int mode, int xof_flags);
|
||||
int hexchat_open_file (const char *file, int flags, int mode, int xof_flags);
|
||||
FILE *hexchat_fopen_file (const char *file, const char *mode, int xof_flags);
|
||||
|
||||
#define XOF_DOMODE 1
|
||||
|
||||
@@ -77,8 +77,8 @@
|
||||
<ClCompile Include="hexchat.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\..\config-win32.h.tt" />
|
||||
<ClInclude Include="..\..\config-win32.h" />
|
||||
<None Include="..\..\win32\config.h.tt" />
|
||||
<ClInclude Include="..\..\config.h" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{87554B59-006C-4D94-9714-897B27067BA3}</ProjectGuid>
|
||||
@@ -125,7 +125,7 @@
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;$(OwnFlags);%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>$(DepsRoot)\include;$(Glib);$(Gtk);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)..;$(DepsRoot)\include;$(Glib);$(Gtk);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
@@ -142,7 +142,7 @@
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;_WIN64;_AMD64_;NDEBUG;_LIB;$(OwnFlags);%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>$(DepsRoot)\include;$(Glib);$(Gtk);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)..;$(DepsRoot)\include;$(Glib);$(Gtk);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<DisableSpecificWarnings>4267;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||
</ClCompile>
|
||||
@@ -160,7 +160,7 @@
|
||||
<PreBuildEvent>
|
||||
<Command><![CDATA[
|
||||
SET SOLUTIONDIR=$(SolutionDir)..\
|
||||
powershell -File "$(SolutionDir)..\version-template.ps1" "$(SolutionDir)..\config-win32.h.tt" "$(SolutionDir)..\config-win32.h"
|
||||
powershell -File "$(SolutionDir)..\win32\version-template.ps1" "$(SolutionDir)..\win32\config.h.tt" "$(SolutionDir)..\config.h"
|
||||
"$(DepsRoot)\bin\glib-genmarshal.exe" --prefix=_hexchat_marshal --header "$(ProjectDir)marshalers.list" > "$(ProjectDir)marshal.h"
|
||||
"$(DepsRoot)\bin\glib-genmarshal.exe" --prefix=_hexchat_marshal --body "$(ProjectDir)marshalers.list" > "$(ProjectDir)marshal.c"
|
||||
|
||||
|
||||
@@ -104,7 +104,7 @@
|
||||
<ClInclude Include="hexchat-plugin.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\config-win32.h">
|
||||
<ClInclude Include="..\..\config.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="typedef.h">
|
||||
@@ -195,6 +195,6 @@
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\..\config-win32.h.tt" />
|
||||
<None Include="..\..\win32\config.h.tt" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -15,7 +15,7 @@ BUILT_SOURCES = \
|
||||
|
||||
CLEANFILES = $(BUILT_SOURCES)
|
||||
|
||||
AM_CPPFLAGS = $(COMMON_CFLAGS) $(DBUS_CFLAGS)
|
||||
AM_CPPFLAGS = $(COMMON_CFLAGS) $(DBUS_CFLAGS) -I$(top_srcdir)/src/common
|
||||
|
||||
noinst_PROGRAMS = example
|
||||
example_SOURCES = example.c
|
||||
|
||||
@@ -22,8 +22,8 @@
|
||||
#define GLIB_DISABLE_DEPRECATION_WARNINGS
|
||||
#include <dbus/dbus-glib.h>
|
||||
#include "dbus-client.h"
|
||||
#include "../hexchat.h"
|
||||
#include "../hexchatc.h"
|
||||
#include "hexchat.h"
|
||||
#include "hexchatc.h"
|
||||
|
||||
#define DBUS_SERVICE "org.hexchat.service"
|
||||
#define DBUS_REMOTE "/org/hexchat/Remote"
|
||||
|
||||
@@ -25,7 +25,8 @@
|
||||
#include <dbus/dbus-glib.h>
|
||||
#include <dbus/dbus-glib-lowlevel.h>
|
||||
#include <glib/gi18n.h>
|
||||
#include "../hexchat-plugin.h"
|
||||
#include "hexchat-plugin.h"
|
||||
#include "dbus-plugin.h"
|
||||
|
||||
#define PNAME _("remote access")
|
||||
#define PDESC _("plugin for remote access using DBUS")
|
||||
|
||||
@@ -33,7 +33,7 @@ guint command_id;
|
||||
guint server_id;
|
||||
|
||||
static void
|
||||
write_error (char *message,
|
||||
write_error (const char *message,
|
||||
GError **error)
|
||||
{
|
||||
if (error == NULL || *error == NULL) {
|
||||
|
||||
@@ -103,6 +103,7 @@ void fe_dcc_remove (struct DCC *dcc);
|
||||
int fe_dcc_open_recv_win (int passive);
|
||||
int fe_dcc_open_send_win (int passive);
|
||||
int fe_dcc_open_chat_win (int passive);
|
||||
void fe_sslalert_open (struct server *serv, void (*callback)(int, void *), void *callback_data);
|
||||
void fe_clear_channel (struct session *sess);
|
||||
void fe_session_callback (struct session *sess);
|
||||
void fe_server_callback (struct server *serv);
|
||||
|
||||
@@ -88,11 +88,19 @@ struct _hexchat_plugin
|
||||
void (*hexchat_print) (hexchat_plugin *ph,
|
||||
const char *text);
|
||||
void (*hexchat_printf) (hexchat_plugin *ph,
|
||||
const char *format, ...);
|
||||
const char *format, ...)
|
||||
#ifdef __GNUC__
|
||||
__attribute__((format(printf, 2, 3)))
|
||||
#endif
|
||||
;
|
||||
void (*hexchat_command) (hexchat_plugin *ph,
|
||||
const char *command);
|
||||
void (*hexchat_commandf) (hexchat_plugin *ph,
|
||||
const char *format, ...);
|
||||
const char *format, ...)
|
||||
#ifdef __GNUC__
|
||||
__attribute__((format(printf, 2, 3)))
|
||||
#endif
|
||||
;
|
||||
int (*hexchat_nickcmp) (hexchat_plugin *ph,
|
||||
const char *s1,
|
||||
const char *s2);
|
||||
@@ -254,7 +262,11 @@ hexchat_print (hexchat_plugin *ph,
|
||||
|
||||
void
|
||||
hexchat_printf (hexchat_plugin *ph,
|
||||
const char *format, ...);
|
||||
const char *format, ...)
|
||||
#ifdef __GNUC__
|
||||
__attribute__((format(printf, 2, 3)))
|
||||
#endif
|
||||
;
|
||||
|
||||
void
|
||||
hexchat_command (hexchat_plugin *ph,
|
||||
@@ -262,7 +274,11 @@ hexchat_command (hexchat_plugin *ph,
|
||||
|
||||
void
|
||||
hexchat_commandf (hexchat_plugin *ph,
|
||||
const char *format, ...);
|
||||
const char *format, ...)
|
||||
#ifdef __GNUC__
|
||||
__attribute__((format(printf, 2, 3)))
|
||||
#endif
|
||||
;
|
||||
|
||||
int
|
||||
hexchat_nickcmp (hexchat_plugin *ph,
|
||||
|
||||
+1
-53
@@ -55,11 +55,6 @@
|
||||
#include <glib-object.h> /* for g_type_init() */
|
||||
#endif
|
||||
|
||||
#ifdef USE_OPENSSL
|
||||
#include <openssl/ssl.h> /* SSL_() */
|
||||
#include "ssl.h"
|
||||
#endif
|
||||
|
||||
#ifdef USE_MSPROXY
|
||||
#include "msproxy.h"
|
||||
#endif
|
||||
@@ -118,10 +113,6 @@ struct session *current_tab;
|
||||
struct session *current_sess = 0;
|
||||
struct hexchatprefs prefs;
|
||||
|
||||
#ifdef USE_OPENSSL
|
||||
SSL_CTX *ctx = NULL;
|
||||
#endif
|
||||
|
||||
#ifdef USE_LIBPROXY
|
||||
pxProxyFactory *libproxy_factory;
|
||||
#endif
|
||||
@@ -942,6 +933,7 @@ xchat_init (void)
|
||||
defaultconf_urlhandlers);
|
||||
|
||||
servlist_init (); /* load server list */
|
||||
_SSL_certlist_init (); /* load known certificate fingerprints */
|
||||
|
||||
/* if we got a URL, don't open the server list GUI */
|
||||
if (!prefs.hex_gui_slist_skip && !arg_url && !arg_urls)
|
||||
@@ -991,47 +983,12 @@ hexchat_exit (void)
|
||||
fe_exit ();
|
||||
}
|
||||
|
||||
#ifndef WIN32
|
||||
|
||||
static int
|
||||
child_handler (gpointer userdata)
|
||||
{
|
||||
int pid = GPOINTER_TO_INT (userdata);
|
||||
|
||||
if (waitpid (pid, 0, WNOHANG) == pid)
|
||||
return 0; /* remove timeout handler */
|
||||
return 1; /* keep the timeout handler */
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void
|
||||
hexchat_exec (const char *cmd)
|
||||
{
|
||||
#ifdef WIN32
|
||||
util_exec (cmd);
|
||||
#else
|
||||
int pid = util_exec (cmd);
|
||||
if (pid != -1)
|
||||
/* zombie avoiding system. Don't ask! it has to be like this to work
|
||||
with zvt (which overrides the default handler) */
|
||||
fe_timeout_add (1000, child_handler, GINT_TO_POINTER (pid));
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
hexchat_execv (char * const argv[])
|
||||
{
|
||||
#ifdef WIN32
|
||||
util_execv (argv);
|
||||
#else
|
||||
int pid = util_execv (argv);
|
||||
if (pid != -1)
|
||||
/* zombie avoiding system. Don't ask! it has to be like this to work
|
||||
with zvt (which overrides the default handler) */
|
||||
fe_timeout_add (1000, child_handler, GINT_TO_POINTER (pid));
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
set_locale (void)
|
||||
@@ -1149,15 +1106,6 @@ main (int argc, char *argv[])
|
||||
px_proxy_factory_free(libproxy_factory);
|
||||
#endif
|
||||
|
||||
#ifdef USE_OPENSSL
|
||||
if (ctx)
|
||||
_SSL_context_free (ctx);
|
||||
#endif
|
||||
|
||||
#ifdef USE_DEBUG
|
||||
hexchat_mem_list ();
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
WSACleanup ();
|
||||
#endif
|
||||
|
||||
+5
-32
@@ -17,14 +17,11 @@
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifdef WIN32
|
||||
#include "../../config-win32.h"
|
||||
#else
|
||||
#include "../../config.h"
|
||||
#endif
|
||||
#include "config.h"
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib/gstdio.h>
|
||||
#include <glib/gi18n.h>
|
||||
|
||||
#include <time.h> /* need time_t */
|
||||
|
||||
@@ -48,17 +45,6 @@
|
||||
#define vsnprintf _vsnprintf
|
||||
#endif
|
||||
|
||||
#ifdef USE_DEBUG
|
||||
#define malloc(n) hexchat_malloc(n, __FILE__, __LINE__)
|
||||
#define realloc(n, m) hexchat_realloc(n, m, __FILE__, __LINE__)
|
||||
#define free(n) hexchat_dfree(n, __FILE__, __LINE__)
|
||||
#define strdup(n) hexchat_strdup(n, __FILE__, __LINE__)
|
||||
void *hexchat_malloc (int size, char *file, int line);
|
||||
void *hexchat_strdup (char *str, char *file, int line);
|
||||
void hexchat_dfree (void *buf, char *file, int line);
|
||||
void *hexchat_realloc (char *old, int len, char *file, int line);
|
||||
#endif
|
||||
|
||||
#ifdef SOCKS
|
||||
#ifdef __sgi
|
||||
#include <sys/time.h>
|
||||
@@ -69,6 +55,7 @@ void *hexchat_realloc (char *old, int len, char *file, int line);
|
||||
|
||||
#ifdef USE_OPENSSL
|
||||
#include <openssl/ssl.h> /* SSL_() */
|
||||
#include "ssl.h"
|
||||
#endif
|
||||
|
||||
#ifdef __EMX__ /* for o/s 2 */
|
||||
@@ -80,9 +67,7 @@ void *hexchat_realloc (char *old, int len, char *file, int line);
|
||||
#endif
|
||||
|
||||
/* force a 32bit CMP.L */
|
||||
#define CMPL(a, c0, c1, c2, c3) (a == (guint32)(c0 | (c1 << 8) | (c2 << 16) | (c3 << 24)))
|
||||
#define WORDL(c0, c1, c2, c3) (guint32)(c0 | (c1 << 8) | (c2 << 16) | (c3 << 24))
|
||||
#define WORDW(c0, c1) (guint16)(c0 | (c1 << 8))
|
||||
|
||||
#ifdef WIN32 /* for win32 */
|
||||
#define OFLAGS O_BINARY
|
||||
@@ -109,20 +94,6 @@ void *hexchat_realloc (char *old, int len, char *file, int line);
|
||||
#define USERNAMELEN 10
|
||||
#define HIDDEN_CHAR 8 /* invisible character for xtext */
|
||||
|
||||
#if defined(ENABLE_NLS) && !defined(_)
|
||||
# include <libintl.h>
|
||||
# define _(x) gettext(x)
|
||||
# ifdef gettext_noop
|
||||
# define N_(String) gettext_noop (String)
|
||||
# else
|
||||
# define N_(String) (String)
|
||||
# endif
|
||||
#endif
|
||||
#if !defined(_)
|
||||
# define N_(String) (String)
|
||||
# define _(x) (x)
|
||||
#endif
|
||||
|
||||
struct nbexec
|
||||
{
|
||||
int myfd;
|
||||
@@ -532,6 +503,7 @@ typedef struct server
|
||||
struct msproxy_state_t msp_state;
|
||||
int id; /* unique ID number (for plugin API) */
|
||||
#ifdef USE_OPENSSL
|
||||
SSL_CTX *ctx;
|
||||
SSL *ssl;
|
||||
int ssl_do_connect_tag;
|
||||
#else
|
||||
@@ -626,6 +598,7 @@ typedef struct server
|
||||
#ifdef USE_OPENSSL
|
||||
unsigned int use_ssl:1; /* is server SSL capable? */
|
||||
unsigned int accept_invalid_cert:1;/* ignore result of server's cert. verify */
|
||||
struct cert_info *cert_info;
|
||||
#endif
|
||||
} server;
|
||||
|
||||
|
||||
@@ -57,6 +57,5 @@ void session_free (session *killsess);
|
||||
void lag_check (void);
|
||||
void hexchat_exit (void);
|
||||
void hexchat_exec (const char *cmd);
|
||||
void hexchat_execv (char * const argv[]);
|
||||
|
||||
#endif
|
||||
|
||||
+1
-1
@@ -47,7 +47,7 @@
|
||||
|
||||
#else
|
||||
|
||||
#include "../../config-win32.h"
|
||||
#include "../../config.h"
|
||||
#ifdef USE_IPV6
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int main()
|
||||
int main(void)
|
||||
{
|
||||
char name[512];
|
||||
char num[512];
|
||||
|
||||
@@ -23,12 +23,10 @@
|
||||
#include <stdio.h>
|
||||
#include <glib.h>
|
||||
|
||||
#ifdef WIN32
|
||||
#include "../../config-win32.h" /* grab USE_IPV6 and LOOKUPD defines */
|
||||
#else
|
||||
#ifndef WIN32
|
||||
#include <unistd.h>
|
||||
#include "../../config.h"
|
||||
#endif
|
||||
#include "../../config.h"
|
||||
|
||||
#define WANTSOCKET
|
||||
#define WANTARPA
|
||||
|
||||
+37
-31
@@ -293,26 +293,20 @@ notify_set_offline_list (server * serv, char *users, int quiet,
|
||||
struct notify_per_server *servnot;
|
||||
char nick[NICKLEN];
|
||||
char *token, *chr;
|
||||
int pos;
|
||||
|
||||
token = strtok (users, ",");
|
||||
while (token != NULL)
|
||||
{
|
||||
chr = strchr (token, '!');
|
||||
if (!chr)
|
||||
goto end;
|
||||
if (chr != NULL)
|
||||
*chr = '\0';
|
||||
|
||||
pos = chr - token;
|
||||
if (pos + 1 >= sizeof(nick))
|
||||
goto end;
|
||||
|
||||
memset (nick, 0, sizeof(nick));
|
||||
strncpy (nick, token, pos);
|
||||
g_strlcpy (nick, token, sizeof(nick));
|
||||
|
||||
servnot = notify_find (serv, nick);
|
||||
if (servnot)
|
||||
notify_announce_offline (serv, servnot, nick, quiet, tags_data);
|
||||
end:
|
||||
|
||||
token = strtok (NULL, ",");
|
||||
}
|
||||
}
|
||||
@@ -324,26 +318,20 @@ notify_set_online_list (server * serv, char *users,
|
||||
struct notify_per_server *servnot;
|
||||
char nick[NICKLEN];
|
||||
char *token, *chr;
|
||||
int pos;
|
||||
|
||||
token = strtok (users, ",");
|
||||
while (token != NULL)
|
||||
{
|
||||
chr = strchr (token, '!');
|
||||
if (!chr)
|
||||
goto end;
|
||||
if (chr != NULL)
|
||||
*chr = '\0';
|
||||
|
||||
pos = chr - token;
|
||||
if (pos + 1 >= sizeof(nick))
|
||||
goto end;
|
||||
|
||||
memset (nick, 0, sizeof(nick));
|
||||
strncpy (nick, token, pos);
|
||||
g_strlcpy (nick, token, sizeof(nick));
|
||||
|
||||
servnot = notify_find (serv, nick);
|
||||
if (servnot)
|
||||
notify_announce_online (serv, servnot, nick, tags_data);
|
||||
end:
|
||||
|
||||
token = strtok (NULL, ",");
|
||||
}
|
||||
}
|
||||
@@ -410,32 +398,50 @@ void
|
||||
notify_send_watches (server * serv)
|
||||
{
|
||||
struct notify *notify;
|
||||
const int format_len = serv->supports_monitor ? 1 : 2; /* just , for monitor or + and space for watch */
|
||||
GSList *list;
|
||||
GSList *point;
|
||||
int len;
|
||||
GSList *send_list = NULL;
|
||||
int len = 0;
|
||||
|
||||
len = 0;
|
||||
point = list = notify_list;
|
||||
/* Only get the list for this network */
|
||||
list = notify_list;
|
||||
while (list)
|
||||
{
|
||||
notify = list->data;
|
||||
|
||||
if (notify_do_network (notify, serv))
|
||||
{
|
||||
len += strlen (notify->name) + serv->supports_monitor ? 1 : 2; /* just , for monitor or + and space for watch */;
|
||||
if (len > 500)
|
||||
{
|
||||
notify_flush_watches (serv, point, list);
|
||||
len = strlen (notify->name) + serv->supports_monitor ? 1 : 2;
|
||||
point = list;
|
||||
}
|
||||
send_list = g_slist_append (send_list, notify);
|
||||
}
|
||||
|
||||
list = list->next;
|
||||
}
|
||||
|
||||
if (point)
|
||||
/* Now send that list in batches */
|
||||
point = list = send_list;
|
||||
while (list)
|
||||
{
|
||||
notify = list->data;
|
||||
|
||||
len += strlen (notify->name) + format_len;
|
||||
if (len > 500)
|
||||
{
|
||||
/* Too long send existing list */
|
||||
notify_flush_watches (serv, point, list);
|
||||
len = strlen (notify->name) + format_len;
|
||||
point = list; /* We left off here */
|
||||
}
|
||||
|
||||
list = g_slist_next (list);
|
||||
}
|
||||
|
||||
if (len) /* We had leftovers under 500, send them all */
|
||||
{
|
||||
notify_flush_watches (serv, point, NULL);
|
||||
}
|
||||
|
||||
g_slist_free (send_list);
|
||||
}
|
||||
|
||||
/* called when receiving a ISON 303 - should this func go? */
|
||||
|
||||
+10
-43
@@ -56,9 +56,6 @@
|
||||
#include "outbound.h"
|
||||
#include "chanopt.h"
|
||||
|
||||
#ifdef USE_DEBUG
|
||||
extern int current_mem_usage;
|
||||
#endif
|
||||
#define TBUFSIZE 4096
|
||||
|
||||
static void help (session *sess, char *tbuf, char *helpcmd, int quiet);
|
||||
@@ -922,10 +919,6 @@ cmd_debug (struct session *sess, char *tbuf, char *word[], char *word_eol[])
|
||||
"current_tab: %p\n\n",
|
||||
sess->server->front_session, current_tab);
|
||||
PrintText (sess, tbuf);
|
||||
#ifdef USE_DEBUG
|
||||
sprintf (tbuf, "current mem: %d\n\n", current_mem_usage);
|
||||
PrintText (sess, tbuf);
|
||||
#endif /* !MEMORY_DEBUG */
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -1841,8 +1834,10 @@ cmd_exec (struct session *sess, char *tbuf, char *word[], char *word_eol[])
|
||||
char **argv;
|
||||
int argc;
|
||||
|
||||
my_poptParseArgvString (cmd, &argc, &argv);
|
||||
g_shell_parse_argv (cmd, &argc, &argv, NULL);
|
||||
execvp (argv[0], argv);
|
||||
|
||||
g_strfreev (argv);
|
||||
}
|
||||
/* not reached unless error */
|
||||
/*printf("exec error\n");*/
|
||||
@@ -2539,7 +2534,6 @@ cmd_load (struct session *sess, char *tbuf, char *word[], char *word_eol[])
|
||||
char *file, *buf;
|
||||
#ifdef USE_PLUGIN
|
||||
char *error, *arg;
|
||||
int len;
|
||||
#endif
|
||||
|
||||
if (!word[2][0])
|
||||
@@ -2560,16 +2554,7 @@ cmd_load (struct session *sess, char *tbuf, char *word[], char *word_eol[])
|
||||
}
|
||||
|
||||
#ifdef USE_PLUGIN
|
||||
len = strlen (word[2]);
|
||||
#ifdef WIN32
|
||||
if (len > 4 && g_ascii_strcasecmp (".dll", word[2] + len - 4) == 0)
|
||||
#else
|
||||
#if defined(__hpux)
|
||||
if (len > 3 && g_ascii_strcasecmp (".sl", word[2] + len - 3) == 0)
|
||||
#else
|
||||
if (len > 3 && g_ascii_strcasecmp (".so", word[2] + len - 3) == 0)
|
||||
#endif
|
||||
#endif
|
||||
if (g_str_has_suffix (word[2], "."G_MODULE_SUFFIX))
|
||||
{
|
||||
arg = NULL;
|
||||
if (word_eol[3][0])
|
||||
@@ -3565,18 +3550,9 @@ static int
|
||||
cmd_unload (struct session *sess, char *tbuf, char *word[], char *word_eol[])
|
||||
{
|
||||
#ifdef USE_PLUGIN
|
||||
int len, by_file = FALSE;
|
||||
gboolean by_file = FALSE;
|
||||
|
||||
len = strlen (word[2]);
|
||||
#ifdef WIN32
|
||||
if (len > 4 && g_ascii_strcasecmp (word[2] + len - 4, ".dll") == 0)
|
||||
#else
|
||||
#if defined(__hpux)
|
||||
if (len > 3 && g_ascii_strcasecmp (word[2] + len - 3, ".sl") == 0)
|
||||
#else
|
||||
if (len > 3 && g_ascii_strcasecmp (word[2] + len - 3, ".so") == 0)
|
||||
#endif
|
||||
#endif
|
||||
if (g_str_has_suffix (word[2], "."G_MODULE_SUFFIX))
|
||||
by_file = TRUE;
|
||||
|
||||
switch (plugin_kill (word[2], by_file))
|
||||
@@ -3599,18 +3575,9 @@ static int
|
||||
cmd_reload (struct session *sess, char *tbuf, char *word[], char *word_eol[])
|
||||
{
|
||||
#ifdef USE_PLUGIN
|
||||
int len, by_file = FALSE;
|
||||
gboolean by_file = FALSE;
|
||||
|
||||
len = strlen (word[2]);
|
||||
#ifdef WIN32
|
||||
if (len > 4 && g_ascii_strcasecmp (word[2] + len - 4, ".dll") == 0)
|
||||
#else
|
||||
#if defined(__hpux)
|
||||
if (len > 3 && g_ascii_strcasecmp (word[2] + len - 3, ".sl") == 0)
|
||||
#else
|
||||
if (len > 3 && g_ascii_strcasecmp (word[2] + len - 3, ".so") == 0)
|
||||
#endif
|
||||
#endif
|
||||
if (g_str_has_suffix (word[2], "."G_MODULE_SUFFIX))
|
||||
by_file = TRUE;
|
||||
|
||||
switch (plugin_reload (sess, word[2], by_file))
|
||||
@@ -3746,8 +3713,8 @@ userlist_cb (struct User *user, session *sess)
|
||||
else
|
||||
lt = time (0) - user->lasttalk;
|
||||
PrintTextf (sess,
|
||||
"\00306%s\t\00314[\00310%-38s\00314] \017ov\0033=\017%d%d away=%u lt\0033=\017%d\n",
|
||||
user->nick, user->hostname, user->op, user->voice, user->away, lt);
|
||||
"\00306%s\t\00314[\00310%-38s\00314] \017ov\0033=\017%d%d away=%u lt\0033=\017%ld\n",
|
||||
user->nick, user->hostname, user->op, user->voice, user->away, (long)lt);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
#define g_ascii_strcasecmp stricmp
|
||||
#endif
|
||||
|
||||
#define _(x) hexchat_gettext(ph,x)
|
||||
|
||||
static hexchat_plugin *ph; /* plugin handle */
|
||||
static GSList *timer_list = NULL;
|
||||
|
||||
@@ -68,13 +70,13 @@ timer_del_ref (int ref, int quiet)
|
||||
{
|
||||
timer_del (tim);
|
||||
if (!quiet)
|
||||
hexchat_printf (ph, "Timer %d deleted.\n", ref);
|
||||
hexchat_printf (ph, _("Timer %d deleted.\n"), ref);
|
||||
return;
|
||||
}
|
||||
list = list->next;
|
||||
}
|
||||
if (!quiet)
|
||||
hexchat_print (ph, "No such ref number found.\n");
|
||||
hexchat_print (ph, _("No such ref number found.\n"));
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -138,17 +140,17 @@ timer_showlist (void)
|
||||
|
||||
if (timer_list == NULL)
|
||||
{
|
||||
hexchat_print (ph, "No timers installed.\n");
|
||||
hexchat_print (ph, HELP);
|
||||
hexchat_print (ph, _("No timers installed.\n"));
|
||||
hexchat_print (ph, _(HELP));
|
||||
return;
|
||||
}
|
||||
/* 00000 00000000 0000000 abc */
|
||||
hexchat_print (ph, "\026 Ref# Seconds Repeat Command \026\n");
|
||||
hexchat_print (ph, _("\026 Ref# Seconds Repeat Command \026\n"));
|
||||
list = timer_list;
|
||||
while (list)
|
||||
{
|
||||
tim = list->data;
|
||||
hexchat_printf (ph, "%5d %8.1f %7d %s\n", tim->ref, tim->timeout,
|
||||
hexchat_printf (ph, _("%5d %8.1f %7d %s\n"), tim->ref, tim->timeout,
|
||||
tim->repeat, tim->command);
|
||||
list = list->next;
|
||||
}
|
||||
@@ -221,7 +223,7 @@ hexchat_plugin_init
|
||||
*plugin_desc = "IrcII style /TIMER command";
|
||||
*plugin_version = "";
|
||||
|
||||
hexchat_hook_command (ph, "TIMER", HEXCHAT_PRI_NORM, timer_cb, HELP, 0);
|
||||
hexchat_hook_command (ph, "TIMER", HEXCHAT_PRI_NORM, timer_cb, _(HELP), 0);
|
||||
|
||||
return 1; /* return 1 for success */
|
||||
}
|
||||
|
||||
+36
-47
@@ -460,17 +460,11 @@ plugin_auto_load (session *sess)
|
||||
for_files (lib_dir, "hcupd.dll", plugin_auto_load_cb);
|
||||
for_files (lib_dir, "hcwinamp.dll", plugin_auto_load_cb);
|
||||
for_files (lib_dir, "hcsysinfo.dll", plugin_auto_load_cb);
|
||||
#else
|
||||
for_files (lib_dir, "*."G_MODULE_SUFFIX, plugin_auto_load_cb);
|
||||
#endif
|
||||
|
||||
for_files (sub_dir, "*.dll", plugin_auto_load_cb);
|
||||
#else
|
||||
#if defined(__hpux)
|
||||
for_files (lib_dir, "*.sl", plugin_auto_load_cb);
|
||||
for_files (sub_dir, "*.sl", plugin_auto_load_cb);
|
||||
#else
|
||||
for_files (lib_dir, "*.so", plugin_auto_load_cb);
|
||||
for_files (sub_dir, "*.so", plugin_auto_load_cb);
|
||||
#endif
|
||||
#endif
|
||||
for_files (sub_dir, "*."G_MODULE_SUFFIX, plugin_auto_load_cb);
|
||||
|
||||
g_free (sub_dir);
|
||||
}
|
||||
@@ -1757,6 +1751,7 @@ hexchat_pluginpref_set_str_real (hexchat_plugin *pl, const char *var, const char
|
||||
int prevSetting;
|
||||
char *confname;
|
||||
char *confname_tmp;
|
||||
char *escaped_value;
|
||||
char *buffer;
|
||||
char *buffer_tmp;
|
||||
char line_buffer[512]; /* the same as in cfg_put_str */
|
||||
@@ -1782,7 +1777,9 @@ hexchat_pluginpref_set_str_real (hexchat_plugin *pl, const char *var, const char
|
||||
{
|
||||
if (mode)
|
||||
{
|
||||
buffer = g_strdup_printf ("%s = %s\n", var, value);
|
||||
escaped_value = g_strescape (value, NULL);
|
||||
buffer = g_strdup_printf ("%s = %s\n", var, escaped_value);
|
||||
g_free (escaped_value);
|
||||
write (fhOut, buffer, strlen (buffer));
|
||||
g_free (buffer);
|
||||
close (fhOut);
|
||||
@@ -1830,7 +1827,9 @@ hexchat_pluginpref_set_str_real (hexchat_plugin *pl, const char *var, const char
|
||||
{
|
||||
if (mode) /* overwrite the existing matching setting if we are in save mode */
|
||||
{
|
||||
buffer = g_strdup_printf ("%s = %s\n", var, value);
|
||||
escaped_value = g_strescape (value, NULL);
|
||||
buffer = g_strdup_printf ("%s = %s\n", var, escaped_value);
|
||||
g_free (escaped_value);
|
||||
}
|
||||
else /* erase the setting in delete mode */
|
||||
{
|
||||
@@ -1854,7 +1853,9 @@ hexchat_pluginpref_set_str_real (hexchat_plugin *pl, const char *var, const char
|
||||
|
||||
if (!prevSetting && mode) /* var doesn't exist currently, append if we're in save mode */
|
||||
{
|
||||
buffer = g_strdup_printf ("%s = %s\n", var, value);
|
||||
escaped_value = g_strescape (value, NULL);
|
||||
buffer = g_strdup_printf ("%s = %s\n", var, escaped_value);
|
||||
g_free (escaped_value);
|
||||
write (fhOut, buffer, strlen (buffer));
|
||||
g_free (buffer);
|
||||
}
|
||||
@@ -1891,58 +1892,46 @@ hexchat_pluginpref_set_str (hexchat_plugin *pl, const char *var, const char *val
|
||||
return hexchat_pluginpref_set_str_real (pl, var, value, 1);
|
||||
}
|
||||
|
||||
int
|
||||
hexchat_pluginpref_get_str (hexchat_plugin *pl, const char *var, char *dest)
|
||||
static int
|
||||
hexchat_pluginpref_get_str_real (hexchat_plugin *pl, const char *var, char *dest, int dest_len)
|
||||
{
|
||||
int fh;
|
||||
int l;
|
||||
char confname[64];
|
||||
char *canon;
|
||||
char *cfg;
|
||||
struct stat st;
|
||||
char *confname, *canon, *cfg, *unescaped_value;
|
||||
char buf[512];
|
||||
|
||||
canon = g_strdup (pl->name);
|
||||
canonalize_key (canon);
|
||||
sprintf (confname, "addon_%s.conf", canon);
|
||||
confname = g_strdup_printf ("%s%caddon_%s.conf", get_xdir(), G_DIR_SEPARATOR, canon);
|
||||
g_free (canon);
|
||||
|
||||
/* partly borrowed from palette.c */
|
||||
fh = hexchat_open_file (confname, O_RDONLY, 0, 0);
|
||||
|
||||
if (fh == -1)
|
||||
if (!g_file_get_contents (confname, &cfg, NULL, NULL))
|
||||
{
|
||||
g_free (confname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
fstat (fh, &st);
|
||||
cfg = malloc (st.st_size + 1);
|
||||
g_free (confname);
|
||||
|
||||
if (!cfg)
|
||||
if (!cfg_get_str (cfg, var, buf, sizeof(buf)))
|
||||
{
|
||||
close (fh);
|
||||
g_free (cfg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
cfg[0] = '\0';
|
||||
l = read (fh, cfg, st.st_size);
|
||||
unescaped_value = g_strcompress (buf);
|
||||
g_strlcpy (dest, unescaped_value, dest_len);
|
||||
|
||||
if (l >= 0)
|
||||
{
|
||||
cfg[l] = '\0';
|
||||
}
|
||||
|
||||
if (!cfg_get_str (cfg, var, dest, 512)) /* dest_len is the same as buffer size in set */
|
||||
{
|
||||
free (cfg);
|
||||
close (fh);
|
||||
return 0;
|
||||
}
|
||||
|
||||
free (cfg);
|
||||
close (fh);
|
||||
g_free (unescaped_value);
|
||||
g_free (cfg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
hexchat_pluginpref_get_str (hexchat_plugin *pl, const char *var, char *dest)
|
||||
{
|
||||
/* All users of this must ensure dest is >= 512... */
|
||||
return hexchat_pluginpref_get_str_real (pl, var, dest, 512);
|
||||
}
|
||||
|
||||
int
|
||||
hexchat_pluginpref_set_int (hexchat_plugin *pl, const char *var, int value)
|
||||
{
|
||||
@@ -1957,7 +1946,7 @@ hexchat_pluginpref_get_int (hexchat_plugin *pl, const char *var)
|
||||
{
|
||||
char buffer[12];
|
||||
|
||||
if (hexchat_pluginpref_get_str (pl, var, buffer))
|
||||
if (hexchat_pluginpref_get_str_real (pl, var, buffer, sizeof(buffer)))
|
||||
{
|
||||
return atoi (buffer);
|
||||
}
|
||||
|
||||
+133
-143
@@ -76,7 +76,6 @@
|
||||
#endif
|
||||
|
||||
#ifdef USE_OPENSSL
|
||||
extern SSL_CTX *ctx; /* hexchat.c */
|
||||
/* local variables */
|
||||
static struct session *g_sess = NULL;
|
||||
#endif
|
||||
@@ -273,7 +272,7 @@ tcp_send (server *serv, char *buf)
|
||||
}*/
|
||||
|
||||
void
|
||||
tcp_sendf (server *serv, char *fmt, ...)
|
||||
tcp_sendf (server *serv, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
/* keep this buffer in BSS. Converting UTF-8 to ISO-8859-x might make the
|
||||
@@ -588,43 +587,76 @@ server_stopconnecting (server * serv)
|
||||
static void
|
||||
ssl_cb_info (SSL * s, int where, int ret)
|
||||
{
|
||||
/* char buf[128];*/
|
||||
|
||||
|
||||
return; /* FIXME: make debug level adjustable in serverlist or settings */
|
||||
|
||||
/* snprintf (buf, sizeof (buf), "%s (%d)", SSL_state_string_long (s), where);
|
||||
if (g_sess)
|
||||
EMIT_SIGNAL (XP_TE_SSLMESSAGE, g_sess, buf, NULL, NULL, NULL, 0);
|
||||
else
|
||||
fprintf (stderr, "%s\n", buf);*/
|
||||
return;
|
||||
}
|
||||
|
||||
static int
|
||||
ssl_cb_verify (int ok, X509_STORE_CTX * ctx)
|
||||
{
|
||||
char subject[256];
|
||||
char issuer[256];
|
||||
char buf[512];
|
||||
return TRUE; /* always ok */
|
||||
}
|
||||
|
||||
static void
|
||||
ssl_do_connect_finish (server *serv, int success, int verify_error)
|
||||
{
|
||||
/*
|
||||
we land here after ssl_do_connect(). possible execution flows are:
|
||||
ssl_do_connect -> ssl_do_connect_finish (with no user interaction)
|
||||
ssl_do_connect -> sslalert.c -> ssl_do_connect_finish (prompt user to accept/reject certificate)
|
||||
*/
|
||||
|
||||
X509_NAME_oneline (X509_get_subject_name (ctx->current_cert), subject,
|
||||
sizeof (subject));
|
||||
X509_NAME_oneline (X509_get_issuer_name (ctx->current_cert), issuer,
|
||||
sizeof (issuer));
|
||||
if (success)
|
||||
{
|
||||
/* connection has been established */
|
||||
server_stopconnecting (serv);
|
||||
server_connected (serv); /* activate gtk poll */
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
the connection failed. most likely because the certificate is invalid
|
||||
and the user hit the cancel button to reject the connection
|
||||
*/
|
||||
|
||||
char buf[128];
|
||||
snprintf (buf, sizeof (buf), "%s.? (%d)",
|
||||
X509_verify_cert_error_string (verify_error),
|
||||
verify_error);
|
||||
EMIT_SIGNAL (XP_TE_CONNFAIL, serv->server_session, buf, NULL, NULL,
|
||||
NULL, 0);
|
||||
server_cleanup (serv);
|
||||
}
|
||||
}
|
||||
|
||||
snprintf (buf, sizeof (buf), "* Subject: %s", subject);
|
||||
EMIT_SIGNAL (XP_TE_SSLMESSAGE, g_sess, buf, NULL, NULL, NULL, 0);
|
||||
snprintf (buf, sizeof (buf), "* Issuer: %s", issuer);
|
||||
EMIT_SIGNAL (XP_TE_SSLMESSAGE, g_sess, buf, NULL, NULL, NULL, 0);
|
||||
|
||||
return (TRUE); /* always ok */
|
||||
static void
|
||||
ssl_alert_cb (int user_action, void *callback_data)
|
||||
{
|
||||
/* interpret the user response and possibly abandon the connection */
|
||||
ssl_alert_context *context = callback_data;
|
||||
switch (user_action)
|
||||
{
|
||||
case SSLALERT_RESPONSE_ABORT: /* user wants to abandon connection */
|
||||
ssl_do_connect_finish (context->serv, FALSE, context->verify_error);
|
||||
break;
|
||||
case SSLALERT_RESPONSE_ACCEPT: /* user wants to accept the certificate ONLY this time */
|
||||
ssl_do_connect_finish (context->serv, TRUE, context->verify_error);
|
||||
break;
|
||||
case SSLALERT_RESPONSE_SAVE: /* user wants to accept the certificate AND remember it for next time */
|
||||
_SSL_certlist_cert_add (context->serv, &context->cert);
|
||||
_SSL_certlist_save ();
|
||||
ssl_do_connect_finish (context->serv, TRUE, context->verify_error);
|
||||
break;
|
||||
}
|
||||
free (context);
|
||||
}
|
||||
|
||||
static int
|
||||
ssl_do_connect (server * serv)
|
||||
{
|
||||
char buf[128];
|
||||
struct cert_info cert_info;
|
||||
ssl_alert_context *cb_context;
|
||||
int cert_error, verify_result;
|
||||
|
||||
g_sess = serv->server_session;
|
||||
if (SSL_connect (serv->ssl) <= 0)
|
||||
@@ -648,118 +680,12 @@ ssl_do_connect (server * serv)
|
||||
if (prefs.hex_net_auto_reconnectonfail)
|
||||
auto_reconnect (serv, FALSE, -1);
|
||||
|
||||
return (0); /* remove it (0) */
|
||||
return 0; /* remove it (0) */
|
||||
}
|
||||
}
|
||||
g_sess = NULL;
|
||||
|
||||
if (SSL_is_init_finished (serv->ssl))
|
||||
{
|
||||
struct cert_info cert_info;
|
||||
struct chiper_info *chiper_info;
|
||||
int verify_error;
|
||||
int i;
|
||||
|
||||
if (!_SSL_get_cert_info (&cert_info, serv->ssl))
|
||||
{
|
||||
snprintf (buf, sizeof (buf), "* Certification info:");
|
||||
EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL,
|
||||
NULL, 0);
|
||||
snprintf (buf, sizeof (buf), " Subject:");
|
||||
EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL,
|
||||
NULL, 0);
|
||||
for (i = 0; cert_info.subject_word[i]; i++)
|
||||
{
|
||||
snprintf (buf, sizeof (buf), " %s", cert_info.subject_word[i]);
|
||||
EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL,
|
||||
NULL, 0);
|
||||
}
|
||||
snprintf (buf, sizeof (buf), " Issuer:");
|
||||
EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL,
|
||||
NULL, 0);
|
||||
for (i = 0; cert_info.issuer_word[i]; i++)
|
||||
{
|
||||
snprintf (buf, sizeof (buf), " %s", cert_info.issuer_word[i]);
|
||||
EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL,
|
||||
NULL, 0);
|
||||
}
|
||||
snprintf (buf, sizeof (buf), " Public key algorithm: %s (%d bits)",
|
||||
cert_info.algorithm, cert_info.algorithm_bits);
|
||||
EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL,
|
||||
NULL, 0);
|
||||
/*if (cert_info.rsa_tmp_bits)
|
||||
{
|
||||
snprintf (buf, sizeof (buf),
|
||||
" Public key algorithm uses ephemeral key with %d bits",
|
||||
cert_info.rsa_tmp_bits);
|
||||
EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL,
|
||||
NULL, 0);
|
||||
}*/
|
||||
snprintf (buf, sizeof (buf), " Sign algorithm %s",
|
||||
cert_info.sign_algorithm/*, cert_info.sign_algorithm_bits*/);
|
||||
EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL,
|
||||
NULL, 0);
|
||||
snprintf (buf, sizeof (buf), " Valid since %s to %s",
|
||||
cert_info.notbefore, cert_info.notafter);
|
||||
EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL,
|
||||
NULL, 0);
|
||||
} else
|
||||
{
|
||||
snprintf (buf, sizeof (buf), " * No Certificate");
|
||||
EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL,
|
||||
NULL, 0);
|
||||
}
|
||||
|
||||
chiper_info = _SSL_get_cipher_info (serv->ssl); /* static buffer */
|
||||
snprintf (buf, sizeof (buf), "* Cipher info:");
|
||||
EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL, NULL,
|
||||
0);
|
||||
snprintf (buf, sizeof (buf), " Version: %s, cipher %s (%u bits)",
|
||||
chiper_info->version, chiper_info->chiper,
|
||||
chiper_info->chiper_bits);
|
||||
EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL, NULL,
|
||||
0);
|
||||
|
||||
verify_error = SSL_get_verify_result (serv->ssl);
|
||||
switch (verify_error)
|
||||
{
|
||||
case X509_V_OK:
|
||||
/* snprintf (buf, sizeof (buf), "* Verify OK (?)"); */
|
||||
/* EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL, NULL, 0); */
|
||||
break;
|
||||
case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
|
||||
case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
|
||||
case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
|
||||
case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
|
||||
case X509_V_ERR_CERT_HAS_EXPIRED:
|
||||
if (serv->accept_invalid_cert)
|
||||
{
|
||||
snprintf (buf, sizeof (buf), "* Verify E: %s.? (%d) -- Ignored",
|
||||
X509_verify_cert_error_string (verify_error),
|
||||
verify_error);
|
||||
EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL,
|
||||
NULL, 0);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
snprintf (buf, sizeof (buf), "%s.? (%d)",
|
||||
X509_verify_cert_error_string (verify_error),
|
||||
verify_error);
|
||||
EMIT_SIGNAL (XP_TE_CONNFAIL, serv->server_session, buf, NULL, NULL,
|
||||
NULL, 0);
|
||||
|
||||
server_cleanup (serv);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
server_stopconnecting (serv);
|
||||
|
||||
/* activate gtk poll */
|
||||
server_connected (serv);
|
||||
|
||||
return (0); /* remove it (0) */
|
||||
} else
|
||||
if (!SSL_is_init_finished (serv->ssl))
|
||||
{
|
||||
if (serv->ssl->session && serv->ssl->session->time + SSLTMOUT < time (NULL))
|
||||
{
|
||||
@@ -771,11 +697,71 @@ ssl_do_connect (server * serv)
|
||||
if (prefs.hex_net_auto_reconnectonfail)
|
||||
auto_reconnect (serv, FALSE, -1);
|
||||
|
||||
return (0); /* remove it (0) */
|
||||
return 0; /* remove it (0) */
|
||||
}
|
||||
|
||||
return (1); /* call it more (1) */
|
||||
return 1; /* call it more (1) */
|
||||
}
|
||||
|
||||
cert_error = _SSL_get_cert_info (&cert_info, serv->ssl);
|
||||
serv->cert_info = &cert_info;
|
||||
|
||||
/* at this point we check the certificate to make sure it is valid */
|
||||
|
||||
verify_result = SSL_get_verify_result (serv->ssl);
|
||||
|
||||
switch (verify_result)
|
||||
{
|
||||
/* 1) certificate is valid. finish connecting */
|
||||
case X509_V_OK:
|
||||
{
|
||||
X509 *cert = SSL_get_peer_certificate (serv->ssl);
|
||||
int hostname_err;
|
||||
if ((hostname_err = _SSL_check_hostname(cert, serv->hostname)) == 0)
|
||||
{
|
||||
ssl_do_connect_finish (serv, TRUE, verify_result);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* 2) certificate has a problem but the user might want to accept it */
|
||||
case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
|
||||
case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
|
||||
case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
|
||||
case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
|
||||
case X509_V_ERR_CERT_HAS_EXPIRED:
|
||||
#if 0
|
||||
if (serv->accept_invalid_cert)
|
||||
{
|
||||
ssl_do_connect_finish (serv, TRUE, verify_result);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
|
||||
/* 3) certificate has a problem and we should disconnect */
|
||||
default:
|
||||
ssl_do_connect_finish (serv, FALSE, verify_result); /* disconnect */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* check if this INVALID certificate is on the users whitelist */
|
||||
|
||||
if (_SSL_certlist_cert_check (serv, &cert_info))
|
||||
{
|
||||
ssl_do_connect_finish (serv, TRUE, verify_result);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* this INVALID certificate is not on the whitelist. ask the user what to do */
|
||||
|
||||
cb_context = malloc (sizeof (ssl_alert_context));
|
||||
cb_context->serv = serv;
|
||||
memcpy (&cb_context->cert, &cert_info, sizeof (cert_info));
|
||||
cb_context->verify_error = verify_result;
|
||||
fe_sslalert_open (serv, ssl_alert_cb, cb_context); /* bring up GUI alert */
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -861,8 +847,8 @@ server_connect_success (server *serv)
|
||||
|
||||
/* it'll be a memory leak, if connection isn't terminated by
|
||||
server_cleanup() */
|
||||
serv->ssl = _SSL_socket (ctx, serv->sok);
|
||||
if ((err = _SSL_set_verify (ctx, ssl_cb_verify, NULL)))
|
||||
serv->ssl = _SSL_socket (serv->ctx, serv->sok);
|
||||
if ((err = _SSL_set_verify (serv->ctx, ssl_cb_verify, NULL)))
|
||||
{
|
||||
EMIT_SIGNAL (XP_TE_CONNFAIL, serv->server_session, err, NULL,
|
||||
NULL, NULL, 0);
|
||||
@@ -1666,9 +1652,9 @@ server_connect (server *serv, char *hostname, int port, int no_login)
|
||||
session *sess = serv->server_session;
|
||||
|
||||
#ifdef USE_OPENSSL
|
||||
if (!ctx && serv->use_ssl)
|
||||
if (!serv->ctx && serv->use_ssl)
|
||||
{
|
||||
if (!(ctx = _SSL_context_init (ssl_cb_info, FALSE)))
|
||||
if (!(serv->ctx = _SSL_context_init (ssl_cb_info, FALSE)))
|
||||
{
|
||||
fprintf (stderr, "_SSL_context_init failed\n");
|
||||
exit (1);
|
||||
@@ -1711,18 +1697,18 @@ server_connect (server *serv, char *hostname, int port, int no_login)
|
||||
/* first try network specific cert/key */
|
||||
cert_file = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "certs" G_DIR_SEPARATOR_S "%s.pem",
|
||||
get_xdir (), server_get_network (serv, TRUE));
|
||||
if (SSL_CTX_use_certificate_file (ctx, cert_file, SSL_FILETYPE_PEM) == 1)
|
||||
if (SSL_CTX_use_certificate_file (serv->ctx, cert_file, SSL_FILETYPE_PEM) == 1)
|
||||
{
|
||||
if (SSL_CTX_use_PrivateKey_file (ctx, cert_file, SSL_FILETYPE_PEM) == 1)
|
||||
if (SSL_CTX_use_PrivateKey_file (serv->ctx, cert_file, SSL_FILETYPE_PEM) == 1)
|
||||
serv->have_cert = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* if that doesn't exist, try <config>/certs/client.pem */
|
||||
cert_file = g_build_filename (get_xdir (), "certs", "client.pem", NULL);
|
||||
if (SSL_CTX_use_certificate_file (ctx, cert_file, SSL_FILETYPE_PEM) == 1)
|
||||
if (SSL_CTX_use_certificate_file (serv->ctx, cert_file, SSL_FILETYPE_PEM) == 1)
|
||||
{
|
||||
if (SSL_CTX_use_PrivateKey_file (ctx, cert_file, SSL_FILETYPE_PEM) == 1)
|
||||
if (SSL_CTX_use_PrivateKey_file (serv->ctx, cert_file, SSL_FILETYPE_PEM) == 1)
|
||||
serv->have_cert = TRUE;
|
||||
}
|
||||
}
|
||||
@@ -2047,6 +2033,10 @@ server_free (server *serv)
|
||||
free (serv->encoding);
|
||||
if (serv->favlist)
|
||||
g_slist_free_full (serv->favlist, (GDestroyNotify) servlist_favchan_free);
|
||||
#ifdef USE_OPENSSL
|
||||
if (serv->ctx)
|
||||
_SSL_context_free (serv->ctx);
|
||||
#endif
|
||||
|
||||
fe_server_callback (serv);
|
||||
|
||||
|
||||
+1
-1
@@ -25,7 +25,7 @@ extern GSList *serv_list;
|
||||
/* eventually need to keep the tcp_* functions isolated to server.c */
|
||||
int tcp_send_len (server *serv, char *buf, int len);
|
||||
int tcp_send (server *serv, char *buf);
|
||||
void tcp_sendf (server *serv, char *fmt, ...);
|
||||
void tcp_sendf (server *serv, const char *fmt, ...) G_GNUC_PRINTF (2, 3);
|
||||
int tcp_send_real (void *ssl, int sok, char *encoding, int using_irc, char *buf, int len);
|
||||
|
||||
server *server_new (void);
|
||||
|
||||
+17
-1
@@ -75,12 +75,16 @@ static const struct defaultserver def[] =
|
||||
#endif
|
||||
#ifdef USE_OPENSSL
|
||||
{0, "irc.data.lt/+6668"},
|
||||
{0, "irc-ssl.omnitel.net/+6668"},
|
||||
{0, "irc.omnitel.net/+6668"},
|
||||
{0, "irc.ktu.lt/+6668"},
|
||||
{0, "irc.kis.lt/+6668"},
|
||||
{0, "irc.vub.lt/+6668"},
|
||||
#endif
|
||||
{0, "irc.data.lt"},
|
||||
{0, "irc.omnitel.net"},
|
||||
{0, "irc.ktu.lt"},
|
||||
{0, "irc.kis.lt"},
|
||||
{0, "irc.vub.lt"},
|
||||
|
||||
{"AlphaChat", 0, 0, 0, LOGIN_SASL},
|
||||
{0, "irc.alphachat.net"},
|
||||
@@ -241,6 +245,12 @@ static const struct defaultserver def[] =
|
||||
{"GameSurge", 0},
|
||||
{0, "irc.gamesurge.net"},
|
||||
|
||||
{"GeeksIRC", 0, 0, 0, LOGIN_SASL},
|
||||
#ifdef USE_OPENSSL
|
||||
{0, "irc.geeksirc.net/+6697"},
|
||||
#endif
|
||||
{0, "irc.geeksirc.net"},
|
||||
|
||||
{"GeekShed", 0},
|
||||
{0, "irc.geekshed.net"},
|
||||
|
||||
@@ -270,6 +280,12 @@ static const struct defaultserver def[] =
|
||||
#endif
|
||||
{0, "irc.interlinked.me"},
|
||||
|
||||
{"IRC4Fun", 0, 0, 0, LOGIN_SASL},
|
||||
#ifdef USE_OPENSSL
|
||||
{0, "irc.irc4fun.net/+6697"},
|
||||
#endif
|
||||
{0, "irc.irc4fun.net"},
|
||||
|
||||
{"IRCHighWay", 0},
|
||||
#ifdef USE_OPENSSL
|
||||
{0, "irc.irchighway.net/+9999"},
|
||||
|
||||
+447
-23
@@ -25,20 +25,25 @@
|
||||
#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() */
|
||||
#include "../../config-win32.h" /* HAVE_SNPRINTF */
|
||||
#else
|
||||
#include "../../config.h"
|
||||
#endif
|
||||
#include "../../config.h"
|
||||
#include <time.h> /* asctime() */
|
||||
#include <string.h> /* strncpy() */
|
||||
#include "hexchat.h"
|
||||
#include "cfgfiles.h"
|
||||
#include "ssl.h" /* struct cert_info */
|
||||
|
||||
#ifndef HAVE_SNPRINTF
|
||||
#include <glib.h>
|
||||
#include <glib/gprintf.h>
|
||||
#define snprintf g_snprintf
|
||||
#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
|
||||
|
||||
/* globals */
|
||||
@@ -57,7 +62,7 @@ __SSL_fill_err_buf (char *funcname)
|
||||
|
||||
err = ERR_get_error ();
|
||||
ERR_error_string (err, buf);
|
||||
snprintf (err_buf, sizeof (err_buf), "%s: %s (%d)\n", funcname, buf, err);
|
||||
g_snprintf (err_buf, sizeof (err_buf), "%s: %s (%d)\n", funcname, buf, err);
|
||||
}
|
||||
|
||||
|
||||
@@ -86,6 +91,11 @@ _SSL_context_init (void (*info_cb_func), int server)
|
||||
|
||||
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);
|
||||
|
||||
/* used in SSL_connect(), SSL_accept() */
|
||||
SSL_CTX_set_info_callback (ctx, info_cb_func);
|
||||
@@ -113,8 +123,8 @@ ASN1_TIME_snprintf (char *buf, int buf_len, ASN1_TIME * tm)
|
||||
buf[0] = 0;
|
||||
if (expires != NULL)
|
||||
{
|
||||
memset (buf, 0, buf_len);
|
||||
strncpy (buf, expires, 24);
|
||||
/* expires is not \0 terminated */
|
||||
safe_strcpy (buf, expires, MIN(24, buf_len));
|
||||
}
|
||||
BIO_free (inMem);
|
||||
}
|
||||
@@ -153,12 +163,15 @@ _SSL_get_cert_info (struct cert_info *cert_info, SSL * ssl)
|
||||
/* EVP_PKEY *tmp_pkey; */
|
||||
char notBefore[64];
|
||||
char notAfter[64];
|
||||
unsigned char digest[EVP_MAX_MD_SIZE]; /* SHA-256 fingerprint of the certificate */
|
||||
int digest_length;
|
||||
int alg;
|
||||
int sign_alg;
|
||||
int i;
|
||||
|
||||
|
||||
if (!(peer_cert = SSL_get_peer_certificate (ssl)))
|
||||
return (1); /* FATAL? */
|
||||
return 1; /* FATAL? */
|
||||
|
||||
X509_NAME_oneline (X509_get_subject_name (peer_cert), cert_info->subject,
|
||||
sizeof (cert_info->subject));
|
||||
@@ -176,20 +189,31 @@ _SSL_get_cert_info (struct cert_info *cert_info, SSL * ssl)
|
||||
|
||||
peer_pkey = X509_get_pubkey (peer_cert);
|
||||
|
||||
strncpy (cert_info->algorithm,
|
||||
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);
|
||||
strncpy (cert_info->sign_algorithm,
|
||||
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;
|
||||
strncpy (cert_info->notbefore, notBefore, sizeof (cert_info->notbefore));
|
||||
strncpy (cert_info->notafter, notAfter, sizeof (cert_info->notafter));
|
||||
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);
|
||||
|
||||
/* compute the fingerprint and make it pretty */
|
||||
X509_digest (peer_cert, EVP_sha256(), digest, &digest_length);
|
||||
cert_info->fingerprint[0] = '\0';
|
||||
for (i = 0; i < digest_length; ++i)
|
||||
{
|
||||
char digits[4];
|
||||
g_snprintf (digits, sizeof(digits), (i?":%02x":"%02x"), digest[i]);
|
||||
g_strlcat (cert_info->fingerprint, digits, sizeof(cert_info->fingerprint));
|
||||
}
|
||||
|
||||
|
||||
/* SSL_SESSION_print_fp(stdout, SSL_get_session(ssl)); */
|
||||
/*
|
||||
if (ssl->session->sess_cert->peer_rsa_tmp) {
|
||||
@@ -204,7 +228,7 @@ _SSL_get_cert_info (struct cert_info *cert_info, SSL * ssl)
|
||||
|
||||
X509_free (peer_cert);
|
||||
|
||||
return (0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -215,16 +239,68 @@ _SSL_get_cipher_info (SSL * ssl)
|
||||
|
||||
|
||||
c = SSL_get_current_cipher (ssl);
|
||||
strncpy (chiper_info.version, SSL_CIPHER_get_version (c),
|
||||
safe_strcpy (chiper_info.version, SSL_CIPHER_get_version (c),
|
||||
sizeof (chiper_info.version));
|
||||
strncpy (chiper_info.chiper, SSL_CIPHER_get_name (c),
|
||||
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);
|
||||
return &chiper_info;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* returns zero on success, non-zero on failure.
|
||||
* "*.freenode.com" matches "ssl.freenode.com" and "irc.freenode.com" but not "chat.irc.freenode.com"
|
||||
*/
|
||||
int
|
||||
_SSL_verify_cert_hostname (struct server *serv, struct cert_info *cert)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; cert->subject_word[i]; i++)
|
||||
{
|
||||
char *cname = cert->subject_word[i];
|
||||
if (strstr (cname, "CN=") == cname)
|
||||
{
|
||||
char *host = serv->hostname;
|
||||
cname += strlen ("CN=");
|
||||
while (*host && *cname)
|
||||
{
|
||||
switch (*cname)
|
||||
{
|
||||
case '*': /* wildcard matching */
|
||||
switch (*host)
|
||||
{
|
||||
case '.':
|
||||
cname++; /* wildcard ends */
|
||||
break;
|
||||
default:
|
||||
host++; /* wildcard continues */
|
||||
if (!*host)
|
||||
{
|
||||
cname++; /* wildcard ends */
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default: /* regular strcmp */
|
||||
if (*host++ != *cname++)
|
||||
{
|
||||
return 1; /* error: mismatch */
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (*host || *cname)
|
||||
{
|
||||
return 1; /* error: failed to process both strings completely */
|
||||
}
|
||||
return 0; /* success: match */
|
||||
}
|
||||
}
|
||||
return 1; /* error: no CNAME field */
|
||||
}
|
||||
|
||||
int
|
||||
_SSL_send (SSL * ssl, char *buf, int len)
|
||||
{
|
||||
@@ -249,7 +325,7 @@ _SSL_send (SSL * ssl, char *buf, int len)
|
||||
break;
|
||||
}
|
||||
|
||||
return (num);
|
||||
return num;
|
||||
}
|
||||
|
||||
|
||||
@@ -278,7 +354,7 @@ _SSL_recv (SSL * ssl, char *buf, int len)
|
||||
break;
|
||||
}
|
||||
|
||||
return (num);
|
||||
return num;
|
||||
}
|
||||
|
||||
|
||||
@@ -298,7 +374,7 @@ _SSL_socket (SSL_CTX *ctx, int sd)
|
||||
else
|
||||
SSL_set_accept_state(ssl);
|
||||
|
||||
return (ssl);
|
||||
return ssl;
|
||||
}
|
||||
|
||||
|
||||
@@ -308,7 +384,7 @@ _SSL_set_verify (SSL_CTX *ctx, void *verify_callback, char *cacert)
|
||||
if (!SSL_CTX_set_default_verify_paths (ctx))
|
||||
{
|
||||
__SSL_fill_err_buf ("SSL_CTX_set_default_verify_paths");
|
||||
return (err_buf);
|
||||
return err_buf;
|
||||
}
|
||||
/*
|
||||
if (cacert)
|
||||
@@ -316,13 +392,13 @@ _SSL_set_verify (SSL_CTX *ctx, void *verify_callback, char *cacert)
|
||||
if (!SSL_CTX_load_verify_locations (ctx, cacert, NULL))
|
||||
{
|
||||
__SSL_fill_err_buf ("SSL_CTX_load_verify_locations");
|
||||
return (err_buf);
|
||||
return err_buf;
|
||||
}
|
||||
}
|
||||
*/
|
||||
SSL_CTX_set_verify (ctx, SSL_VERIFY_PEER, verify_callback);
|
||||
|
||||
return (NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -333,3 +409,351 @@ _SSL_close (SSL * ssl)
|
||||
SSL_free (ssl);
|
||||
ERR_remove_state (0); /* free state buffer */
|
||||
}
|
||||
|
||||
|
||||
/* 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)
|
||||
{
|
||||
unsigned char *data;
|
||||
int format;
|
||||
|
||||
format = ASN1_STRING_type (altname->d.dNSName);
|
||||
if (format == V_ASN1_IA5STRING)
|
||||
{
|
||||
data = ASN1_STRING_data (altname->d.dNSName);
|
||||
|
||||
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)
|
||||
{
|
||||
unsigned char *data;
|
||||
const guint8 *addr_bytes;
|
||||
int datalen, addr_len;
|
||||
|
||||
datalen = ASN1_STRING_length (altname->d.iPAddress);
|
||||
data = ASN1_STRING_data (altname->d.iPAddress);
|
||||
|
||||
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_free (altname_stack);
|
||||
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 = calloc (common_name_len + 1, 1);
|
||||
if (common_name == NULL)
|
||||
return -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:
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
/* Cert list */
|
||||
|
||||
static GSList *ssl_certlist = NULL; /* loaded at startup, saved on shutdown */
|
||||
|
||||
typedef struct ssl_certlist_item {
|
||||
char *hostname;
|
||||
char *fingerprint;
|
||||
} ssl_certlist_item;
|
||||
|
||||
static void
|
||||
_SSL_certlist_item_free (ssl_certlist_item *item)
|
||||
{
|
||||
g_return_if_fail (item != NULL);
|
||||
|
||||
if (item->hostname)
|
||||
g_free (item->hostname);
|
||||
if (item->fingerprint)
|
||||
g_free (item->fingerprint);
|
||||
g_free (item);
|
||||
}
|
||||
|
||||
/* append a new hostname+fingerprint to the certificate list */
|
||||
static void
|
||||
_SSL_certlist_item_add (char *hostname, char *fingerprint)
|
||||
{
|
||||
int hn_length = strlen (hostname);
|
||||
int fp_length = strlen (fingerprint);
|
||||
ssl_certlist_item *item = g_malloc0 (sizeof (ssl_certlist_item));
|
||||
|
||||
if (item)
|
||||
{
|
||||
item->hostname = g_malloc0 (hn_length + 1);
|
||||
item->fingerprint = g_malloc0 (fp_length + 1);
|
||||
if (!item->hostname || !item->fingerprint)
|
||||
{
|
||||
_SSL_certlist_item_free (item);
|
||||
return;
|
||||
}
|
||||
g_strlcpy (item->hostname, hostname, hn_length);
|
||||
g_strlcpy (item->fingerprint, fingerprint, fp_length);
|
||||
|
||||
ssl_certlist = g_slist_append (ssl_certlist, item);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* parse a simple new-line/whitepsace delimited text file of hostname+fingerprint combinations.
|
||||
* it is not a problem if the file does not exist - we just end up with a empty list.
|
||||
* it should be pretty safe against corrupted input. example file contents follows:
|
||||
*
|
||||
* irc.something.com 01:22:1a:c3:43:e6:35:ff:73:76:17:98:68:2f:2c:00:07:ae:1b:b8:81:a3:8d:0f:a6:a5:bd:dc:80:03:6c:33
|
||||
* ssl.someircserver.com 02:22:1a:c3:43:e6:35:ff:73:76:17:98:68:2f:2c:00:07:ae:1b:b8:81:a3:8d:0f:a6:a5:bd:dc:80:03:6c:33
|
||||
* another.com 03:22:1a:c3:43:e6:35:ff:73:76:17:98:68:2f:2c:00:07:ae:1b:b8:81:a3:8d:0f:a6:a5:bd:dc:80:03:6c:33
|
||||
*/
|
||||
void
|
||||
_SSL_certlist_init ()
|
||||
{
|
||||
char buf[1024];
|
||||
char *space, *host, *fp;
|
||||
FILE *fh;
|
||||
|
||||
fh = hexchat_fopen_file ("sslcerts.conf", "r", 0);
|
||||
if (!fh)
|
||||
return;
|
||||
|
||||
while (fgets (buf, sizeof(buf), fh))
|
||||
{
|
||||
|
||||
space = strchr (buf, ' ');
|
||||
if (!space)
|
||||
continue;
|
||||
|
||||
*space = '\0';
|
||||
|
||||
host = buf;
|
||||
fp = g_strchomp (space + 1);
|
||||
|
||||
if (host[0] && fp[0])
|
||||
_SSL_certlist_item_add (host, fp);
|
||||
}
|
||||
|
||||
fclose (fh);
|
||||
}
|
||||
|
||||
void
|
||||
_SSL_certlist_save ()
|
||||
{
|
||||
/* write the list back out to disk. if there are no items an empty file is created. */
|
||||
GSList *list;
|
||||
ssl_certlist_item *item;
|
||||
FILE *fh;
|
||||
|
||||
fh = hexchat_fopen_file ("sslcerts.conf", "w", 0);
|
||||
if (fh)
|
||||
{
|
||||
list = ssl_certlist;
|
||||
while (list)
|
||||
{
|
||||
item = (ssl_certlist_item*)list->data;
|
||||
|
||||
fprintf (fh, "%s %s\n", item->hostname, item->fingerprint);
|
||||
|
||||
list = g_slist_next (list);
|
||||
}
|
||||
fclose (fh);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* a "computer" is a hostname + certificate combination. we extract these details
|
||||
* from the input structures and make an O(n) (worst-case) pass over the list to find
|
||||
* a match. if the computer is known to us we return 1, and 0 otherwise.
|
||||
*/
|
||||
int
|
||||
_SSL_certlist_cert_check (struct server *serv, struct cert_info *cert)
|
||||
{
|
||||
GSList *list;
|
||||
ssl_certlist_item *item;
|
||||
|
||||
if (serv && cert)
|
||||
{
|
||||
list = ssl_certlist;
|
||||
while (list)
|
||||
{
|
||||
item = (ssl_certlist_item*)list->data;
|
||||
|
||||
if (!g_ascii_strcasecmp (serv->hostname, item->hostname)
|
||||
&& !g_ascii_strcasecmp (cert->fingerprint, item->fingerprint))
|
||||
{
|
||||
return 1; /* the user trusts this computer */
|
||||
}
|
||||
list = g_slist_next (list);
|
||||
}
|
||||
}
|
||||
return 0; /* the user does NOT trust this computer */
|
||||
}
|
||||
|
||||
void
|
||||
_SSL_certlist_cert_add (struct server *serv, struct cert_info *cert)
|
||||
{
|
||||
/* called from server.c when the user decides that they want to remember a computer */
|
||||
_SSL_certlist_item_add (serv->hostname, cert->fingerprint);
|
||||
}
|
||||
|
||||
|
||||
+24
-2
@@ -31,13 +31,28 @@ struct cert_info {
|
||||
int sign_algorithm_bits;
|
||||
char notbefore[32];
|
||||
char notafter[32];
|
||||
char fingerprint[128];
|
||||
|
||||
int rsa_tmp_bits;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
SSLALERT_RESPONSE_ABORT = 0,
|
||||
SSLALERT_RESPONSE_ACCEPT = 1,
|
||||
SSLALERT_RESPONSE_SAVE = 2
|
||||
};
|
||||
|
||||
typedef struct ssl_alert_context
|
||||
{
|
||||
struct server *serv;
|
||||
struct cert_info cert;
|
||||
int verify_error;
|
||||
} ssl_alert_context;
|
||||
|
||||
struct chiper_info {
|
||||
char version[16];
|
||||
char chiper[24];
|
||||
char chiper[48];
|
||||
int chiper_bits;
|
||||
};
|
||||
|
||||
@@ -52,9 +67,10 @@ char *_SSL_set_verify (SSL_CTX *ctx, void *(verify_callback), char *cacert);
|
||||
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);
|
||||
int _SSL_verify_cert_hostname (struct server *serv, struct cert_info *cert);
|
||||
|
||||
/*char *_SSL_add_keypair (SSL_CTX *ctx, char *privkey, char *cert);*/
|
||||
/*void _SSL_add_random_keypair(SSL_CTX *ctx, int bits);*/
|
||||
@@ -82,4 +98,10 @@ int _SSL_recv (SSL * ssl, char *buf, int len);
|
||||
|
||||
/*int _SSL_verify_x509(X509 *x509);*/
|
||||
|
||||
/* functions for managing the SSL certificate/fingerprint cache */
|
||||
void _SSL_certlist_init ();
|
||||
void _SSL_certlist_save ();
|
||||
int _SSL_certlist_cert_check (struct server *serv, struct cert_info *cert);
|
||||
void _SSL_certlist_cert_add (struct server *serv, struct cert_info *cert);
|
||||
|
||||
#endif
|
||||
|
||||
+10
-3
@@ -927,7 +927,7 @@ PrintText (session *sess, char *text)
|
||||
}
|
||||
|
||||
void
|
||||
PrintTextf (session *sess, char *format, ...)
|
||||
PrintTextf (session *sess, const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
char *buf;
|
||||
@@ -941,7 +941,7 @@ PrintTextf (session *sess, char *format, ...)
|
||||
}
|
||||
|
||||
void
|
||||
PrintTextTimeStampf (session *sess, time_t timestamp, char *format, ...)
|
||||
PrintTextTimeStampf (session *sess, time_t timestamp, const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
char *buf;
|
||||
@@ -2300,7 +2300,14 @@ sound_play (const char *file, gboolean quiet)
|
||||
if (g_access (wavfile, R_OK) == 0)
|
||||
{
|
||||
#ifdef WIN32
|
||||
PlaySound (wavfile, NULL, SND_NODEFAULT|SND_FILENAME|SND_ASYNC);
|
||||
gunichar2 *wavfile_utf16 = g_utf8_to_utf16 (wavfile, -1, NULL, NULL, NULL);
|
||||
|
||||
if (wavfile_utf16 != NULL)
|
||||
{
|
||||
PlaySoundW (wavfile_utf16, NULL, SND_NODEFAULT | SND_FILENAME | SND_ASYNC);
|
||||
|
||||
g_free (wavfile_utf16);
|
||||
}
|
||||
#else
|
||||
#ifdef USE_LIBCANBERRA
|
||||
if (ca_con == NULL)
|
||||
|
||||
+2
-2
@@ -43,8 +43,8 @@ void scrollback_load (session *sess);
|
||||
int text_word_check (char *word, int len);
|
||||
void PrintText (session *sess, char *text);
|
||||
void PrintTextTimeStamp (session *sess, char *text, time_t timestamp);
|
||||
void PrintTextf (session *sess, char *format, ...);
|
||||
void PrintTextTimeStampf (session *sess, time_t timestamp, char *format, ...);
|
||||
void PrintTextf (session *sess, const char *format, ...) G_GNUC_PRINTF (2, 3);
|
||||
void PrintTextTimeStampf (session *sess, time_t timestamp, const char *format, ...) G_GNUC_PRINTF (3, 4);
|
||||
void log_close (session *sess);
|
||||
void log_open_or_close (session *sess);
|
||||
void load_text_events (void);
|
||||
|
||||
+4
-4
@@ -415,8 +415,8 @@ regex_match (const GRegex *re, const char *word, int *start, int *end)
|
||||
}
|
||||
|
||||
/* Miscellaneous description --- */
|
||||
#define DOMAIN "[a-z0-9][-a-z0-9]*(\\.[-a-z0-9]+)*"
|
||||
#define TLD "\\.[a-z][-a-z0-9]*[a-z]"
|
||||
#define DOMAIN "[_\\pL\\pN][-_\\pL\\pN]*(\\.[-_\\pL\\pN]+)*"
|
||||
#define TLD "\\.[\\pL][-\\pL\\pN]*[\\pL]"
|
||||
#define IPADDR "[0-9]{1,3}(\\.[0-9]{1,3}){3}"
|
||||
#define IPV6GROUP "([0-9a-f]{0,4})"
|
||||
#define IPV6ADDR "((" IPV6GROUP "(:" IPV6GROUP "){7})" \
|
||||
@@ -429,7 +429,7 @@ regex_match (const GRegex *re, const char *word, int *start, int *end)
|
||||
#define OPT_PORT "(" PORT ")?"
|
||||
|
||||
static GRegex *
|
||||
make_re (char *grist)
|
||||
make_re (const char *grist)
|
||||
{
|
||||
GRegex *ret;
|
||||
GError *err = NULL;
|
||||
@@ -610,7 +610,7 @@ re_url (void)
|
||||
}
|
||||
|
||||
/* EMAIL description --- */
|
||||
#define EMAIL "[a-z][-_a-z0-9]+@" "(" HOST_URL ")"
|
||||
#define EMAIL "[a-z][._%+-a-z0-9]+@" "(" HOST_URL ")"
|
||||
|
||||
static const GRegex *
|
||||
re_email (void)
|
||||
|
||||
+40
-385
@@ -34,17 +34,14 @@
|
||||
#include <process.h>
|
||||
#include <io.h>
|
||||
#include <VersionHelpers.h>
|
||||
#include "../dirent/dirent-win32.h"
|
||||
#include "../../config-win32.h"
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#include <pwd.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <dirent.h>
|
||||
#include "../../config.h"
|
||||
#endif
|
||||
|
||||
#include "../../config.h"
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include "hexchat.h"
|
||||
@@ -74,187 +71,6 @@
|
||||
#define snprintf g_snprintf
|
||||
#endif
|
||||
|
||||
#ifdef USE_DEBUG
|
||||
|
||||
#undef free
|
||||
#undef malloc
|
||||
#undef realloc
|
||||
#undef strdup
|
||||
|
||||
int current_mem_usage;
|
||||
|
||||
struct mem_block
|
||||
{
|
||||
char *file;
|
||||
void *buf;
|
||||
int size;
|
||||
int line;
|
||||
int total;
|
||||
struct mem_block *next;
|
||||
};
|
||||
|
||||
struct mem_block *mroot = NULL;
|
||||
|
||||
void *
|
||||
hexchat_malloc (int size, char *file, int line)
|
||||
{
|
||||
void *ret;
|
||||
struct mem_block *new;
|
||||
|
||||
current_mem_usage += size;
|
||||
ret = malloc (size);
|
||||
if (!ret)
|
||||
{
|
||||
printf ("Out of memory! (%d)\n", current_mem_usage);
|
||||
exit (255);
|
||||
}
|
||||
|
||||
new = malloc (sizeof (struct mem_block));
|
||||
new->buf = ret;
|
||||
new->size = size;
|
||||
new->next = mroot;
|
||||
new->line = line;
|
||||
new->file = strdup (file);
|
||||
mroot = new;
|
||||
|
||||
printf ("%s:%d Malloc'ed %d bytes, now \033[35m%d\033[m\n", file, line,
|
||||
size, current_mem_usage);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void *
|
||||
hexchat_realloc (char *old, int len, char *file, int line)
|
||||
{
|
||||
char *ret;
|
||||
|
||||
ret = hexchat_malloc (len, file, line);
|
||||
if (ret)
|
||||
{
|
||||
strcpy (ret, old);
|
||||
hexchat_dfree (old, file, line);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void *
|
||||
hexchat_strdup (char *str, char *file, int line)
|
||||
{
|
||||
void *ret;
|
||||
struct mem_block *new;
|
||||
int size;
|
||||
|
||||
size = strlen (str) + 1;
|
||||
current_mem_usage += size;
|
||||
ret = malloc (size);
|
||||
if (!ret)
|
||||
{
|
||||
printf ("Out of memory! (%d)\n", current_mem_usage);
|
||||
exit (255);
|
||||
}
|
||||
strcpy (ret, str);
|
||||
|
||||
new = malloc (sizeof (struct mem_block));
|
||||
new->buf = ret;
|
||||
new->size = size;
|
||||
new->next = mroot;
|
||||
new->line = line;
|
||||
new->file = strdup (file);
|
||||
mroot = new;
|
||||
|
||||
printf ("%s:%d strdup (\"%-.40s\") size: %d, total: \033[35m%d\033[m\n",
|
||||
file, line, str, size, current_mem_usage);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
hexchat_mem_list (void)
|
||||
{
|
||||
struct mem_block *cur, *p;
|
||||
GSList *totals = 0;
|
||||
GSList *list;
|
||||
|
||||
cur = mroot;
|
||||
while (cur)
|
||||
{
|
||||
list = totals;
|
||||
while (list)
|
||||
{
|
||||
p = list->data;
|
||||
if (p->line == cur->line &&
|
||||
strcmp (p->file, cur->file) == 0)
|
||||
{
|
||||
p->total += p->size;
|
||||
break;
|
||||
}
|
||||
list = list->next;
|
||||
}
|
||||
if (!list)
|
||||
{
|
||||
cur->total = cur->size;
|
||||
totals = g_slist_prepend (totals, cur);
|
||||
}
|
||||
cur = cur->next;
|
||||
}
|
||||
|
||||
fprintf (stderr, "file line size num total\n");
|
||||
list = totals;
|
||||
while (list)
|
||||
{
|
||||
cur = list->data;
|
||||
fprintf (stderr, "%-15.15s %6d %6d %6d %6d\n", cur->file, cur->line,
|
||||
cur->size, cur->total/cur->size, cur->total);
|
||||
list = list->next;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
hexchat_dfree (void *buf, char *file, int line)
|
||||
{
|
||||
struct mem_block *cur, *last;
|
||||
|
||||
if (buf == NULL)
|
||||
{
|
||||
printf ("%s:%d \033[33mTried to free NULL\033[m\n", file, line);
|
||||
return;
|
||||
}
|
||||
|
||||
last = NULL;
|
||||
cur = mroot;
|
||||
while (cur)
|
||||
{
|
||||
if (buf == cur->buf)
|
||||
break;
|
||||
last = cur;
|
||||
cur = cur->next;
|
||||
}
|
||||
if (cur == NULL)
|
||||
{
|
||||
printf ("%s:%d \033[31mTried to free unknown block %lx!\033[m\n",
|
||||
file, line, (unsigned long) buf);
|
||||
/* abort(); */
|
||||
free (buf);
|
||||
return;
|
||||
}
|
||||
current_mem_usage -= cur->size;
|
||||
printf ("%s:%d Free'ed %d bytes, usage now \033[35m%d\033[m\n",
|
||||
file, line, cur->size, current_mem_usage);
|
||||
if (last)
|
||||
last->next = cur->next;
|
||||
else
|
||||
mroot = cur->next;
|
||||
free (cur->file);
|
||||
free (cur);
|
||||
}
|
||||
|
||||
#define malloc(n) hexchat_malloc(n, __FILE__, __LINE__)
|
||||
#define realloc(n, m) hexchat_realloc(n, m, __FILE__, __LINE__)
|
||||
#define free(n) hexchat_dfree(n, __FILE__, __LINE__)
|
||||
#define strdup(n) hexchat_strdup(n, __FILE__, __LINE__)
|
||||
|
||||
#endif /* MEMORY_DEBUG */
|
||||
|
||||
char *
|
||||
file_part (char *file)
|
||||
{
|
||||
@@ -433,33 +249,33 @@ char *
|
||||
expand_homedir (char *file)
|
||||
{
|
||||
#ifndef WIN32
|
||||
char *ret, *user;
|
||||
char *user;
|
||||
struct passwd *pw;
|
||||
|
||||
if (*file == '~')
|
||||
if (file[0] == '~')
|
||||
{
|
||||
if (file[1] != '\0' && file[1] != '/')
|
||||
{
|
||||
user = strdup(file);
|
||||
if (strchr(user,'/') != NULL)
|
||||
*(strchr(user,'/')) = '\0';
|
||||
if ((pw = getpwnam(user + 1)) == NULL)
|
||||
{
|
||||
free(user);
|
||||
return strdup(file);
|
||||
}
|
||||
free(user);
|
||||
user = strchr(file, '/') != NULL ? strchr(file,'/') : file;
|
||||
ret = malloc(strlen(user) + strlen(pw->pw_dir) + 1);
|
||||
strcpy(ret, pw->pw_dir);
|
||||
strcat(ret, user);
|
||||
}
|
||||
if (file[1] == '\0' || file[1] == '/')
|
||||
return g_strconcat (g_get_home_dir (), &file[1], NULL);
|
||||
|
||||
char *slash_pos;
|
||||
|
||||
user = g_strdup(file);
|
||||
|
||||
slash_pos = strchr(user, '/');
|
||||
if (slash_pos != NULL)
|
||||
*slash_pos = '\0';
|
||||
|
||||
pw = getpwnam(user + 1);
|
||||
g_free(user);
|
||||
|
||||
if (pw == NULL)
|
||||
return g_strdup(file);
|
||||
|
||||
slash_pos = strchr(file, '/');
|
||||
if (slash_pos == NULL)
|
||||
return g_strdup (pw->pw_dir);
|
||||
else
|
||||
{
|
||||
ret = malloc (strlen (file) + strlen (g_get_home_dir ()) + 1);
|
||||
sprintf (ret, "%s%s", g_get_home_dir (), file + 1);
|
||||
}
|
||||
return ret;
|
||||
return g_strconcat (pw->pw_dir, slash_pos, NULL);
|
||||
}
|
||||
#endif
|
||||
return g_strdup (file);
|
||||
@@ -935,27 +751,26 @@ break_while:
|
||||
void
|
||||
for_files (char *dirname, char *mask, void callback (char *file))
|
||||
{
|
||||
DIR *dir;
|
||||
struct dirent *ent;
|
||||
GDir *dir;
|
||||
const gchar *entry_name;
|
||||
char *buf;
|
||||
|
||||
dir = opendir (dirname);
|
||||
dir = g_dir_open (dirname, 0, NULL);
|
||||
if (dir)
|
||||
{
|
||||
while ((ent = readdir (dir)))
|
||||
while ((entry_name = g_dir_read_name (dir)))
|
||||
{
|
||||
if (strcmp (ent->d_name, ".") && strcmp (ent->d_name, ".."))
|
||||
if (strcmp (entry_name, ".") && strcmp (entry_name, ".."))
|
||||
{
|
||||
if (match (mask, ent->d_name))
|
||||
if (match (mask, entry_name))
|
||||
{
|
||||
buf = malloc (strlen (dirname) + strlen (ent->d_name) + 2);
|
||||
sprintf (buf, "%s" G_DIR_SEPARATOR_S "%s", dirname, ent->d_name);
|
||||
buf = g_build_filename (dirname, entry_name, NULL);
|
||||
callback (buf);
|
||||
free (buf);
|
||||
g_free (buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
closedir (dir);
|
||||
g_dir_close (dir);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1299,171 +1114,10 @@ country_search (char *pattern, void *ud, void (*print)(void *, char *, ...))
|
||||
}
|
||||
}
|
||||
|
||||
/* I think gnome1.0.x isn't necessarily linked against popt, ah well! */
|
||||
/* !!! For now use this inlined function, or it would break fe-text building */
|
||||
/* .... will find a better solution later. */
|
||||
/*#ifndef USE_GNOME*/
|
||||
|
||||
/* this is taken from gnome-libs 1.2.4 */
|
||||
#define POPT_ARGV_ARRAY_GROW_DELTA 5
|
||||
|
||||
int my_poptParseArgvString(const char * s, int * argcPtr, char *** argvPtr) {
|
||||
char * buf, * bufStart, * dst;
|
||||
const char * src;
|
||||
char quote = '\0';
|
||||
int argvAlloced = POPT_ARGV_ARRAY_GROW_DELTA;
|
||||
char ** argv = malloc(sizeof(*argv) * argvAlloced);
|
||||
const char ** argv2;
|
||||
int argc = 0;
|
||||
int i, buflen;
|
||||
|
||||
buflen = strlen(s) + 1;
|
||||
/* bufStart = buf = alloca(buflen);*/
|
||||
bufStart = buf = malloc (buflen);
|
||||
memset(buf, '\0', buflen);
|
||||
|
||||
src = s;
|
||||
argv[argc] = buf;
|
||||
|
||||
while (*src) {
|
||||
if (quote == *src) {
|
||||
quote = '\0';
|
||||
} else if (quote) {
|
||||
if (*src == '\\') {
|
||||
src++;
|
||||
if (!*src) {
|
||||
free(argv);
|
||||
free(bufStart);
|
||||
return 1;
|
||||
}
|
||||
if (*src != quote) *buf++ = '\\';
|
||||
}
|
||||
*buf++ = *src;
|
||||
/*} else if (isspace((unsigned char) *src)) {*/
|
||||
} else if (*src == ' ') {
|
||||
if (*argv[argc]) {
|
||||
buf++, argc++;
|
||||
if (argc == argvAlloced) {
|
||||
char **temp;
|
||||
argvAlloced += POPT_ARGV_ARRAY_GROW_DELTA;
|
||||
temp = realloc(argv, sizeof(*argv) * argvAlloced);
|
||||
if (temp)
|
||||
argv = temp;
|
||||
else
|
||||
{
|
||||
free(argv);
|
||||
free(bufStart);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
argv[argc] = buf;
|
||||
}
|
||||
} else switch (*src) {
|
||||
case '"':
|
||||
case '\'':
|
||||
quote = *src;
|
||||
break;
|
||||
case '\\':
|
||||
src++;
|
||||
if (!*src) {
|
||||
free(argv);
|
||||
free(bufStart);
|
||||
return 1;
|
||||
}
|
||||
/* fallthrough */
|
||||
default:
|
||||
*buf++ = *src;
|
||||
}
|
||||
|
||||
src++;
|
||||
}
|
||||
|
||||
if (strlen(argv[argc])) {
|
||||
argc++, buf++;
|
||||
}
|
||||
|
||||
dst = malloc((argc + 1) * sizeof(*argv) + (buf - bufStart));
|
||||
argv2 = (void *) dst;
|
||||
dst += (argc + 1) * sizeof(*argv);
|
||||
memcpy((void *)argv2, argv, argc * sizeof(*argv));
|
||||
argv2[argc] = NULL;
|
||||
memcpy(dst, bufStart, buf - bufStart);
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
argv2[i] = dst + (argv[i] - bufStart);
|
||||
}
|
||||
|
||||
free(argv);
|
||||
|
||||
*argvPtr = (char **)argv2; /* XXX don't change the API */
|
||||
*argcPtr = argc;
|
||||
|
||||
free (bufStart);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
void
|
||||
util_exec (const char *cmd)
|
||||
{
|
||||
char **argv;
|
||||
int argc;
|
||||
#ifndef WIN32
|
||||
int pid;
|
||||
int fd;
|
||||
#endif
|
||||
|
||||
if (my_poptParseArgvString (cmd, &argc, &argv) != 0)
|
||||
return -1;
|
||||
|
||||
#ifndef WIN32
|
||||
pid = fork ();
|
||||
if (pid == -1)
|
||||
{
|
||||
free (argv);
|
||||
return -1;
|
||||
}
|
||||
if (pid == 0)
|
||||
{
|
||||
/* Now close all open file descriptors except stdin, stdout and stderr */
|
||||
for (fd = 3; fd < 1024; fd++) close(fd);
|
||||
execvp (argv[0], argv);
|
||||
_exit (0);
|
||||
} else
|
||||
{
|
||||
free (argv);
|
||||
return pid;
|
||||
}
|
||||
#else
|
||||
spawnvp (_P_DETACH, argv[0], argv);
|
||||
free (argv);
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
util_execv (char * const argv[])
|
||||
{
|
||||
#ifndef WIN32
|
||||
int pid, fd;
|
||||
|
||||
pid = fork ();
|
||||
if (pid == -1)
|
||||
return -1;
|
||||
if (pid == 0)
|
||||
{
|
||||
/* Now close all open file descriptors except stdin, stdout and stderr */
|
||||
for (fd = 3; fd < 1024; fd++) close(fd);
|
||||
execv (argv[0], argv);
|
||||
_exit (0);
|
||||
} else
|
||||
{
|
||||
return pid;
|
||||
}
|
||||
#else
|
||||
spawnv (_P_DETACH, argv[0], argv);
|
||||
return 0;
|
||||
#endif
|
||||
g_spawn_command_line_async (cmd, NULL);
|
||||
}
|
||||
|
||||
unsigned long
|
||||
@@ -1872,7 +1526,7 @@ canonalize_key (char *key)
|
||||
}
|
||||
|
||||
int
|
||||
portable_mode ()
|
||||
portable_mode (void)
|
||||
{
|
||||
#ifdef WIN32
|
||||
if ((_access( "portable-mode", 0 )) != -1)
|
||||
@@ -1889,11 +1543,12 @@ portable_mode ()
|
||||
}
|
||||
|
||||
int
|
||||
unity_mode ()
|
||||
unity_mode (void)
|
||||
{
|
||||
#ifdef G_OS_UNIX
|
||||
const char *env = g_getenv("XDG_CURRENT_DESKTOP");
|
||||
if (env && strcmp (env, "Unity") == 0)
|
||||
if (env && (strcmp (env, "Unity") == 0
|
||||
|| strcmp (env, "Pantheon") == 0))
|
||||
return 1;
|
||||
#endif
|
||||
return 0;
|
||||
@@ -2016,7 +1671,7 @@ encode_sasl_pass_blowfish (char *user, char *pass, char *data)
|
||||
memset (encrypted_pass, 0, pass_len);
|
||||
plain_pass = (char*)malloc (pass_len);
|
||||
memset (plain_pass, 0, pass_len);
|
||||
memcpy (plain_pass, pass, pass_len);
|
||||
memcpy (plain_pass, pass, strlen(pass));
|
||||
out_ptr = (char*)encrypted_pass;
|
||||
in_ptr = (char*)plain_pass;
|
||||
|
||||
|
||||
+3
-5
@@ -37,7 +37,6 @@
|
||||
|
||||
extern const unsigned char rfc_tolowertab[];
|
||||
|
||||
int my_poptParseArgvString(const char * s, int * argcPtr, char *** argvPtr);
|
||||
char *expand_homedir (char *file);
|
||||
void path_part (char *file, char *path, int pathlen);
|
||||
int match (const char *mask, const char *string);
|
||||
@@ -50,8 +49,7 @@ char *nocasestrstr (const char *text, const char *tofind);
|
||||
char *country (char *);
|
||||
void country_search (char *pattern, void *ud, void (*print)(void *, char *, ...));
|
||||
char *get_sys_str (int with_cpu);
|
||||
int util_exec (const char *cmd);
|
||||
int util_execv (char * const argv[]);
|
||||
void util_exec (const char *cmd);
|
||||
#define STRIP_COLOR 1
|
||||
#define STRIP_ATTRIB 2
|
||||
#define STRIP_HIDDEN 4
|
||||
@@ -75,8 +73,8 @@ guint32 str_hash (const char *key);
|
||||
guint32 str_ihash (const unsigned char *key);
|
||||
void safe_strcpy (char *dest, const char *src, int bytes_left);
|
||||
void canonalize_key (char *key);
|
||||
int portable_mode ();
|
||||
int unity_mode ();
|
||||
int portable_mode (void);
|
||||
int unity_mode (void);
|
||||
char *encode_sasl_pass_plain (char *user, char *pass);
|
||||
char *encode_sasl_pass_blowfish (char *user, char *pass, char *data);
|
||||
char *encode_sasl_pass_aes (char *user, char *pass, char *data);
|
||||
|
||||
@@ -30,7 +30,8 @@ hexchat_SOURCES = ascii.c banlist.c chanlist.c chanview.c custom-list.c \
|
||||
dccgui.c editlist.c fe-gtk.c fkeys.c gtkutil.c ignoregui.c joind.c menu.c \
|
||||
maingui.c notifygui.c palette.c pixmaps.c plugin-tray.c $(plugingui_c) \
|
||||
rawlog.c resources.c servlistgui.c setup.c $(iso_codes_c) \
|
||||
sexy-spell-entry.c textgui.c urlgrab.c userlistgui.c xtext.c
|
||||
sslalert.c sexy-spell-entry.c textgui.c urlgrab.c userlistgui.c xtext.c
|
||||
hexchat_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_builddir)/src/common
|
||||
|
||||
resources.c: ../../data/hexchat.gresource.xml $(shell $(GLIB_COMPILE_RESOURCES) --sourcedir=../../data --generate-dependencies ../../data/hexchat.gresource.xml)
|
||||
$(AM_V_GEN) $(GLIB_COMPILE_RESOURCES) --target=$@ --sourcedir=../../data --generate-source $<
|
||||
resources.c: $(top_srcdir)/data/hexchat.gresource.xml $(shell $(GLIB_COMPILE_RESOURCES) --sourcedir=$(top_srcdir)/data --generate-dependencies $(top_srcdir)/data/hexchat.gresource.xml)
|
||||
$(AM_V_GEN) $(GLIB_COMPILE_RESOURCES) --target=$@ --sourcedir=$(top_srcdir)/data --generate-source $<
|
||||
|
||||
@@ -239,6 +239,9 @@ banlist_sensitize (banlist_info *banl)
|
||||
int checkable, i;
|
||||
gboolean is_op = FALSE;
|
||||
|
||||
if (banl->sess->me == NULL)
|
||||
return;
|
||||
|
||||
/* FIXME: More access levels than these can unban */
|
||||
if (banl->sess->me->op || banl->sess->me->hop)
|
||||
is_op = TRUE;
|
||||
@@ -283,7 +286,7 @@ banlist_sensitize (banlist_info *banl)
|
||||
else
|
||||
{
|
||||
gtk_widget_set_sensitive (banl->but_clear, FALSE);
|
||||
gtk_widget_set_sensitive (banl->but_crop, TRUE);
|
||||
gtk_widget_set_sensitive (banl->but_crop, banl->line_ct == banl->select_ct? FALSE: TRUE);
|
||||
gtk_widget_set_sensitive (banl->but_remove, TRUE);
|
||||
}
|
||||
}
|
||||
@@ -410,7 +413,7 @@ banlist_select_changed (GtkWidget *item, banlist_info *banl)
|
||||
else
|
||||
{
|
||||
list = gtk_tree_selection_get_selected_rows (GTK_TREE_SELECTION (item), NULL);
|
||||
banl->select_ct = list? 1: 0;
|
||||
banl->select_ct = g_list_length (list);
|
||||
g_list_foreach (list, (GFunc) gtk_tree_path_free, NULL);
|
||||
g_list_free (list);
|
||||
}
|
||||
@@ -426,7 +429,6 @@ banlist_do_refresh (banlist_info *banl)
|
||||
session *sess = banl->sess;
|
||||
char tbuf[256];
|
||||
int i;
|
||||
char *tbufp;
|
||||
|
||||
banlist_sensitize (banl);
|
||||
|
||||
@@ -444,14 +446,12 @@ banlist_do_refresh (banlist_info *banl)
|
||||
banl->pending = banl->checked;
|
||||
if (banl->pending)
|
||||
{
|
||||
tbufp = tbuf + g_snprintf (tbuf, sizeof tbuf, "quote mode %s +", sess->channel);
|
||||
for (i = 0; i < MODE_CT; i++)
|
||||
if (banl->pending & 1<<i)
|
||||
{
|
||||
*tbufp++ = modes[i].letter;
|
||||
g_snprintf (tbuf, sizeof tbuf, "quote mode %s +%c", sess->channel, modes[i].letter);
|
||||
handle_command (sess, tbuf, FALSE);
|
||||
}
|
||||
*tbufp = 0;
|
||||
handle_command (sess, tbuf, FALSE);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -53,7 +53,6 @@ typedef struct banlist_info_s {
|
||||
int current; /* index of currently processing mode */
|
||||
int line_ct; /* count of presented lines */
|
||||
int select_ct; /* count of selected lines */
|
||||
/* Not really; 1 if any are selected otherwise 0 */
|
||||
GtkWidget *window;
|
||||
GtkWidget *treeview;
|
||||
GtkWidget *checkboxes[MODE_CT];
|
||||
|
||||
@@ -62,12 +62,13 @@ cv_tabs_sizerequest (GtkWidget *viewport, GtkRequisition *requisition, chanview
|
||||
static void
|
||||
cv_tabs_sizealloc (GtkWidget *widget, GtkAllocation *allocation, chanview *cv)
|
||||
{
|
||||
GdkWindow *parent_win;
|
||||
GtkAdjustment *adj;
|
||||
GtkWidget *inner;
|
||||
gint viewport_size;
|
||||
|
||||
inner = ((tabview *)cv)->inner;
|
||||
GdkWindow *parent_win = gtk_widget_get_window (gtk_widget_get_parent (inner));
|
||||
parent_win = gtk_widget_get_window (gtk_widget_get_parent (inner));
|
||||
|
||||
if (cv->vertical)
|
||||
{
|
||||
|
||||
+73
-32
@@ -656,10 +656,11 @@ void
|
||||
fe_beep (session *sess)
|
||||
{
|
||||
#ifdef WIN32
|
||||
if (!PlaySound ("Notification.IM", NULL, SND_ALIAS|SND_ASYNC))
|
||||
/* Play the "Instant Message Notification" system sound
|
||||
*/
|
||||
if (!PlaySoundW (L"Notification.IM", NULL, SND_ALIAS | SND_ASYNC))
|
||||
{
|
||||
/* This is really just a fallback attempt, may or may not work on new Windows releases, especially on x64.
|
||||
* You should set up the "Instant Message Notification" system sound instead, supported on Vista and up.
|
||||
/* The user does not have the "Instant Message Notification" sound set. Fall back to system beep.
|
||||
*/
|
||||
Beep (1000, 50);
|
||||
}
|
||||
@@ -983,23 +984,84 @@ fe_set_inputbox_contents (session *sess, char *text)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __APPLE__
|
||||
static char *
|
||||
url_escape_hostname (const char *url)
|
||||
{
|
||||
char *host_start, *host_end, *ret, *hostname;
|
||||
|
||||
host_start = strstr (url, "://");
|
||||
if (host_start != NULL)
|
||||
{
|
||||
*host_start = '\0';
|
||||
host_start += 3;
|
||||
host_end = strchr (host_start, '/');
|
||||
|
||||
if (host_end != NULL)
|
||||
{
|
||||
*host_end = '\0';
|
||||
host_end++;
|
||||
}
|
||||
|
||||
hostname = g_hostname_to_ascii (host_start);
|
||||
if (host_end != NULL)
|
||||
ret = g_strdup_printf ("%s://%s/%s", url, hostname, host_end);
|
||||
else
|
||||
ret = g_strdup_printf ("%s://%s", url, hostname);
|
||||
|
||||
g_free (hostname);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return g_strdup (url);
|
||||
}
|
||||
|
||||
static void
|
||||
osx_show_uri (const char *url)
|
||||
{
|
||||
char *escaped_url, *encoded_url, *open, *cmd;
|
||||
|
||||
escaped_url = url_escape_hostname (url);
|
||||
encoded_url = g_filename_from_utf8 (escaped_url, -1, NULL, NULL, NULL);
|
||||
if (encoded_url)
|
||||
{
|
||||
open = g_find_program_in_path ("open");
|
||||
cmd = g_strjoin (" ", open, encoded_url, NULL);
|
||||
|
||||
hexchat_exec (cmd);
|
||||
|
||||
g_free (encoded_url);
|
||||
g_free (cmd);
|
||||
}
|
||||
|
||||
g_free (escaped_url);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static void
|
||||
fe_open_url_inner (const char *url)
|
||||
{
|
||||
#ifdef WIN32
|
||||
ShellExecute (0, "open", url, NULL, NULL, SW_SHOWNORMAL);
|
||||
#elif defined __APPLE__
|
||||
/* on Mac you can just 'open http://foo.bar/' */
|
||||
gchar open[512];
|
||||
g_snprintf (open, sizeof(open), "%s %s", g_find_program_in_path ("open"), url, NULL);
|
||||
hexchat_exec (open);
|
||||
gunichar2 *url_utf16 = g_utf8_to_utf16 (url, -1, NULL, NULL, NULL);
|
||||
|
||||
if (url_utf16 == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ShellExecuteW (0, L"open", url_utf16, NULL, NULL, SW_SHOWNORMAL);
|
||||
|
||||
g_free (url_utf16);
|
||||
#elif defined(__APPLE__)
|
||||
osx_show_uri (url);
|
||||
#else
|
||||
gtk_show_uri (NULL, url, GDK_CURRENT_TIME, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
fe_open_url_locale (const char *url)
|
||||
void
|
||||
fe_open_url (const char *url)
|
||||
{
|
||||
int url_type = url_check_word (url);
|
||||
char *uri;
|
||||
@@ -1041,27 +1103,6 @@ fe_open_url_locale (const char *url)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
fe_open_url (const char *url)
|
||||
{
|
||||
char *loc;
|
||||
|
||||
if (prefs.utf8_locale)
|
||||
{
|
||||
fe_open_url_locale (url);
|
||||
return;
|
||||
}
|
||||
|
||||
/* the OS expects it in "locale" encoding. This makes it work on
|
||||
unix systems that use ISO-8859-x and Win32. */
|
||||
loc = g_locale_from_utf8 (url, -1, 0, 0, 0);
|
||||
if (loc)
|
||||
{
|
||||
fe_open_url_locale (loc);
|
||||
g_free (loc);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
fe_server_event (server *serv, int type, int arg)
|
||||
{
|
||||
|
||||
+1
-19
@@ -20,11 +20,7 @@
|
||||
#ifndef HEXCHAT_FE_GTK_H
|
||||
#define HEXCHAT_FE_GTK_H
|
||||
|
||||
#ifdef WIN32
|
||||
#include "../../config-win32.h"
|
||||
#else
|
||||
#include "../../config.h"
|
||||
#endif
|
||||
|
||||
#define DISPLAY_NAME "HexChat"
|
||||
|
||||
@@ -32,21 +28,7 @@
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#if defined(ENABLE_NLS) && !defined(_)
|
||||
# include <libintl.h>
|
||||
# define _(x) gettext(x)
|
||||
# ifdef gettext_noop
|
||||
# define N_(String) gettext_noop (String)
|
||||
# else
|
||||
# define N_(String) (String)
|
||||
# endif
|
||||
#endif
|
||||
#if !defined(ENABLE_NLS) && defined(_)
|
||||
# undef _
|
||||
# define N_(String) (String)
|
||||
# define _(x) (x)
|
||||
#endif
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#ifdef HAVE_GTK_MAC
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;$(OwnFlags);%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>$(DepsRoot)\include;$(Glib);$(Gtk);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)..;$(DepsRoot)\include;$(Glib);$(Gtk);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<DisableSpecificWarnings>4244;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||
</ClCompile>
|
||||
@@ -81,7 +81,7 @@
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;_WIN64;_AMD64_;NDEBUG;_WINDOWS;$(OwnFlags);%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>$(DepsRoot)\include;$(Glib);$(Gtk);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)..;$(DepsRoot)\include;$(Glib);$(Gtk);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<DisableSpecificWarnings>4244;4267;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||
</ClCompile>
|
||||
@@ -99,7 +99,7 @@
|
||||
<PreBuildEvent>
|
||||
<Command><![CDATA[
|
||||
SET SOLUTIONDIR=$(SolutionDir)..\
|
||||
powershell -File "$(SolutionDir)..\version-template.ps1" "$(SolutionDir)..\src\fe-gtk\hexchat.rc.tt" "$(SolutionDir)..\src\fe-gtk\hexchat.rc.utf8"
|
||||
powershell -File "$(SolutionDir)..\win32\version-template.ps1" "$(SolutionDir)..\src\fe-gtk\hexchat.rc.tt" "$(SolutionDir)..\src\fe-gtk\hexchat.rc.utf8"
|
||||
REM hexchat.rc needs to be in UCS-2 or Resource Compiler will complain
|
||||
powershell "Get-Content -Encoding UTF8 '$(SolutionDir)..\src\fe-gtk\hexchat.rc.utf8' | Out-File '$(SolutionDir)..\src\fe-gtk\hexchat.rc'; Remove-Item '$(SolutionDir)..\src\fe-gtk\hexchat.rc.utf8'"
|
||||
"$(DepsRoot)\bin\glib-compile-resources.exe" --generate-source --sourcedir "$(DataDir)" --target "$(ProjectDir)resources.c" "$(DataDir)hexchat.gresource.xml"
|
||||
@@ -161,6 +161,7 @@ powershell "Get-Content -Encoding UTF8 '$(SolutionDir)..\src\fe-gtk\hexchat.rc.u
|
||||
<ClCompile Include="setup.c" />
|
||||
<ClCompile Include="sexy-iso-codes.c" />
|
||||
<ClCompile Include="sexy-spell-entry.c" />
|
||||
<ClCompile Include="sslalert.c" />
|
||||
<ClCompile Include="textgui.c" />
|
||||
<ClCompile Include="urlgrab.c" />
|
||||
<ClCompile Include="userlistgui.c" />
|
||||
|
||||
@@ -182,6 +182,9 @@
|
||||
<ClCompile Include="resources.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="sslalert.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Manifest Include="hexchat.exe.manifest">
|
||||
@@ -202,4 +205,4 @@
|
||||
<ItemGroup>
|
||||
<Xml Include="..\..\data\hexchat.gresource.xml" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
||||
+52
-22
@@ -66,48 +66,69 @@ gtkutil_file_req_destroy (GtkWidget * wid, struct file_req *freq)
|
||||
}
|
||||
|
||||
static void
|
||||
gtkutil_check_file (char *file, struct file_req *freq)
|
||||
gtkutil_check_file (char *filename, struct file_req *freq)
|
||||
{
|
||||
struct stat st;
|
||||
int axs = FALSE;
|
||||
char temp[256];
|
||||
|
||||
path_part (file, temp, sizeof (temp));
|
||||
GFile *file = g_file_new_for_path (filename);
|
||||
|
||||
/* check if the file is readable or writable */
|
||||
if (freq->flags & FRF_WRITE)
|
||||
{
|
||||
if (access (temp, W_OK) == 0)
|
||||
axs = TRUE;
|
||||
} else
|
||||
{
|
||||
if (stat (file, &st) != -1)
|
||||
GFile *parent = g_file_get_parent (file);
|
||||
|
||||
GFileInfo *fi = g_file_query_info (parent, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE, G_FILE_QUERY_INFO_NONE, NULL, NULL);
|
||||
if (fi != NULL)
|
||||
{
|
||||
if (!S_ISDIR (st.st_mode) || (freq->flags & FRF_CHOOSEFOLDER))
|
||||
if (g_file_info_get_attribute_boolean (fi, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE))
|
||||
{
|
||||
axs = TRUE;
|
||||
}
|
||||
|
||||
g_object_unref (fi);
|
||||
}
|
||||
|
||||
g_object_unref (parent);
|
||||
}
|
||||
else
|
||||
{
|
||||
GFileInfo *fi = g_file_query_info (file, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE, G_FILE_QUERY_INFO_NONE, NULL, NULL);
|
||||
|
||||
if (fi != NULL)
|
||||
{
|
||||
if (g_file_info_get_file_type (fi) != G_FILE_TYPE_DIRECTORY || (freq->flags & FRF_CHOOSEFOLDER))
|
||||
{
|
||||
axs = TRUE;
|
||||
}
|
||||
|
||||
g_object_unref (fi);
|
||||
}
|
||||
}
|
||||
|
||||
g_object_unref (file);
|
||||
|
||||
if (axs)
|
||||
{
|
||||
char *utf8_file;
|
||||
/* convert to UTF8. It might be converted back to locale by
|
||||
server.c's g_convert */
|
||||
utf8_file = hexchat_filename_to_utf8 (file, -1, NULL, NULL, NULL);
|
||||
if (utf8_file)
|
||||
char *filename_utf8 = g_filename_to_utf8 (filename, -1, NULL, NULL, NULL);
|
||||
if (filename_utf8 != NULL)
|
||||
{
|
||||
freq->callback (freq->userdata, utf8_file);
|
||||
g_free (utf8_file);
|
||||
} else
|
||||
freq->callback (freq->userdata, filename_utf8);
|
||||
g_free (filename_utf8);
|
||||
}
|
||||
else
|
||||
{
|
||||
fe_message ("Filename encoding is corrupt.", FE_MSG_ERROR);
|
||||
}
|
||||
} else
|
||||
}
|
||||
else
|
||||
{
|
||||
if (freq->flags & FRF_WRITE)
|
||||
{
|
||||
fe_message (_("Cannot write to that file."), FE_MSG_ERROR);
|
||||
}
|
||||
else
|
||||
{
|
||||
fe_message (_("Cannot read that file."), FE_MSG_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,12 +149,21 @@ gtkutil_file_req_done (GtkWidget * wid, struct file_req *freq)
|
||||
}
|
||||
if (files)
|
||||
g_slist_free (files);
|
||||
} else
|
||||
}
|
||||
else
|
||||
{
|
||||
if (freq->flags & FRF_CHOOSEFOLDER)
|
||||
gtkutil_check_file (gtk_file_chooser_get_current_folder (fs), freq);
|
||||
{
|
||||
gchar *filename = gtk_file_chooser_get_current_folder (fs);
|
||||
gtkutil_check_file (filename, freq);
|
||||
g_free (filename);
|
||||
}
|
||||
else
|
||||
{
|
||||
gchar *filename = gtk_file_chooser_get_filename (fs);
|
||||
gtkutil_check_file (gtk_file_chooser_get_filename (fs), freq);
|
||||
g_free (filename);
|
||||
}
|
||||
}
|
||||
|
||||
/* this should call the "destroy" cb, where we free(freq) */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#include <winver.h>
|
||||
#include "../../config-win32.h"
|
||||
#include "../../config.h"
|
||||
|
||||
#define COMMA_VERSION <#= [string]::Join(',', $versionParts) #>,0
|
||||
|
||||
|
||||
@@ -441,7 +441,8 @@ mg_windowstate_cb (GtkWindow *wid, GdkEventWindowState *event, gpointer userdata
|
||||
{
|
||||
if ((event->changed_mask & GDK_WINDOW_STATE_ICONIFIED) &&
|
||||
(event->new_window_state & GDK_WINDOW_STATE_ICONIFIED) &&
|
||||
prefs.hex_gui_tray_minimize && !unity_mode ())
|
||||
prefs.hex_gui_tray_minimize && prefs.hex_gui_tray &&
|
||||
!unity_mode ())
|
||||
{
|
||||
tray_toggle_visibility (TRUE);
|
||||
gtk_window_deiconify (wid);
|
||||
|
||||
+14
-11
@@ -403,8 +403,10 @@ toggle_cb (GtkWidget *item, char *pref_name)
|
||||
static int
|
||||
is_in_path (char *cmd)
|
||||
{
|
||||
char *prog = strdup (cmd + 1); /* 1st char is "!" */
|
||||
char *space, *path, *orig;
|
||||
char *prog = g_strdup (cmd + 1); /* 1st char is "!" */
|
||||
char *path, *orig;
|
||||
char **argv;
|
||||
int argc;
|
||||
|
||||
orig = prog; /* save for free()ing */
|
||||
/* special-case these default entries. */
|
||||
@@ -413,16 +415,17 @@ is_in_path (char *cmd)
|
||||
/* don't check for gnome-terminal, but the thing it's executing! */
|
||||
prog += 18;
|
||||
|
||||
space = strchr (prog, ' '); /* this isn't 100% but good enuf */
|
||||
if (space)
|
||||
*space = 0;
|
||||
|
||||
path = g_find_program_in_path (prog);
|
||||
if (path)
|
||||
if (g_shell_parse_argv (prog, &argc, &argv, NULL))
|
||||
{
|
||||
g_free (path);
|
||||
g_free (orig);
|
||||
return 1;
|
||||
path = g_find_program_in_path (argv[0]);
|
||||
if (path)
|
||||
{
|
||||
g_free (path);
|
||||
g_free (orig);
|
||||
g_strfreev (argv);
|
||||
return 1;
|
||||
}
|
||||
g_strfreev (argv);
|
||||
}
|
||||
|
||||
g_free (orig);
|
||||
|
||||
@@ -186,9 +186,10 @@ fe_tray_set_balloon (const char *title, const char *text)
|
||||
|
||||
if (!notify_is_initted())
|
||||
{
|
||||
GList* server_caps;
|
||||
notify_init(PACKAGE_NAME);
|
||||
|
||||
GList* server_caps = notify_get_server_caps ();
|
||||
server_caps = notify_get_server_caps ();
|
||||
if (g_list_find_custom (server_caps, "body-markup", (GCompareFunc)strcmp))
|
||||
{
|
||||
notify_text_strip_flags |= STRIP_ESCMARKUP;
|
||||
|
||||
+2
-16
@@ -161,11 +161,7 @@ plugingui_load (void)
|
||||
sub_dir = g_build_filename (get_xdir(), "addons", NULL);
|
||||
|
||||
gtkutil_file_req (_("Select a Plugin or Script to load"), plugingui_load_cb, current_sess,
|
||||
#ifdef WIN32
|
||||
sub_dir, "*.dll;*.lua;*.pl;*.py;*.tcl;*.js", FRF_FILTERISINITIAL|FRF_EXTENSIONS);
|
||||
#else
|
||||
sub_dir, "*.so;*.lua;*.pl;*.py;*.tcl;*.js", FRF_FILTERISINITIAL|FRF_EXTENSIONS);
|
||||
#endif
|
||||
sub_dir, "*."G_MODULE_SUFFIX";*.lua;*.pl;*.py;*.tcl;*.js", FRF_FILTERISINITIAL|FRF_EXTENSIONS);
|
||||
|
||||
g_free (sub_dir);
|
||||
}
|
||||
@@ -179,7 +175,6 @@ plugingui_loadbutton_cb (GtkWidget * wid, gpointer unused)
|
||||
static void
|
||||
plugingui_unload (GtkWidget * wid, gpointer unused)
|
||||
{
|
||||
int len;
|
||||
char *modname, *file, *buf;
|
||||
GtkTreeView *view;
|
||||
GtkTreeIter iter;
|
||||
@@ -189,16 +184,7 @@ plugingui_unload (GtkWidget * wid, gpointer unused)
|
||||
FILE_COLUMN, &file, -1))
|
||||
return;
|
||||
|
||||
len = strlen (file);
|
||||
#ifdef WIN32
|
||||
if (len > 4 && g_ascii_strcasecmp (file + len - 4, ".dll") == 0)
|
||||
#else
|
||||
#if defined(__hpux)
|
||||
if (len > 3 && g_ascii_strcasecmp (file + len - 3, ".sl") == 0)
|
||||
#else
|
||||
if (len > 3 && g_ascii_strcasecmp (file + len - 3, ".so") == 0)
|
||||
#endif
|
||||
#endif
|
||||
if (g_str_has_suffix (file, "."G_MODULE_SUFFIX))
|
||||
{
|
||||
if (plugin_kill (modname, FALSE) == 2)
|
||||
fe_message (_("That plugin is refusing to unload.\n"), FE_MSG_ERROR);
|
||||
|
||||
+20
-17
@@ -1526,13 +1526,14 @@ servlist_logintypecombo_cb (GtkComboBox *cb, gpointer *userdata)
|
||||
|
||||
index = gtk_combo_box_get_active (cb); /* starts at 0, returns -1 for invalid selections */
|
||||
|
||||
if (index != -1)
|
||||
{
|
||||
/* The selection is valid. It can be 0, which is the default type, but we need to allow
|
||||
* that so that you can revert from other types. servlist_save() will dump 0 anyway.
|
||||
*/
|
||||
selected_net->logintype = login_types_conf[index];
|
||||
}
|
||||
if (index == -1)
|
||||
return; /* Invalid */
|
||||
|
||||
/* The selection is valid. It can be 0, which is the default type, but we need to allow
|
||||
* that so that you can revert from other types. servlist_save() will dump 0 anyway.
|
||||
*/
|
||||
selected_net->logintype = login_types_conf[index];
|
||||
|
||||
if (login_types_conf[index] == LOGIN_CUSTOM)
|
||||
{
|
||||
gtk_notebook_set_current_page (GTK_NOTEBOOK (userdata), 2); /* FIXME avoid hardcoding? */
|
||||
@@ -1865,33 +1866,35 @@ servlist_open_edit (GtkWidget *parent, ircnet *net)
|
||||
#ifndef USE_OPENSSL
|
||||
gtk_widget_set_sensitive (check, FALSE);
|
||||
#endif
|
||||
#if 0
|
||||
check = servlist_create_check (5, net->flags & FLAG_ALLOW_INVALID, table3, 4, 0, _("Accept invalid SSL certificates"));
|
||||
#ifndef USE_OPENSSL
|
||||
gtk_widget_set_sensitive (check, FALSE);
|
||||
#endif
|
||||
servlist_create_check (1, net->flags & FLAG_USE_GLOBAL, table3, 5, 0, _("Use global user information"));
|
||||
#endif
|
||||
servlist_create_check (1, net->flags & FLAG_USE_GLOBAL, table3, 4, 0, _("Use global user information"));
|
||||
|
||||
edit_entry_nick = servlist_create_entry (table3, _("_Nick name:"), 6, net->nick, &edit_label_nick, 0);
|
||||
edit_entry_nick2 = servlist_create_entry (table3, _("Second choice:"), 7, net->nick2, &edit_label_nick2, 0);
|
||||
edit_entry_real = servlist_create_entry (table3, _("Rea_l name:"), 8, net->real, &edit_label_real, 0);
|
||||
edit_entry_user = servlist_create_entry (table3, _("_User name:"), 9, net->user, &edit_label_user, 0);
|
||||
edit_entry_nick = servlist_create_entry (table3, _("_Nick name:"), 5, net->nick, &edit_label_nick, 0);
|
||||
edit_entry_nick2 = servlist_create_entry (table3, _("Second choice:"), 6, net->nick2, &edit_label_nick2, 0);
|
||||
edit_entry_real = servlist_create_entry (table3, _("Rea_l name:"), 7, net->real, &edit_label_real, 0);
|
||||
edit_entry_user = servlist_create_entry (table3, _("_User name:"), 8, net->user, &edit_label_user, 0);
|
||||
|
||||
label_logintype = gtk_label_new (_("Login method:"));
|
||||
gtk_table_attach (GTK_TABLE (table3), label_logintype, 0, 1, 10, 11, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), SERVLIST_X_PADDING, SERVLIST_Y_PADDING);
|
||||
gtk_table_attach (GTK_TABLE (table3), label_logintype, 0, 1, 9, 10, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), SERVLIST_X_PADDING, SERVLIST_Y_PADDING);
|
||||
gtk_misc_set_alignment (GTK_MISC (label_logintype), 0, 0.5);
|
||||
combobox_logintypes = servlist_create_logintypecombo (notebook);
|
||||
gtk_table_attach (GTK_TABLE (table3), combobox_logintypes, 1, 2, 10, 11, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (GTK_FILL), 4, 2);
|
||||
gtk_table_attach (GTK_TABLE (table3), combobox_logintypes, 1, 2, 9, 10, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (GTK_FILL), 4, 2);
|
||||
|
||||
edit_entry_pass = servlist_create_entry (table3, _("Password:"), 11, net->pass, 0, _("Password used for login. If in doubt, leave blank."));
|
||||
edit_entry_pass = servlist_create_entry (table3, _("Password:"), 10, net->pass, 0, _("Password used for login. If in doubt, leave blank."));
|
||||
gtk_entry_set_visibility (GTK_ENTRY (edit_entry_pass), FALSE);
|
||||
if (selected_net && selected_net->logintype == LOGIN_SASLEXTERNAL)
|
||||
gtk_widget_set_sensitive (edit_entry_pass, FALSE);
|
||||
|
||||
label34 = gtk_label_new (_("Character set:"));
|
||||
gtk_table_attach (GTK_TABLE (table3), label34, 0, 1, 12, 13, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), SERVLIST_X_PADDING, SERVLIST_Y_PADDING);
|
||||
gtk_table_attach (GTK_TABLE (table3), label34, 0, 1, 11, 12, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), SERVLIST_X_PADDING, SERVLIST_Y_PADDING);
|
||||
gtk_misc_set_alignment (GTK_MISC (label34), 0, 0.5);
|
||||
comboboxentry_charset = servlist_create_charsetcombo ();
|
||||
gtk_table_attach (GTK_TABLE (table3), comboboxentry_charset, 1, 2, 12, 13, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (GTK_FILL), 4, 2);
|
||||
gtk_table_attach (GTK_TABLE (table3), comboboxentry_charset, 1, 2, 11, 12, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (GTK_FILL), 4, 2);
|
||||
|
||||
|
||||
/* Rule and Close button */
|
||||
|
||||
+1
-1
@@ -2168,7 +2168,7 @@ setup_apply (struct hexchatprefs *pr)
|
||||
" restart to take full effect."), FE_MSG_WARN);
|
||||
|
||||
#ifndef WIN32
|
||||
if (prefs.hex_dcc_auto_recv)
|
||||
if (prefs.hex_dcc_auto_recv == 2) /* Auto */
|
||||
{
|
||||
if (!strcmp ((char *)g_get_home_dir (), prefs.hex_dcc_dir))
|
||||
{
|
||||
|
||||
@@ -22,12 +22,7 @@
|
||||
#include "sexy-iso-codes.h"
|
||||
#include <libintl.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
#include "../../config-win32.h"
|
||||
#else
|
||||
#include "../../config.h"
|
||||
#endif
|
||||
|
||||
#define ISO_639_DOMAIN "iso_639"
|
||||
#define ISO_3166_DOMAIN "iso_3166"
|
||||
|
||||
@@ -153,11 +153,8 @@ initialize_enchant ()
|
||||
GModule *enchant;
|
||||
gpointer funcptr;
|
||||
|
||||
#ifdef WIN32
|
||||
enchant = g_module_open("libenchant.dll", 0);
|
||||
#else
|
||||
enchant = g_module_open("libenchant", 0);
|
||||
#endif
|
||||
|
||||
enchant = g_module_open("libenchant."G_MODULE_SUFFIX, 0);
|
||||
if (enchant == NULL)
|
||||
{
|
||||
#ifndef WIN32
|
||||
@@ -1115,32 +1112,40 @@ entry_strsplit_utf8(GtkEntry *entry, gchar ***set, gint **starts, gint **ends)
|
||||
const PangoLogAttr *log_attrs;
|
||||
const gchar *text;
|
||||
gint n_attrs, n_strings, i, j;
|
||||
PangoLogAttr a;
|
||||
|
||||
layout = gtk_entry_get_layout(GTK_ENTRY(entry));
|
||||
text = gtk_entry_get_text(GTK_ENTRY(entry));
|
||||
log_attrs = pango_layout_get_log_attrs_readonly (layout, &n_attrs);
|
||||
|
||||
/* Find how many words we have */
|
||||
n_strings = 0;
|
||||
for (i = 0; i < n_attrs; i++)
|
||||
if (log_attrs[i].is_word_start)
|
||||
for (i = 0, n_strings = 0; i < n_attrs; i++)
|
||||
{
|
||||
a = log_attrs[i];
|
||||
if (a.is_word_start && a.is_word_boundary)
|
||||
n_strings++;
|
||||
}
|
||||
|
||||
*set = g_new0(gchar *, n_strings + 1);
|
||||
*starts = g_new0(gint, n_strings);
|
||||
*ends = g_new0(gint, n_strings);
|
||||
|
||||
/* Copy out strings */
|
||||
for (i = 0, j = 0; i < n_attrs; i++) {
|
||||
if (log_attrs[i].is_word_start) {
|
||||
for (i = 0, j = 0; i < n_attrs; i++)
|
||||
{
|
||||
a = log_attrs[i];
|
||||
if (a.is_word_start && a.is_word_boundary)
|
||||
{
|
||||
gint cend, bytes;
|
||||
gchar *start;
|
||||
|
||||
/* Find the end of this string */
|
||||
cend = i;
|
||||
while ((!log_attrs[cend].is_word_end || !log_attrs[cend].is_word_boundary)
|
||||
&& !log_attrs[cend].is_white)
|
||||
cend++;
|
||||
for (cend = i; cend < n_attrs; cend++)
|
||||
{
|
||||
a = log_attrs[cend];
|
||||
if (a.is_word_end && a.is_word_boundary)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Copy sub-string */
|
||||
start = g_utf8_offset_to_pointer(text, i);
|
||||
|
||||
@@ -0,0 +1,144 @@
|
||||
/* X-Chat
|
||||
* Copyright (C) 1998 Peter Zelezny.
|
||||
*
|
||||
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "fe-gtk.h"
|
||||
#include <gtk/gtk.h>
|
||||
#include "../common/hexchat.h"
|
||||
#include "../common/util.h"
|
||||
#include "palette.h"
|
||||
#include "pixmaps.h"
|
||||
#include "gtkutil.h"
|
||||
|
||||
void (*server_callback)(int, void *) = 0;
|
||||
|
||||
static void
|
||||
sslalert_cb (GtkDialog *dialog, gint response, gpointer data)
|
||||
{
|
||||
if (response < 0) /* Such as window deleted */
|
||||
server_callback (SSLALERT_RESPONSE_ABORT, data);
|
||||
else
|
||||
server_callback (response, data);
|
||||
|
||||
gtk_widget_destroy (GTK_WIDGET (dialog));
|
||||
}
|
||||
|
||||
void
|
||||
fe_sslalert_open (struct server *serv, void (*callback)(int, void *), void *callback_data)
|
||||
{
|
||||
GtkWidget *sslalert;
|
||||
GtkWidget *wid;
|
||||
GtkWidget *dialog_vbox;
|
||||
GtkWidget *expander;
|
||||
GtkWidget *hbox1, *vbox1, *vbox2;
|
||||
GtkWidget *img_vbox;
|
||||
char *cert_buf;
|
||||
char buf[256];
|
||||
char buf2[256];
|
||||
|
||||
server_callback = callback;
|
||||
|
||||
sslalert = gtk_dialog_new ();
|
||||
gtk_window_set_title (GTK_WINDOW (sslalert), _ (DISPLAY_NAME": Security Alert"));
|
||||
gtk_window_set_type_hint (GTK_WINDOW (sslalert), GDK_WINDOW_TYPE_HINT_DIALOG);
|
||||
gtk_window_set_position (GTK_WINDOW (sslalert), GTK_WIN_POS_CENTER_ON_PARENT);
|
||||
gtk_window_set_transient_for (GTK_WINDOW (sslalert), GTK_WINDOW (serv->front_session->gui->window));
|
||||
gtk_window_set_modal (GTK_WINDOW (sslalert), TRUE);
|
||||
gtk_window_set_resizable (GTK_WINDOW (sslalert), FALSE);
|
||||
|
||||
dialog_vbox = gtk_dialog_get_content_area (GTK_DIALOG (sslalert));
|
||||
|
||||
vbox1 = gtk_vbox_new (FALSE, 0);
|
||||
gtk_box_pack_start (GTK_BOX (dialog_vbox), vbox1, TRUE, TRUE, 0);
|
||||
|
||||
hbox1 = gtk_hbox_new (FALSE, 0);
|
||||
gtk_box_pack_start (GTK_BOX (vbox1), hbox1, TRUE, TRUE, 0);
|
||||
|
||||
img_vbox = gtk_vbox_new (FALSE, 10);
|
||||
gtk_container_set_border_width (GTK_CONTAINER (img_vbox), 6);
|
||||
gtk_box_pack_start (GTK_BOX (hbox1), img_vbox, TRUE, TRUE, 0);
|
||||
|
||||
wid = gtk_image_new_from_stock (GTK_STOCK_DIALOG_AUTHENTICATION, GTK_ICON_SIZE_DIALOG);
|
||||
gtk_box_pack_start (GTK_BOX (img_vbox), wid, FALSE, TRUE, 24);
|
||||
gtk_misc_set_alignment (GTK_MISC (wid), 0.5f, 0.06f);
|
||||
|
||||
vbox2 = gtk_vbox_new (FALSE, 10);
|
||||
gtk_container_set_border_width (GTK_CONTAINER (vbox2), 6);
|
||||
gtk_box_pack_start (GTK_BOX (hbox1), vbox2, TRUE, TRUE, 0);
|
||||
|
||||
snprintf (buf2, sizeof (buf2), _ ("Connecting to %s (+%d)"),
|
||||
serv->hostname, serv->port);
|
||||
snprintf (buf, sizeof (buf), "\n<b>%s</b>", buf2);
|
||||
wid = gtk_label_new (buf);
|
||||
gtk_box_pack_start (GTK_BOX (vbox2), wid, FALSE, FALSE, 0);
|
||||
gtk_label_set_use_markup (GTK_LABEL (wid), TRUE);
|
||||
gtk_misc_set_alignment (GTK_MISC (wid), 0, 0.5);
|
||||
|
||||
wid = gtk_label_new (_ ("This server has presented an invalid certificate, and is self-signed, expired, or has another problem."));
|
||||
gtk_box_pack_start (GTK_BOX (vbox2), wid, FALSE, FALSE, 0);
|
||||
gtk_label_set_line_wrap (GTK_LABEL (wid), TRUE);
|
||||
gtk_misc_set_alignment (GTK_MISC (wid), 0, 0.5);
|
||||
|
||||
wid = gtk_label_new (_ ("If you are certain that your connection is not being tampered with, you can continue and your connection will be secure."));
|
||||
gtk_box_pack_start (GTK_BOX (vbox2), wid, FALSE, FALSE, 0);
|
||||
gtk_label_set_line_wrap (GTK_LABEL (wid), TRUE);
|
||||
gtk_misc_set_alignment (GTK_MISC (wid), 0, 0.5);
|
||||
|
||||
if (serv->cert_info)
|
||||
{
|
||||
char *subject;
|
||||
char *issuer;
|
||||
|
||||
expander = gtk_expander_new (_ ("More details:"));
|
||||
gtk_widget_set_can_focus (expander, FALSE);
|
||||
gtk_container_set_border_width (GTK_CONTAINER (expander), 10);
|
||||
gtk_box_pack_start (GTK_BOX (vbox1), expander, FALSE, FALSE, 0);
|
||||
|
||||
wid = gtk_label_new (NULL);
|
||||
gtk_label_set_use_markup (GTK_LABEL (wid), TRUE);
|
||||
gtk_label_set_justify (GTK_LABEL (wid), GTK_JUSTIFY_LEFT);
|
||||
gtk_container_add (GTK_CONTAINER (expander), wid);
|
||||
|
||||
issuer = g_strjoinv ("\n\t\t", serv->cert_info->issuer_word);
|
||||
subject = g_strjoinv ("\n\t\t", serv->cert_info->subject_word);
|
||||
cert_buf = g_markup_printf_escaped ("<b>Issuer:</b>\t%s\n\n"\
|
||||
"<b>Subject:</b> %s\n\n"\
|
||||
"<b>Valid:</b>\tAfter: %s\n\t\tBefore: %s\n\n"\
|
||||
"<b>Algorithm:</b> %s (%d bits)",
|
||||
issuer, subject,
|
||||
serv->cert_info->notbefore, serv->cert_info->notafter,
|
||||
serv->cert_info->algorithm, serv->cert_info->algorithm_bits);
|
||||
|
||||
gtk_label_set_markup (GTK_LABEL (wid), cert_buf);
|
||||
|
||||
g_free (cert_buf);
|
||||
g_free (issuer);
|
||||
g_free (subject);
|
||||
}
|
||||
|
||||
gtk_dialog_add_buttons (GTK_DIALOG (sslalert), _ ("Abort"), SSLALERT_RESPONSE_ABORT,
|
||||
_("Accept Once"), SSLALERT_RESPONSE_ACCEPT,
|
||||
_("Always Accept"), SSLALERT_RESPONSE_SAVE, NULL);
|
||||
gtk_dialog_set_default_response (GTK_DIALOG (sslalert), SSLALERT_RESPONSE_ABORT);
|
||||
|
||||
g_signal_connect (G_OBJECT (sslalert), "response", G_CALLBACK (sslalert_cb), callback_data);
|
||||
|
||||
gtk_widget_show_all (sslalert);
|
||||
}
|
||||
+84
-84
@@ -31,12 +31,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
#ifdef WIN32
|
||||
#include "../../config-win32.h"
|
||||
#else
|
||||
#include "../../config.h"
|
||||
#endif
|
||||
|
||||
#include "../common/hexchat.h"
|
||||
#include "../common/fe.h"
|
||||
#include "../common/util.h"
|
||||
@@ -143,6 +138,7 @@ static void gtk_xtext_search_textentry_del (xtext_buffer *, textentry *);
|
||||
static void gtk_xtext_search_textentry_fini (gpointer, gpointer);
|
||||
static void gtk_xtext_search_fini (xtext_buffer *);
|
||||
static gboolean gtk_xtext_search_init (xtext_buffer *buf, const gchar *text, gtk_xtext_search_flags flags, GError **perr);
|
||||
static char * gtk_xtext_get_word (GtkXText * xtext, int x, int y, textentry ** ret_ent, int *ret_off, int *ret_len, GSList **slp);
|
||||
|
||||
/* Avoid warning messages for this unused function */
|
||||
#if 0
|
||||
@@ -488,7 +484,10 @@ gtk_xtext_adjustment_set (xtext_buffer *buf, int fire_signal)
|
||||
adj->page_increment = adj->page_size;
|
||||
|
||||
if (adj->value > adj->upper - adj->page_size)
|
||||
{
|
||||
buf->scrollbar_down = TRUE;
|
||||
adj->value = adj->upper - adj->page_size;
|
||||
}
|
||||
|
||||
if (adj->value < 0)
|
||||
adj->value = 0;
|
||||
@@ -939,7 +938,7 @@ gtk_xtext_find_x (GtkXText * xtext, int x, textentry * ent, int subline,
|
||||
|
||||
static textentry *
|
||||
gtk_xtext_find_char (GtkXText * xtext, int x, int y, int *off,
|
||||
int *out_of_bounds)
|
||||
int *out_of_bounds, int *ret_subline)
|
||||
{
|
||||
textentry *ent;
|
||||
int line;
|
||||
@@ -957,6 +956,9 @@ gtk_xtext_find_char (GtkXText * xtext, int x, int y, int *off,
|
||||
if (off)
|
||||
*off = gtk_xtext_find_x (xtext, x, ent, subline, line, out_of_bounds);
|
||||
|
||||
if (ret_subline)
|
||||
*ret_subline = subline;
|
||||
|
||||
return ent;
|
||||
}
|
||||
|
||||
@@ -1050,14 +1052,14 @@ gtk_xtext_paint (GtkWidget *widget, GdkRectangle *area)
|
||||
return;
|
||||
}
|
||||
|
||||
ent_start = gtk_xtext_find_char (xtext, area->x, area->y, NULL, NULL);
|
||||
ent_start = gtk_xtext_find_char (xtext, area->x, area->y, NULL, NULL, NULL);
|
||||
if (!ent_start)
|
||||
{
|
||||
xtext_draw_bg (xtext, area->x, area->y, area->width, area->height);
|
||||
goto xit;
|
||||
}
|
||||
ent_end = gtk_xtext_find_char (xtext, area->x + area->width,
|
||||
area->y + area->height, NULL, NULL);
|
||||
area->y + area->height, NULL, NULL, NULL);
|
||||
if (!ent_end)
|
||||
ent_end = xtext->buffer->text_last;
|
||||
|
||||
@@ -1302,84 +1304,95 @@ gtk_xtext_selection_draw (GtkXText * xtext, GdkEventMotion * event, gboolean ren
|
||||
textentry *ent_start;
|
||||
int offset_start;
|
||||
int offset_end;
|
||||
int low_x;
|
||||
int low_y;
|
||||
int high_x;
|
||||
int high_y;
|
||||
int tmp;
|
||||
int subline_start;
|
||||
int subline_end;
|
||||
int oob;
|
||||
int marking_up;
|
||||
int marking_up = FALSE;
|
||||
int len_start;
|
||||
int len_end;
|
||||
|
||||
if (xtext->select_start_y > xtext->select_end_y)
|
||||
{
|
||||
low_x = xtext->select_end_x;
|
||||
low_y = xtext->select_end_y;
|
||||
marking_up = TRUE;
|
||||
high_x = xtext->select_start_x;
|
||||
high_y = xtext->select_start_y;
|
||||
} else
|
||||
{
|
||||
low_x = xtext->select_start_x;
|
||||
low_y = xtext->select_start_y;
|
||||
high_x = xtext->select_end_x;
|
||||
high_y = xtext->select_end_y;
|
||||
marking_up = FALSE;
|
||||
}
|
||||
ent_start = gtk_xtext_find_char (xtext, xtext->select_start_x, xtext->select_start_y, &offset_start, &oob, &subline_start);
|
||||
ent_end = gtk_xtext_find_char (xtext, xtext->select_end_x, xtext->select_end_y, &offset_end, &oob, &subline_end);
|
||||
|
||||
ent_start = gtk_xtext_find_char (xtext, low_x, low_y, &offset_start, &oob);
|
||||
if (!ent_start)
|
||||
if ((!ent_start || !ent_end) && !xtext->buffer->text_last && xtext->adj->value != xtext->buffer->old_value)
|
||||
{
|
||||
if (xtext->adj->value != xtext->buffer->old_value)
|
||||
gtk_xtext_render_page (xtext);
|
||||
gtk_xtext_render_page (xtext);
|
||||
return;
|
||||
}
|
||||
else if (oob)
|
||||
|
||||
if (!ent_start)
|
||||
{
|
||||
offset_start = marking_up == TRUE? 0: xtext->buffer->last_offset_start;
|
||||
ent_start = xtext->buffer->text_last;
|
||||
offset_start = ent_start->str_len;
|
||||
}
|
||||
|
||||
ent_end = gtk_xtext_find_char (xtext, high_x, high_y, &offset_end, &oob);
|
||||
if (!ent_end)
|
||||
{
|
||||
ent_end = xtext->buffer->text_last;
|
||||
if (!ent_end)
|
||||
{
|
||||
if (xtext->adj->value != xtext->buffer->old_value)
|
||||
gtk_xtext_render_page (xtext);
|
||||
return;
|
||||
}
|
||||
offset_end = ent_end->str_len;
|
||||
}
|
||||
else if (oob)
|
||||
|
||||
if ((ent_start != ent_end && xtext->select_start_y > xtext->select_end_y) || /* different entries */
|
||||
(ent_start == ent_end && subline_start > subline_end) || /* different lines */
|
||||
(ent_start == ent_end && subline_start == subline_end && xtext->select_start_x > xtext->select_end_x)) /* marking to the left */
|
||||
{
|
||||
offset_end = marking_up == FALSE? ent_end->str_len: xtext->buffer->last_offset_end;
|
||||
marking_up = TRUE;
|
||||
}
|
||||
|
||||
/* marking less than a complete line? */
|
||||
/* make sure "start" is smaller than "end" (swap them if need be) */
|
||||
if (ent_start == ent_end && offset_start > offset_end)
|
||||
/* word selection */
|
||||
if (xtext->word_select)
|
||||
{
|
||||
tmp = offset_start;
|
||||
/* a word selection cannot be started if the cursor is out of bounds in gtk_xtext_button_press */
|
||||
gtk_xtext_get_word (xtext, xtext->select_start_x, xtext->select_start_y, NULL, &offset_start, &len_start, NULL);
|
||||
|
||||
/* in case the cursor is out of bounds we keep offset_end from gtk_xtext_find_char and fix the length */
|
||||
if (gtk_xtext_get_word (xtext, xtext->select_end_x, xtext->select_end_y, NULL, &offset_end, &len_end, NULL) == NULL)
|
||||
len_end = offset_end == ent_end->str_len? 0: -1; /* -1 for the space, 0 if at the end */
|
||||
|
||||
if (!marking_up)
|
||||
offset_end += len_end;
|
||||
else
|
||||
offset_start += len_start;
|
||||
}
|
||||
/* line/ent selection */
|
||||
else if (xtext->line_select)
|
||||
{
|
||||
offset_start = marking_up? ent_start->str_len: 0;
|
||||
offset_end = marking_up? 0: ent_end->str_len;
|
||||
}
|
||||
|
||||
if (marking_up)
|
||||
{
|
||||
int temp;
|
||||
|
||||
/* ensure ent_start is above ent_end */
|
||||
if (ent_start != ent_end)
|
||||
{
|
||||
ent = ent_start;
|
||||
ent_start = ent_end;
|
||||
ent_end = ent;
|
||||
}
|
||||
|
||||
/* switch offsets as well */
|
||||
temp = offset_start;
|
||||
offset_start = offset_end;
|
||||
offset_end = tmp;
|
||||
offset_end = temp;
|
||||
}
|
||||
|
||||
/* set all the old mark_ fields to -1 */
|
||||
gtk_xtext_selection_clear (xtext->buffer);
|
||||
|
||||
ent_start->mark_start = offset_start;
|
||||
ent_start->mark_end = offset_end;
|
||||
/* set the default values */
|
||||
ent_start->mark_end = ent_start->str_len;
|
||||
ent_end->mark_start = 0;
|
||||
|
||||
/* set the calculated values (this overwrites the default values if we're on the same ent) */
|
||||
ent_start->mark_start = offset_start;
|
||||
ent_end->mark_end = offset_end;
|
||||
|
||||
/* set all the mark_ fields of the ents within the selection */
|
||||
if (ent_start != ent_end)
|
||||
{
|
||||
ent_start->mark_end = ent_start->str_len;
|
||||
if (offset_end != 0)
|
||||
{
|
||||
ent_end->mark_start = 0;
|
||||
ent_end->mark_end = offset_end;
|
||||
}
|
||||
|
||||
/* set all the mark_ fields of the ents within the selection */
|
||||
ent = ent_start->next;
|
||||
while (ent && ent != ent_end)
|
||||
{
|
||||
@@ -1388,11 +1401,6 @@ gtk_xtext_selection_draw (GtkXText * xtext, GdkEventMotion * event, gboolean ren
|
||||
ent = ent->next;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (xtext->mark_stamp)
|
||||
offset_start = 0;
|
||||
}
|
||||
|
||||
if (render)
|
||||
gtk_xtext_selection_render (xtext, ent_start, ent_end);
|
||||
@@ -1527,7 +1535,7 @@ gtk_xtext_get_word (GtkXText * xtext, int x, int y, textentry ** ret_ent,
|
||||
int out_of_bounds = 0;
|
||||
int len_to_offset = 0;
|
||||
|
||||
ent = gtk_xtext_find_char (xtext, x, y, &offset, &out_of_bounds);
|
||||
ent = gtk_xtext_find_char (xtext, x, y, &offset, &out_of_bounds, NULL);
|
||||
if (ent == NULL || out_of_bounds || offset < 0 || offset >= ent->str_len)
|
||||
return NULL;
|
||||
|
||||
@@ -1912,13 +1920,6 @@ gtk_xtext_button_release (GtkWidget * widget, GdkEventButton * event)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (xtext->word_or_line_select)
|
||||
{
|
||||
xtext->word_or_line_select = FALSE;
|
||||
xtext->button_down = FALSE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (event->button == 1)
|
||||
{
|
||||
xtext->button_down = FALSE;
|
||||
@@ -1943,6 +1944,13 @@ gtk_xtext_button_release (GtkWidget * widget, GdkEventButton * event)
|
||||
}
|
||||
}
|
||||
|
||||
if (xtext->word_select || xtext->line_select)
|
||||
{
|
||||
xtext->word_select = FALSE;
|
||||
xtext->line_select = FALSE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (xtext->select_start_x == event->x &&
|
||||
xtext->select_start_y == event->y &&
|
||||
xtext->buffer->last_ent_start)
|
||||
@@ -2003,11 +2011,7 @@ gtk_xtext_button_press (GtkWidget * widget, GdkEventButton * event)
|
||||
ent->mark_start = offset;
|
||||
ent->mark_end = offset + len;
|
||||
gtk_xtext_selection_render (xtext, ent, ent);
|
||||
xtext->word_or_line_select = TRUE;
|
||||
if (prefs.hex_text_autocopy_text)
|
||||
{
|
||||
gtk_xtext_set_clip_owner (GTK_WIDGET (xtext), event);
|
||||
}
|
||||
xtext->word_select = TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
@@ -2022,11 +2026,7 @@ gtk_xtext_button_press (GtkWidget * widget, GdkEventButton * event)
|
||||
ent->mark_start = 0;
|
||||
ent->mark_end = ent->str_len;
|
||||
gtk_xtext_selection_render (xtext, ent, ent);
|
||||
xtext->word_or_line_select = TRUE;
|
||||
if (prefs.hex_text_autocopy_text)
|
||||
{
|
||||
gtk_xtext_set_clip_owner (GTK_WIDGET (xtext), event);
|
||||
}
|
||||
xtext->line_select = TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
@@ -3257,7 +3257,7 @@ gtk_xtext_render_stamp (GtkXText * xtext, textentry * ent,
|
||||
{
|
||||
textentry tmp_ent;
|
||||
int jo, ji, hs;
|
||||
int xsize, y;
|
||||
int xsize, y, emphasis;
|
||||
|
||||
/* trashing ent here, so make a backup first */
|
||||
memcpy (&tmp_ent, ent, sizeof (tmp_ent));
|
||||
@@ -3267,7 +3267,7 @@ gtk_xtext_render_stamp (GtkXText * xtext, textentry * ent,
|
||||
xtext->jump_out_offset = 0;
|
||||
xtext->jump_in_offset = 0;
|
||||
xtext->hilight_start = 0xffff; /* temp disable */
|
||||
int emphasis = 0;
|
||||
emphasis = 0;
|
||||
|
||||
if (xtext->mark_stamp)
|
||||
{
|
||||
|
||||
+2
-1
@@ -216,7 +216,8 @@ struct _GtkXText
|
||||
|
||||
/* various state information */
|
||||
unsigned int moving_separator:1;
|
||||
unsigned int word_or_line_select:1;
|
||||
unsigned int word_select:1;
|
||||
unsigned int line_select:1;
|
||||
unsigned int button_down:1;
|
||||
unsigned int hilighting:1;
|
||||
unsigned int dont_render:1;
|
||||
|
||||
@@ -922,3 +922,8 @@ fe_get_default_font (void)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
void
|
||||
fe_sslalert_open (struct server *serv, void (*callback)(int, void *), void *callback_data)
|
||||
{
|
||||
callback (SSLALERT_RESPONSE_ACCEPT, callback_data);
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;$(OwnFlags);%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>$(DepsRoot)\include;$(Glib);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)..;$(DepsRoot)\include;$(Glib);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
@@ -81,7 +81,7 @@
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;_WIN64;_AMD64_;NDEBUG;_CONSOLE;$(OwnFlags);%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>$(DepsRoot)\include;$(Glib);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)..;$(DepsRoot)\include;$(Glib);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
|
||||
@@ -80,11 +80,6 @@
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<None Include="changelog.url" />
|
||||
<None Include="etc\download.png" />
|
||||
<None Include="etc\gtk-2.0\gtkrc" />
|
||||
<None Include="etc\gtkpref.png" />
|
||||
<None Include="etc\music.png" />
|
||||
<None Include="etc\system.png" />
|
||||
<None Include="readme.url" />
|
||||
<None Include="share\xml\iso-codes\iso_3166.xml" />
|
||||
<None Include="share\xml\iso-codes\iso_639.xml" />
|
||||
|
||||
@@ -1,69 +0,0 @@
|
||||
gtk-icon-sizes = "gtk-menu=13,13:gtk-small-toolbar=16,16:gtk-large-toolbar=24,24:gtk-dnd=32,32"
|
||||
gtk-toolbar-icon-size = small-toolbar
|
||||
|
||||
# disable images in buttons. i've only seen ugly delphi apps use this feature.
|
||||
gtk-button-images = 0
|
||||
|
||||
# enable/disable images in menus. most "stock" microsoft apps don't use these, except sparingly.
|
||||
# the office apps use them heavily, though.
|
||||
gtk-menu-images = 1
|
||||
|
||||
# use the win32 button ordering instead of the GNOME HIG one, where applicable
|
||||
gtk-alternative-button-order = 1
|
||||
|
||||
# use the win32 sort indicators direction, as in Explorer
|
||||
gtk-alternative-sort-arrows = 1
|
||||
|
||||
# Windows users don't expect the PC Speaker beeping at them when they backspace in an empty textview and stuff like that
|
||||
gtk-error-bell = 0
|
||||
|
||||
# hide mnemonic underlines until the Alt key is pressed
|
||||
gtk-auto-mnemonics = 1
|
||||
|
||||
style "msw-default"
|
||||
{
|
||||
GtkWidget::interior-focus = 1
|
||||
GtkOptionMenu::indicator-size = { 9, 5 }
|
||||
GtkOptionMenu::indicator-spacing = { 7, 5, 2, 2 }
|
||||
GtkSpinButton::shadow-type = in
|
||||
|
||||
# Owen and I disagree that these should be themable
|
||||
#GtkUIManager::add-tearoffs = 0
|
||||
#GtkComboBox::add-tearoffs = 0
|
||||
|
||||
GtkComboBox::appears-as-list = 1
|
||||
GtkComboBox::focus-on-click = 0
|
||||
|
||||
GOComboBox::add_tearoffs = 0
|
||||
|
||||
GtkTreeView::allow-rules = 0
|
||||
GtkTreeView::expander-size = 12
|
||||
|
||||
GtkExpander::expander-size = 12
|
||||
|
||||
GtkScrolledWindow::scrollbar_spacing = 1
|
||||
|
||||
GtkSeparatorMenuItem::horizontal-padding = 2
|
||||
|
||||
engine "wimp"
|
||||
{
|
||||
}
|
||||
}
|
||||
class "*" style "msw-default"
|
||||
|
||||
binding "ms-windows-tree-view"
|
||||
{
|
||||
bind "Right" { "expand-collapse-cursor-row" (1,1,0) }
|
||||
bind "Left" { "expand-collapse-cursor-row" (1,0,0) }
|
||||
}
|
||||
|
||||
class "GtkTreeView" binding "ms-windows-tree-view"
|
||||
|
||||
style "msw-combobox-thickness" = "msw-default"
|
||||
{
|
||||
xthickness = 0
|
||||
ythickness = 0
|
||||
}
|
||||
|
||||
widget_class "*TreeView*ComboBox*" style "msw-combobox-thickness"
|
||||
widget_class "*ComboBox*GtkFrame*" style "msw-combobox-thickness"
|
||||
+3
-3
@@ -75,12 +75,12 @@ copy "$(DepsRoot)\bin\pixman-1.dll" "$(HexChatRel)"
|
||||
copy "$(DepsRoot)\bin\ssleay32.dll" "$(HexChatRel)"
|
||||
copy "$(DepsRoot)\bin\zlib1.dll" "$(HexChatRel)"
|
||||
xcopy /q /s /i "$(DepsRoot)\lib\gtk-2.0\i686-pc-vs10\engines" "$(HexChatRel)\lib\gtk-2.0\i686-pc-vs10\engines"
|
||||
xcopy /q /s /i etc "$(HexChatRel)\etc"
|
||||
xcopy /q /s /i share "$(HexChatRel)\share"
|
||||
xcopy /q /s /i "..\..\COPYING" "$(HexChatRel)\"
|
||||
xcopy /q /s /i "..\..\COPYING" "$(HexChatRel)\share\doc\hexchat\"
|
||||
xcopy /q /s /i "$(DepsRoot)\share\doc" "$(HexChatRel)\share\doc"
|
||||
xcopy /q /s /i "$(DepsRoot)\share\themes\MS-Windows" "$(HexChatRel)\share\themes\MS-Windows"
|
||||
xcopy /q /s /i "$(DepsRoot)\lib\enchant\libenchant_myspell.dll" "$(HexChatRel)\lib\enchant\"
|
||||
xcopy /q /s /i "$(HexChatBin)hcchecksum.dll" "$(HexChatRel)\plugins\"
|
||||
copy "$(HexChatBin)hcdns.dll" "$(HexChatRel)\plugins"
|
||||
copy "$(HexChatBin)hcdoat.dll" "$(HexChatRel)\plugins"
|
||||
copy "$(HexChatBin)hcexec.dll" "$(HexChatRel)\plugins"
|
||||
copy "$(HexChatBin)hcfishlim.dll" "$(HexChatRel)\plugins"
|
||||
|
||||
@@ -16,7 +16,7 @@ AppPublisherURL=http://hexchat.github.io
|
||||
AppCopyright=Copyright (C) 1998-2010 Peter Zelezny
|
||||
AppSupportURL=https://github.com/hexchat/hexchat/issues
|
||||
AppUpdatesURL=http://hexchat.github.io/downloads.html
|
||||
LicenseFile=COPYING
|
||||
LicenseFile=share\doc\hexchat\COPYING
|
||||
UninstallDisplayIcon={app}\hexchat.exe
|
||||
UninstallDisplayName=HexChat
|
||||
#if APPARCH == "x64"
|
||||
@@ -46,7 +46,7 @@ ArchitecturesInstallIn64BitMode=x64
|
||||
#else
|
||||
ArchitecturesAllowed=x86 x64
|
||||
#endif
|
||||
MinVersion=6.0
|
||||
MinVersion=6.1
|
||||
WizardImageFile={#PROJECTDIR}wizardimage.bmp
|
||||
WizardSmallImageFile={#PROJECTDIR}wizardsmallimage.bmp
|
||||
SetupIconFile={#PROJECTDIR}..\..\data\icons\hexchat.ico
|
||||
@@ -58,7 +58,6 @@ Name: "custom"; Description: "Custom Installation"; Flags: iscustom
|
||||
|
||||
[Components]
|
||||
Name: "libs"; Description: "HexChat"; Types: normal minimal custom; Flags: fixed
|
||||
Name: "gtktheme"; Description: "GTK+ Theme (Native Windows look)"; Types: normal minimal custom; Flags: disablenouninstallwarning
|
||||
Name: "xctext"; Description: "HexChat-Text"; Types: custom; Flags: disablenouninstallwarning
|
||||
Name: "xtm"; Description: "HexChat Theme Manager"; Types: normal custom; Flags: disablenouninstallwarning
|
||||
Name: "translations"; Description: "Translations"; Types: normal custom; Flags: disablenouninstallwarning
|
||||
@@ -111,9 +110,9 @@ Source: "portable-mode"; DestDir: "{app}"; Tasks: portable
|
||||
Source: "changelog.url"; DestDir: "{app}"; Flags: ignoreversion; Components: libs
|
||||
Source: "readme.url"; DestDir: "{app}"; Flags: ignoreversion; Components: libs
|
||||
Source: "cert.pem"; DestDir: "{app}"; Flags: ignoreversion; Components: libs
|
||||
Source: "etc\gtk-2.0\gtkrc"; DestDir: "{app}\etc\gtk-2.0"; Flags: ignoreversion; Components: gtktheme
|
||||
Source: "share\xml\*"; DestDir: "{app}\share\xml"; Flags: ignoreversion createallsubdirs recursesubdirs; Components: libs
|
||||
Source: "COPYING"; DestDir: "{app}"; Flags: ignoreversion; Components: libs
|
||||
Source: "share\doc\*"; DestDir: "{app}\share\doc"; Flags: ignoreversion createallsubdirs recursesubdirs; Components: libs
|
||||
Source: "share\themes\MS-Windows\*"; DestDir: "{app}\share\themes\MS-Windows"; Flags: ignoreversion createallsubdirs recursesubdirs; Components: libs
|
||||
Source: "share\locale\*"; DestDir: "{app}\share\locale"; Flags: ignoreversion createallsubdirs recursesubdirs; Components: translations
|
||||
|
||||
Source: "atk-1.0.dll"; DestDir: "{app}"; Flags: ignoreversion; Components: libs
|
||||
@@ -246,20 +245,20 @@ begin
|
||||
if(CurPageID = wpReady) then
|
||||
begin
|
||||
idpClearFiles;
|
||||
|
||||
|
||||
if not IsTaskSelected('portable') then
|
||||
begin
|
||||
|
||||
|
||||
#if APPARCH == "x64"
|
||||
REDIST := 'http://dl.hexchat.net/misc/vcredist_2013_x64.exe';
|
||||
PERL := 'http://dl.hexchat.net/misc/perl/Perl%205.20.0%20x64.msi';
|
||||
PY2 := 'http://python.org/ftp/python/2.7.6/python-2.7.6.amd64.msi';
|
||||
PY3 := 'http://python.org/ftp/python/3.4.0/python-3.4.0.amd64.msi';
|
||||
PY2 := 'http://python.org/ftp/python/2.7.8/python-2.7.8.amd64.msi';
|
||||
PY3 := 'http://python.org/ftp/python/3.4.1/python-3.4.1.amd64.msi';
|
||||
#else
|
||||
REDIST := 'http://dl.hexchat.net/misc/vcredist_2013_x86.exe';
|
||||
PERL := 'http://dl.hexchat.net/misc/perl/Perl%205.20.0%20x86.msi';
|
||||
PY2 := 'http://python.org/ftp/python/2.7.6/python-2.7.6.msi';
|
||||
PY3 := 'http://python.org/ftp/python/3.4.0/python-3.4.0.msi';
|
||||
PY2 := 'http://python.org/ftp/python/2.7.8/python-2.7.8.msi';
|
||||
PY3 := 'http://python.org/ftp/python/3.4.1/python-3.4.1.msi';
|
||||
#endif
|
||||
DOTNET := 'http://dl.hexchat.net/misc/dotnet_40.exe';
|
||||
SPELL := 'http://dl.hexchat.net/hexchat/HexChat%20Spelling%20Dictionaries%20r2.exe';
|
||||
@@ -272,15 +271,18 @@ begin
|
||||
|
||||
if IsComponentSelected('spell') and not CheckSpellInstall() then
|
||||
idpAddFile(SPELL, ExpandConstant('{tmp}\spelling-dicts.exe'));
|
||||
|
||||
if IsComponentSelected('langs\perl') and not CheckDLL('perl520.dll') then
|
||||
idpAddFile(PERL, ExpandConstant('{tmp}\perl.msi'));
|
||||
|
||||
if IsComponentSelected('langs\python\python2') and not CheckDLL('python27.dll') then
|
||||
idpAddFile(PY2, ExpandConstant('{tmp}\python.msi'));
|
||||
|
||||
if IsComponentSelected('langs\python\python3') and not CheckDLL('python34.dll') then
|
||||
idpAddFile(PY3, ExpandConstant('{tmp}\python.msi'));
|
||||
|
||||
if not WizardSilent() then
|
||||
begin
|
||||
if IsComponentSelected('langs\perl') and not CheckDLL('perl520.dll') then
|
||||
idpAddFile(PERL, ExpandConstant('{tmp}\perl.msi'));
|
||||
|
||||
if IsComponentSelected('langs\python\python2') and not CheckDLL('python27.dll') then
|
||||
idpAddFile(PY2, ExpandConstant('{tmp}\python.msi'));
|
||||
|
||||
if IsComponentSelected('langs\python\python3') and not CheckDLL('python34.dll') then
|
||||
idpAddFile(PY3, ExpandConstant('{tmp}\python.msi'));
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
@@ -356,7 +358,7 @@ begin
|
||||
sUnInstallString := GetUninstallString();
|
||||
if sUnInstallString <> '' then begin
|
||||
sUnInstallString := RemoveQuotes(sUnInstallString);
|
||||
if Exec(sUnInstallString, '/SILENT /NORESTART /SUPPRESSMSGBOXES','', SW_HIDE, ewWaitUntilTerminated, iResultCode) then
|
||||
if Exec(sUnInstallString, '/VERYSILENT /NORESTART /SUPPRESSMSGBOXES','', SW_HIDE, ewWaitUntilTerminated, iResultCode) then
|
||||
Result := 3
|
||||
else
|
||||
Result := 2;
|
||||
|
||||
@@ -64,7 +64,7 @@
|
||||
<Command>
|
||||
<![CDATA[
|
||||
SET SOLUTIONDIR=$(SolutionDir)..\
|
||||
powershell -File "$(SolutionDir)..\version-template.ps1" "$(SolutionDir)..\win32\installer\hexchat.iss.tt" "$(SolutionDir)..\win32\installer\hexchat.iss"
|
||||
powershell -File "$(SolutionDir)..\win32\version-template.ps1" "$(SolutionDir)..\win32\installer\hexchat.iss.tt" "$(SolutionDir)..\win32\installer\hexchat.iss"
|
||||
del "$(OutDir)hexchat.iss"
|
||||
type hexchat.iss >> "$(OutDir)hexchat.iss"
|
||||
$(IsccPath) /dPROJECTDIR="$(ProjectDir)" /dAPPARCH="$(Platform)" "$(OutDir)hexchat.iss"
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
2.10.0
|
||||
2.10.2
|
||||
Reference in New Issue
Block a user