Compare commits
1 Commits
v2.16.1
...
python-ite
Author | SHA1 | Date | |
---|---|---|---|
cd72f2a55b |
@ -1,19 +0,0 @@
|
||||
# EditorConfig is awesome: http://EditorConfig.org
|
||||
|
||||
# top-most EditorConfig file
|
||||
root = true
|
||||
|
||||
[*.{c,cpp,h,hpp,m}]
|
||||
indent_style = tab
|
||||
indent_size = 4
|
||||
end_of_line = lf
|
||||
|
||||
[*.cs]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
end_of_line = lf
|
||||
|
||||
[{meson.build,meson_options.txt}]
|
||||
indent_size = 2
|
||||
indent_style = space
|
||||
insert_final_newline = true
|
17
.github/workflows/flatpak-build.yml
vendored
@ -1,17 +0,0 @@
|
||||
name: Flatpak Build
|
||||
on: [push, pull_request]
|
||||
jobs:
|
||||
flatpak_build:
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: bilelmoussaoui/flatpak-github-actions:gnome-40
|
||||
options: --privileged
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- uses: bilelmoussaoui/flatpak-github-actions/flatpak-builder@v3
|
||||
with:
|
||||
bundle: hexchat.flatpak
|
||||
manifest-path: flatpak/io.github.Hexchat.json
|
40
.github/workflows/msys-build.yml
vendored
@ -1,40 +0,0 @@
|
||||
name: MSYS2 Build
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
msys2_build:
|
||||
runs-on: windows-latest
|
||||
defaults:
|
||||
run:
|
||||
shell: msys2 {0}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- uses: msys2/setup-msys2@v2
|
||||
with:
|
||||
install: >-
|
||||
mingw-w64-x86_64-gcc
|
||||
mingw-w64-x86_64-pkg-config
|
||||
mingw-w64-x86_64-python3-cffi
|
||||
mingw-w64-x86_64-meson
|
||||
mingw-w64-x86_64-gtk2
|
||||
mingw-w64-x86_64-luajit
|
||||
mingw-w64-x86_64-desktop-file-utils
|
||||
|
||||
- name: Configure
|
||||
run: >-
|
||||
meson build
|
||||
-Dtext-frontend=true
|
||||
-Ddbus=disabled
|
||||
-Dwith-upd=false
|
||||
-Dwith-perl=false
|
||||
|
||||
- name: Build
|
||||
run: ninja -C build
|
||||
|
||||
- name: Test
|
||||
run: ninja -C build test
|
||||
|
||||
- name: Install
|
||||
run: ninja -C build install
|
25
.github/workflows/ubuntu-build.yml
vendored
@ -1,25 +0,0 @@
|
||||
name: Ubuntu Build
|
||||
on: [push, pull_request]
|
||||
jobs:
|
||||
ubuntu_build:
|
||||
runs-on: ubuntu-20.04
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y meson libcanberra-dev libdbus-glib-1-dev libglib2.0-dev libgtk2.0-dev libluajit-5.1-dev libpci-dev libperl-dev libssl-dev python3-dev python3-cffi mono-devel desktop-file-utils
|
||||
|
||||
- name: Configure
|
||||
run: meson build -Dtext=true -Dtheme-manager=true -Dauto_features=enabled
|
||||
|
||||
- name: Build
|
||||
run: ninja -C build
|
||||
|
||||
- name: Test
|
||||
run: ninja -C build test
|
||||
|
||||
- name: Install
|
||||
run: sudo ninja -C build install
|
72
.github/workflows/windows-build.yml
vendored
@ -1,72 +0,0 @@
|
||||
name: Windows Build
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
windows_build:
|
||||
runs-on: windows-2019
|
||||
strategy:
|
||||
matrix:
|
||||
platform: [x64, win32]
|
||||
arch: [x64, x86]
|
||||
exclude:
|
||||
- platform: x64
|
||||
arch: x86
|
||||
- platform: win32
|
||||
arch: x64
|
||||
fail-fast: false
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
New-Item -Name "deps" -ItemType "Directory"
|
||||
|
||||
Invoke-WebRequest http://files.jrsoftware.org/is/5/innosetup-5.5.9-unicode.exe -OutFile deps\innosetup-unicode.exe
|
||||
& deps\innosetup-unicode.exe /VERYSILENT | Out-Null
|
||||
|
||||
Invoke-WebRequest https://dl.hexchat.net/misc/idpsetup-1.5.1.exe -OutFile deps\idpsetup.exe
|
||||
& deps\idpsetup.exe /VERYSILENT
|
||||
|
||||
Invoke-WebRequest https://dl.hexchat.net/gtk/gtk-${{ matrix.platform }}-2018-08-29-openssl1.1.7z -OutFile deps\gtk-${{ matrix.arch }}.7z
|
||||
& 7z.exe x deps\gtk-${{ matrix.arch }}.7z -oC:\gtk-build\gtk
|
||||
|
||||
Invoke-WebRequest https://dl.hexchat.net/gtk-win32/gendef-20111031.7z -OutFile deps\gendef.7z
|
||||
& 7z.exe x deps\gendef.7z -oC:\gtk-build
|
||||
|
||||
Invoke-WebRequest https://dl.hexchat.net/gtk-win32/WinSparkle-20151011.7z -OutFile deps\WinSparkle.7z
|
||||
& 7z.exe x deps\WinSparkle.7z -oC:\gtk-build\WinSparkle
|
||||
|
||||
Invoke-WebRequest https://dl.hexchat.net/misc/perl/perl-5.20.0-${{ matrix.arch }}.7z -OutFile deps\perl-${{ matrix.arch }}.7z
|
||||
& 7z.exe x deps\perl-${{ matrix.arch }}.7z -oC:\gtk-build\perl-5.20\${{ matrix.platform }}
|
||||
|
||||
New-Item -Path "c:\gtk-build" -Name "python-2.7" -ItemType "Directory"
|
||||
New-Item -Path "c:\gtk-build" -Name "python-3.6" -ItemType "Directory"
|
||||
New-Item -Path "c:\gtk-build\python-2.7" -Name "${{ matrix.platform }}" -ItemType "SymbolicLink" -Value "C:/hostedtoolcache/windows/Python/2.7.18/${{ matrix.arch }}"
|
||||
New-Item -Path "c:\gtk-build\python-3.6" -Name "${{ matrix.platform }}" -ItemType "SymbolicLink" -Value "C:/hostedtoolcache/windows/Python/3.6.8/${{ matrix.arch }}"
|
||||
|
||||
C:/hostedtoolcache/windows/Python/3.6.8/${{ matrix.arch }}/python.exe -m pip install cffi
|
||||
C:/hostedtoolcache/windows/Python/2.7.18/${{ matrix.arch }}/python.exe -m pip install -qq cffi
|
||||
shell: powershell
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\Tools\VsDevCmd.bat"
|
||||
msbuild win32\hexchat.sln /m /verbosity:minimal /p:Configuration=Release /p:Platform=${{ matrix.platform }}
|
||||
shell: cmd
|
||||
|
||||
- name: Preparing Artifacts
|
||||
run: |
|
||||
move ..\hexchat-build\${{ matrix.platform }}\HexChat*.exe .\
|
||||
move ..\hexchat-build .\
|
||||
shell: cmd
|
||||
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: Installer ${{ matrix.arch }}
|
||||
path: HexChat*.exe
|
||||
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: Build Files ${{ matrix.arch }}
|
||||
path: hexchat-build
|
70
.gitignore
vendored
@ -1,29 +1,75 @@
|
||||
/build
|
||||
builddir/
|
||||
# git ignore file
|
||||
# Unix generated files
|
||||
.deps/
|
||||
.libs/
|
||||
Makefile
|
||||
Makefile.in
|
||||
aclocal.m4
|
||||
autom4te.cache/
|
||||
compile
|
||||
confdefs.h
|
||||
conftest
|
||||
conftest.c
|
||||
conftest.err
|
||||
config.guess
|
||||
config.h.in
|
||||
config.h
|
||||
config.log
|
||||
config.status
|
||||
config.sub
|
||||
configure
|
||||
configure.tmp
|
||||
depcomp
|
||||
doxygen*.tmp
|
||||
html/
|
||||
install-sh
|
||||
intl/
|
||||
libtool
|
||||
ltmain.sh
|
||||
m4/
|
||||
missing
|
||||
plugins/perl/irc.pm.h
|
||||
plugins/perl/xchat.pm.h
|
||||
po/Makefile.in.in
|
||||
po/POTFILES
|
||||
po/remove-potcdate.sed
|
||||
po/stamp-po
|
||||
share/pkgconfig/hexchat-plugin.pc
|
||||
src/common/dbus/example
|
||||
src/common/dbus/marshallers.h
|
||||
src/common/dbus/org.hexchat.service.service
|
||||
src/common/dbus/remote-object-glue.h
|
||||
src/common/make-te
|
||||
src/common/textenums.h
|
||||
src/common/textevents.h
|
||||
src/fe-gtk/hexchat
|
||||
src/fe-text/hexchat-text
|
||||
src/htm/Main.resources
|
||||
src/htm/thememan.exe
|
||||
src/htm/thememan.exe.config
|
||||
src/htm/thememan.exe.mdb
|
||||
src/htm/thememan
|
||||
stamp-h1
|
||||
*.a
|
||||
*.o
|
||||
*.la
|
||||
*.lo
|
||||
*.gmo
|
||||
*.mo
|
||||
*.po~
|
||||
*.patch
|
||||
tags
|
||||
# Win32 generated files
|
||||
plugins/wmpa/wmpa_h.h
|
||||
plugins/wmpa/wmpa_i.c
|
||||
src/pixmaps/inline_pngs.h
|
||||
src/htm/obj/*
|
||||
win32/ipch/*
|
||||
win32/ext/perl/perl-x86-cache
|
||||
win32/ext/perl/perl-x86-SetupFiles
|
||||
win32/ext/perl/perl-x64-cache
|
||||
win32/ext/perl/perl-x64-SetupFiles
|
||||
win32/installer/hexchat.iss
|
||||
resource.h
|
||||
*.opensdf
|
||||
*.sdf
|
||||
*.suo
|
||||
*.user
|
||||
*.exe
|
||||
# OSX
|
||||
osx/HexChat.app
|
||||
osx/.HexChat.app
|
||||
*.zip
|
||||
*.dmg
|
||||
*.VC.db
|
||||
*.VC.opendb
|
||||
|
3
.gitmodules
vendored
@ -1,3 +0,0 @@
|
||||
[submodule "flatpak/shared-modules"]
|
||||
path = flatpak/shared-modules
|
||||
url = https://github.com/flathub/shared-modules.git
|
10
.mailmap
@ -1,10 +0,0 @@
|
||||
Berke Viktor <github.bviktor@outlook.com> <berkeviktor@aol.com>
|
||||
Berke Viktor <github.bviktor@outlook.com> <bviktor@hexchat.org>
|
||||
Berke Viktor <github.bviktor@outlook.com> <bviktor@outlook.com>
|
||||
Berke Viktor <github.bviktor@outlook.com> berkeviktor@aol.com
|
||||
Patrick Griffis <tingping@tingping.se> TingPing <tingping@fedoraproject.org>
|
||||
Patrick Griffis <tingping@tingping.se> TingPing <tingping@tingping.se>
|
||||
Patrick Griffis <tingping@tingping.se> TingPing <tngpng@gmail.com>
|
||||
Patrick Griffis <tingping@tingping.se> TingPing <TingPing@users.noreply.github.com>
|
||||
Arnav Singh <arnavion@gmail.com> Arnavion
|
||||
Eustachy Kapusta <Eustachy.kapusta@gmail.com> tomek
|
14
.travis.yml
Normal file
@ -0,0 +1,14 @@
|
||||
language: c
|
||||
compiler: gcc
|
||||
before_script:
|
||||
- sudo apt-get build-dep -qq xchat
|
||||
- sudo apt-get install -qq libnotify-dev libproxy-dev libpci-dev libcanberra-dev monodevelop
|
||||
script:
|
||||
- ./autogen.sh
|
||||
- ./configure --enable-textfe --with-theme-manager
|
||||
- make
|
||||
notifications:
|
||||
irc:
|
||||
channels: "chat.freenode.net#hexchat-devel"
|
||||
template: "Build #%{build_number} (%{commit}) by %{author}: %{message}"
|
||||
on_success: change
|
8
Makefile.am
Normal file
@ -0,0 +1,8 @@
|
||||
## Process this file with automake to produce Makefile.in
|
||||
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
|
||||
SUBDIRS = po intl src plugins man share
|
||||
|
||||
EXTRA_DIST = autogen.sh
|
||||
|
40
acinclude.m4
Normal file
@ -0,0 +1,40 @@
|
||||
dnl AS_AC_EXPAND(VAR, CONFIGURE_VAR)
|
||||
dnl
|
||||
dnl example
|
||||
dnl AS_AC_EXPAND(SYSCONFDIR, $sysconfdir)
|
||||
dnl will set SYSCONFDIR to /usr/local/etc if prefix=/usr/local
|
||||
|
||||
AC_DEFUN([AS_AC_EXPAND],
|
||||
[
|
||||
EXP_VAR=[$1]
|
||||
FROM_VAR=[$2]
|
||||
|
||||
dnl first expand prefix and exec_prefix if necessary
|
||||
prefix_save=$prefix
|
||||
exec_prefix_save=$exec_prefix
|
||||
|
||||
dnl if no prefix given, then use /usr/local, the default prefix
|
||||
if test "x$prefix" = "xNONE"; then
|
||||
prefix=$ac_default_prefix
|
||||
fi
|
||||
dnl if no exec_prefix given, then use prefix
|
||||
if test "x$exec_prefix" = "xNONE"; then
|
||||
exec_prefix=$prefix
|
||||
fi
|
||||
|
||||
full_var="$FROM_VAR"
|
||||
dnl loop until it doesn't change anymore
|
||||
while true; do
|
||||
new_full_var="`eval echo $full_var`"
|
||||
if test "x$new_full_var" = "x$full_var"; then break; fi
|
||||
full_var=$new_full_var
|
||||
done
|
||||
|
||||
dnl clean up
|
||||
full_var=$new_full_var
|
||||
AC_SUBST([$1], "$full_var")
|
||||
|
||||
dnl restore prefix and exec_prefix
|
||||
prefix=$prefix_save
|
||||
exec_prefix=$exec_prefix_save
|
||||
])
|
113
autogen.sh
Executable file
@ -0,0 +1,113 @@
|
||||
#!/bin/bash
|
||||
have_automake=false
|
||||
|
||||
if automake --version < /dev/null > /dev/null 2>&1 ; then
|
||||
automake_version=`automake --version | grep 'automake (GNU automake)' | sed 's/^[^0-9]*\(.*\)/\1/'`
|
||||
case $automake_version in
|
||||
1.2*|1.3*|1.4|1.4*|1.5*|1.6*|1.7*|1.8*)
|
||||
;;
|
||||
*)
|
||||
have_automake=true
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
if $have_automake ; then
|
||||
AUTOMAKE="automake"
|
||||
ACLOCAL="aclocal"
|
||||
else
|
||||
if automake-1.9 --version < /dev/null > /dev/null 2>&1 ; then
|
||||
AUTOMAKE="automake-1.9"
|
||||
ACLOCAL="aclocal-1.9"
|
||||
else
|
||||
echo "automake missing or too old. This requires at least automake 1.9"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# ------ START GETTEXT ------
|
||||
|
||||
echo searching for GNU gettext intl directory...
|
||||
|
||||
dirs="/usr/share /usr/local/share /opt/share /usr /usr/local /opt /usr/gnu/share /opt/local /opt/local/share"
|
||||
found=0
|
||||
for try in $dirs; do
|
||||
echo -n " -> $try/gettext/intl... "
|
||||
if test -d $try/gettext/intl; then
|
||||
echo found it
|
||||
found=1
|
||||
break
|
||||
fi
|
||||
echo no
|
||||
done
|
||||
if test "$found" != 1; then
|
||||
echo ERROR: Cannot find gettext/intl directory.
|
||||
echo ERROR: Install GNU gettext in /usr or /usr/local prefix.
|
||||
exit 7
|
||||
fi;
|
||||
|
||||
echo copying gettext intl files...
|
||||
if test -f $try/gettext/mkinstalldirs; then
|
||||
ln -s $try/gettext/mkinstalldirs mkinstalldirs
|
||||
fi
|
||||
intldir="$try/gettext/intl"
|
||||
if test ! -d intl; then
|
||||
mkdir intl
|
||||
fi
|
||||
olddir=`pwd`
|
||||
cd $intldir
|
||||
for file in *; do
|
||||
if test $file != COPYING.LIB-2.0 && test $file != COPYING.LIB-2.1; then
|
||||
rm -f $olddir/intl/$file
|
||||
cp $intldir/$file $olddir/intl/
|
||||
fi
|
||||
done
|
||||
cp -f $try/gettext/po/Makefile.in.in $olddir/po/
|
||||
cd $olddir
|
||||
if test -f intl/plural.c; then
|
||||
sleep 2
|
||||
touch intl/plural.c
|
||||
fi
|
||||
|
||||
# ------ END GETTEXT ------
|
||||
|
||||
|
||||
echo running $ACLOCAL...
|
||||
$ACLOCAL $ACLOCAL_FLAGS
|
||||
if test "$?" != "0"; then
|
||||
echo aclocal failed, stopping.
|
||||
exit 2
|
||||
fi
|
||||
echo running libtoolize...
|
||||
libtoolize --copy --force --install
|
||||
if test "$?" != "0"; then
|
||||
echo libtoolize failed, stopping.
|
||||
exit 3
|
||||
fi
|
||||
echo running autoheader...
|
||||
autoheader
|
||||
if test "$?" != "0"; then
|
||||
echo autoheader failed, stopping.
|
||||
exit 4
|
||||
fi
|
||||
echo running $AUTOMAKE...
|
||||
$AUTOMAKE -a -c
|
||||
if test "$?" != "0"; then
|
||||
echo automake failed, stopping.
|
||||
exit 5
|
||||
fi
|
||||
echo running autoconf...
|
||||
autoconf
|
||||
if test "$?" != "0"; then
|
||||
echo autoconf failed, stopping.
|
||||
exit 6
|
||||
fi
|
||||
|
||||
echo if no errors occured, run ./configure
|
||||
exit 0
|
||||
|
||||
#autogen.sh generates:
|
||||
# aclocal.m4 Makefile.in config.guess config.sub ltmain.sh
|
||||
# configure install-sh missing mkinstalldirs depcomp
|
||||
#
|
||||
#configure generates:
|
||||
# config.status libtool Makefile.in
|
@ -1,14 +1,18 @@
|
||||
#define LOCALEDIR ".\\share\\locale"
|
||||
#define ENABLE_NLS
|
||||
#define USE_GMODULE
|
||||
#define USE_PLUGIN
|
||||
#define USE_OPENSSL
|
||||
#define USE_LIBSEXY
|
||||
#define USE_IPV6
|
||||
#define HAVE_ISO_CODES
|
||||
#define ISO_CODES_PREFIX ".\\"
|
||||
#define ISO_CODES_LOCALEDIR LOCALEDIR
|
||||
#define PACKAGE_NAME "hexchat"
|
||||
#define PACKAGE_VERSION "<#= [string]::Join('.', $versionParts) #>"
|
||||
#define PACKAGE_VERSION "2.9.6"
|
||||
#define HEXCHATLIBDIR ".\\plugins"
|
||||
#define HEXCHATSHAREDIR "."
|
||||
#define OLD_PERL
|
||||
#define GETTEXT_PACKAGE "hexchat"
|
||||
#define PACKAGE_TARNAME "hexchat-<#= [string]::Join('.', $versionParts) #>"
|
||||
#define PACKAGE_TARNAME "hexchat-2.9.6"
|
||||
#ifndef USE_IPV6
|
||||
#define socklen_t int
|
||||
#endif
|
672
config.rpath
Normal file
@ -0,0 +1,672 @@
|
||||
#! /bin/sh
|
||||
# Output a system dependent set of variables, describing how to set the
|
||||
# run time search path of shared libraries in an executable.
|
||||
#
|
||||
# Copyright 1996-2010 Free Software Foundation, Inc.
|
||||
# Taken from GNU libtool, 2001
|
||||
# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
|
||||
#
|
||||
# This file is free software; the Free Software Foundation gives
|
||||
# unlimited permission to copy and/or distribute it, with or without
|
||||
# modifications, as long as this notice is preserved.
|
||||
#
|
||||
# The first argument passed to this file is the canonical host specification,
|
||||
# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
|
||||
# or
|
||||
# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
|
||||
# The environment variables CC, GCC, LDFLAGS, LD, with_gnu_ld
|
||||
# should be set by the caller.
|
||||
#
|
||||
# The set of defined variables is at the end of this script.
|
||||
|
||||
# Known limitations:
|
||||
# - On IRIX 6.5 with CC="cc", the run time search patch must not be longer
|
||||
# than 256 bytes, otherwise the compiler driver will dump core. The only
|
||||
# known workaround is to choose shorter directory names for the build
|
||||
# directory and/or the installation directory.
|
||||
|
||||
# All known linkers require a `.a' archive for static linking (except MSVC,
|
||||
# which needs '.lib').
|
||||
libext=a
|
||||
shrext=.so
|
||||
|
||||
host="$1"
|
||||
host_cpu=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
|
||||
host_vendor=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
|
||||
host_os=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
|
||||
|
||||
# Code taken from libtool.m4's _LT_CC_BASENAME.
|
||||
|
||||
for cc_temp in $CC""; do
|
||||
case $cc_temp in
|
||||
compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
|
||||
distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
|
||||
\-*) ;;
|
||||
*) break;;
|
||||
esac
|
||||
done
|
||||
cc_basename=`echo "$cc_temp" | sed -e 's%^.*/%%'`
|
||||
|
||||
# Code taken from libtool.m4's _LT_COMPILER_PIC.
|
||||
|
||||
wl=
|
||||
if test "$GCC" = yes; then
|
||||
wl='-Wl,'
|
||||
else
|
||||
case "$host_os" in
|
||||
aix*)
|
||||
wl='-Wl,'
|
||||
;;
|
||||
darwin*)
|
||||
case $cc_basename in
|
||||
xlc*)
|
||||
wl='-Wl,'
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
mingw* | cygwin* | pw32* | os2* | cegcc*)
|
||||
;;
|
||||
hpux9* | hpux10* | hpux11*)
|
||||
wl='-Wl,'
|
||||
;;
|
||||
irix5* | irix6* | nonstopux*)
|
||||
wl='-Wl,'
|
||||
;;
|
||||
newsos6)
|
||||
;;
|
||||
linux* | k*bsd*-gnu)
|
||||
case $cc_basename in
|
||||
ecc*)
|
||||
wl='-Wl,'
|
||||
;;
|
||||
icc* | ifort*)
|
||||
wl='-Wl,'
|
||||
;;
|
||||
lf95*)
|
||||
wl='-Wl,'
|
||||
;;
|
||||
pgcc | pgf77 | pgf90)
|
||||
wl='-Wl,'
|
||||
;;
|
||||
ccc*)
|
||||
wl='-Wl,'
|
||||
;;
|
||||
como)
|
||||
wl='-lopt='
|
||||
;;
|
||||
*)
|
||||
case `$CC -V 2>&1 | sed 5q` in
|
||||
*Sun\ C*)
|
||||
wl='-Wl,'
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
osf3* | osf4* | osf5*)
|
||||
wl='-Wl,'
|
||||
;;
|
||||
rdos*)
|
||||
;;
|
||||
solaris*)
|
||||
wl='-Wl,'
|
||||
;;
|
||||
sunos4*)
|
||||
wl='-Qoption ld '
|
||||
;;
|
||||
sysv4 | sysv4.2uw2* | sysv4.3*)
|
||||
wl='-Wl,'
|
||||
;;
|
||||
sysv4*MP*)
|
||||
;;
|
||||
sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
|
||||
wl='-Wl,'
|
||||
;;
|
||||
unicos*)
|
||||
wl='-Wl,'
|
||||
;;
|
||||
uts4*)
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Code taken from libtool.m4's _LT_LINKER_SHLIBS.
|
||||
|
||||
hardcode_libdir_flag_spec=
|
||||
hardcode_libdir_separator=
|
||||
hardcode_direct=no
|
||||
hardcode_minus_L=no
|
||||
|
||||
case "$host_os" in
|
||||
cygwin* | mingw* | pw32* | cegcc*)
|
||||
# FIXME: the MSVC++ port hasn't been tested in a loooong time
|
||||
# When not using gcc, we currently assume that we are using
|
||||
# Microsoft Visual C++.
|
||||
if test "$GCC" != yes; then
|
||||
with_gnu_ld=no
|
||||
fi
|
||||
;;
|
||||
interix*)
|
||||
# we just hope/assume this is gcc and not c89 (= MSVC++)
|
||||
with_gnu_ld=yes
|
||||
;;
|
||||
openbsd*)
|
||||
with_gnu_ld=no
|
||||
;;
|
||||
esac
|
||||
|
||||
ld_shlibs=yes
|
||||
if test "$with_gnu_ld" = yes; then
|
||||
# Set some defaults for GNU ld with shared library support. These
|
||||
# are reset later if shared libraries are not supported. Putting them
|
||||
# here allows them to be overridden if necessary.
|
||||
# Unlike libtool, we use -rpath here, not --rpath, since the documented
|
||||
# option of GNU ld is called -rpath, not --rpath.
|
||||
hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
|
||||
case "$host_os" in
|
||||
aix[3-9]*)
|
||||
# On AIX/PPC, the GNU linker is very broken
|
||||
if test "$host_cpu" != ia64; then
|
||||
ld_shlibs=no
|
||||
fi
|
||||
;;
|
||||
amigaos*)
|
||||
hardcode_libdir_flag_spec='-L$libdir'
|
||||
hardcode_minus_L=yes
|
||||
# Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports
|
||||
# that the semantics of dynamic libraries on AmigaOS, at least up
|
||||
# to version 4, is to share data among multiple programs linked
|
||||
# with the same dynamic library. Since this doesn't match the
|
||||
# behavior of shared libraries on other platforms, we cannot use
|
||||
# them.
|
||||
ld_shlibs=no
|
||||
;;
|
||||
beos*)
|
||||
if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
|
||||
:
|
||||
else
|
||||
ld_shlibs=no
|
||||
fi
|
||||
;;
|
||||
cygwin* | mingw* | pw32* | cegcc*)
|
||||
# hardcode_libdir_flag_spec is actually meaningless, as there is
|
||||
# no search path for DLLs.
|
||||
hardcode_libdir_flag_spec='-L$libdir'
|
||||
if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then
|
||||
:
|
||||
else
|
||||
ld_shlibs=no
|
||||
fi
|
||||
;;
|
||||
interix[3-9]*)
|
||||
hardcode_direct=no
|
||||
hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
|
||||
;;
|
||||
gnu* | linux* | k*bsd*-gnu)
|
||||
if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
|
||||
:
|
||||
else
|
||||
ld_shlibs=no
|
||||
fi
|
||||
;;
|
||||
netbsd*)
|
||||
;;
|
||||
solaris*)
|
||||
if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then
|
||||
ld_shlibs=no
|
||||
elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
|
||||
:
|
||||
else
|
||||
ld_shlibs=no
|
||||
fi
|
||||
;;
|
||||
sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
|
||||
case `$LD -v 2>&1` in
|
||||
*\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*)
|
||||
ld_shlibs=no
|
||||
;;
|
||||
*)
|
||||
if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
|
||||
hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`'
|
||||
else
|
||||
ld_shlibs=no
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
sunos4*)
|
||||
hardcode_direct=yes
|
||||
;;
|
||||
*)
|
||||
if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
|
||||
:
|
||||
else
|
||||
ld_shlibs=no
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
if test "$ld_shlibs" = no; then
|
||||
hardcode_libdir_flag_spec=
|
||||
fi
|
||||
else
|
||||
case "$host_os" in
|
||||
aix3*)
|
||||
# Note: this linker hardcodes the directories in LIBPATH if there
|
||||
# are no directories specified by -L.
|
||||
hardcode_minus_L=yes
|
||||
if test "$GCC" = yes; then
|
||||
# Neither direct hardcoding nor static linking is supported with a
|
||||
# broken collect2.
|
||||
hardcode_direct=unsupported
|
||||
fi
|
||||
;;
|
||||
aix[4-9]*)
|
||||
if test "$host_cpu" = ia64; then
|
||||
# On IA64, the linker does run time linking by default, so we don't
|
||||
# have to do anything special.
|
||||
aix_use_runtimelinking=no
|
||||
else
|
||||
aix_use_runtimelinking=no
|
||||
# Test if we are trying to use run time linking or normal
|
||||
# AIX style linking. If -brtl is somewhere in LDFLAGS, we
|
||||
# need to do runtime linking.
|
||||
case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*)
|
||||
for ld_flag in $LDFLAGS; do
|
||||
if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
|
||||
aix_use_runtimelinking=yes
|
||||
break
|
||||
fi
|
||||
done
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
hardcode_direct=yes
|
||||
hardcode_libdir_separator=':'
|
||||
if test "$GCC" = yes; then
|
||||
case $host_os in aix4.[012]|aix4.[012].*)
|
||||
collect2name=`${CC} -print-prog-name=collect2`
|
||||
if test -f "$collect2name" && \
|
||||
strings "$collect2name" | grep resolve_lib_name >/dev/null
|
||||
then
|
||||
# We have reworked collect2
|
||||
:
|
||||
else
|
||||
# We have old collect2
|
||||
hardcode_direct=unsupported
|
||||
hardcode_minus_L=yes
|
||||
hardcode_libdir_flag_spec='-L$libdir'
|
||||
hardcode_libdir_separator=
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
# Begin _LT_AC_SYS_LIBPATH_AIX.
|
||||
echo 'int main () { return 0; }' > conftest.c
|
||||
${CC} ${LDFLAGS} conftest.c -o conftest
|
||||
aix_libpath=`dump -H conftest 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
|
||||
}'`
|
||||
if test -z "$aix_libpath"; then
|
||||
aix_libpath=`dump -HX64 conftest 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
|
||||
}'`
|
||||
fi
|
||||
if test -z "$aix_libpath"; then
|
||||
aix_libpath="/usr/lib:/lib"
|
||||
fi
|
||||
rm -f conftest.c conftest
|
||||
# End _LT_AC_SYS_LIBPATH_AIX.
|
||||
if test "$aix_use_runtimelinking" = yes; then
|
||||
hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
|
||||
else
|
||||
if test "$host_cpu" = ia64; then
|
||||
hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib'
|
||||
else
|
||||
hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
amigaos*)
|
||||
hardcode_libdir_flag_spec='-L$libdir'
|
||||
hardcode_minus_L=yes
|
||||
# see comment about different semantics on the GNU ld section
|
||||
ld_shlibs=no
|
||||
;;
|
||||
bsdi[45]*)
|
||||
;;
|
||||
cygwin* | mingw* | pw32* | cegcc*)
|
||||
# When not using gcc, we currently assume that we are using
|
||||
# Microsoft Visual C++.
|
||||
# hardcode_libdir_flag_spec is actually meaningless, as there is
|
||||
# no search path for DLLs.
|
||||
hardcode_libdir_flag_spec=' '
|
||||
libext=lib
|
||||
;;
|
||||
darwin* | rhapsody*)
|
||||
hardcode_direct=no
|
||||
if test "$GCC" = yes ; then
|
||||
:
|
||||
else
|
||||
case $cc_basename in
|
||||
xlc*)
|
||||
;;
|
||||
*)
|
||||
ld_shlibs=no
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
;;
|
||||
dgux*)
|
||||
hardcode_libdir_flag_spec='-L$libdir'
|
||||
;;
|
||||
freebsd1*)
|
||||
ld_shlibs=no
|
||||
;;
|
||||
freebsd2.2*)
|
||||
hardcode_libdir_flag_spec='-R$libdir'
|
||||
hardcode_direct=yes
|
||||
;;
|
||||
freebsd2*)
|
||||
hardcode_direct=yes
|
||||
hardcode_minus_L=yes
|
||||
;;
|
||||
freebsd* | dragonfly*)
|
||||
hardcode_libdir_flag_spec='-R$libdir'
|
||||
hardcode_direct=yes
|
||||
;;
|
||||
hpux9*)
|
||||
hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
|
||||
hardcode_libdir_separator=:
|
||||
hardcode_direct=yes
|
||||
# hardcode_minus_L: Not really in the search PATH,
|
||||
# but as the default location of the library.
|
||||
hardcode_minus_L=yes
|
||||
;;
|
||||
hpux10*)
|
||||
if test "$with_gnu_ld" = no; then
|
||||
hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
|
||||
hardcode_libdir_separator=:
|
||||
hardcode_direct=yes
|
||||
# hardcode_minus_L: Not really in the search PATH,
|
||||
# but as the default location of the library.
|
||||
hardcode_minus_L=yes
|
||||
fi
|
||||
;;
|
||||
hpux11*)
|
||||
if test "$with_gnu_ld" = no; then
|
||||
hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
|
||||
hardcode_libdir_separator=:
|
||||
case $host_cpu in
|
||||
hppa*64*|ia64*)
|
||||
hardcode_direct=no
|
||||
;;
|
||||
*)
|
||||
hardcode_direct=yes
|
||||
# hardcode_minus_L: Not really in the search PATH,
|
||||
# but as the default location of the library.
|
||||
hardcode_minus_L=yes
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
;;
|
||||
irix5* | irix6* | nonstopux*)
|
||||
hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
|
||||
hardcode_libdir_separator=:
|
||||
;;
|
||||
netbsd*)
|
||||
hardcode_libdir_flag_spec='-R$libdir'
|
||||
hardcode_direct=yes
|
||||
;;
|
||||
newsos6)
|
||||
hardcode_direct=yes
|
||||
hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
|
||||
hardcode_libdir_separator=:
|
||||
;;
|
||||
openbsd*)
|
||||
if test -f /usr/libexec/ld.so; then
|
||||
hardcode_direct=yes
|
||||
if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
|
||||
hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
|
||||
else
|
||||
case "$host_os" in
|
||||
openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*)
|
||||
hardcode_libdir_flag_spec='-R$libdir'
|
||||
;;
|
||||
*)
|
||||
hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
else
|
||||
ld_shlibs=no
|
||||
fi
|
||||
;;
|
||||
os2*)
|
||||
hardcode_libdir_flag_spec='-L$libdir'
|
||||
hardcode_minus_L=yes
|
||||
;;
|
||||
osf3*)
|
||||
hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
|
||||
hardcode_libdir_separator=:
|
||||
;;
|
||||
osf4* | osf5*)
|
||||
if test "$GCC" = yes; then
|
||||
hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
|
||||
else
|
||||
# Both cc and cxx compiler support -rpath directly
|
||||
hardcode_libdir_flag_spec='-rpath $libdir'
|
||||
fi
|
||||
hardcode_libdir_separator=:
|
||||
;;
|
||||
solaris*)
|
||||
hardcode_libdir_flag_spec='-R$libdir'
|
||||
;;
|
||||
sunos4*)
|
||||
hardcode_libdir_flag_spec='-L$libdir'
|
||||
hardcode_direct=yes
|
||||
hardcode_minus_L=yes
|
||||
;;
|
||||
sysv4)
|
||||
case $host_vendor in
|
||||
sni)
|
||||
hardcode_direct=yes # is this really true???
|
||||
;;
|
||||
siemens)
|
||||
hardcode_direct=no
|
||||
;;
|
||||
motorola)
|
||||
hardcode_direct=no #Motorola manual says yes, but my tests say they lie
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
sysv4.3*)
|
||||
;;
|
||||
sysv4*MP*)
|
||||
if test -d /usr/nec; then
|
||||
ld_shlibs=yes
|
||||
fi
|
||||
;;
|
||||
sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*)
|
||||
;;
|
||||
sysv5* | sco3.2v5* | sco5v6*)
|
||||
hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`'
|
||||
hardcode_libdir_separator=':'
|
||||
;;
|
||||
uts4*)
|
||||
hardcode_libdir_flag_spec='-L$libdir'
|
||||
;;
|
||||
*)
|
||||
ld_shlibs=no
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Check dynamic linker characteristics
|
||||
# Code taken from libtool.m4's _LT_SYS_DYNAMIC_LINKER.
|
||||
# Unlike libtool.m4, here we don't care about _all_ names of the library, but
|
||||
# only about the one the linker finds when passed -lNAME. This is the last
|
||||
# element of library_names_spec in libtool.m4, or possibly two of them if the
|
||||
# linker has special search rules.
|
||||
library_names_spec= # the last element of library_names_spec in libtool.m4
|
||||
libname_spec='lib$name'
|
||||
case "$host_os" in
|
||||
aix3*)
|
||||
library_names_spec='$libname.a'
|
||||
;;
|
||||
aix[4-9]*)
|
||||
library_names_spec='$libname$shrext'
|
||||
;;
|
||||
amigaos*)
|
||||
library_names_spec='$libname.a'
|
||||
;;
|
||||
beos*)
|
||||
library_names_spec='$libname$shrext'
|
||||
;;
|
||||
bsdi[45]*)
|
||||
library_names_spec='$libname$shrext'
|
||||
;;
|
||||
cygwin* | mingw* | pw32* | cegcc*)
|
||||
shrext=.dll
|
||||
library_names_spec='$libname.dll.a $libname.lib'
|
||||
;;
|
||||
darwin* | rhapsody*)
|
||||
shrext=.dylib
|
||||
library_names_spec='$libname$shrext'
|
||||
;;
|
||||
dgux*)
|
||||
library_names_spec='$libname$shrext'
|
||||
;;
|
||||
freebsd1*)
|
||||
;;
|
||||
freebsd* | dragonfly*)
|
||||
case "$host_os" in
|
||||
freebsd[123]*)
|
||||
library_names_spec='$libname$shrext$versuffix' ;;
|
||||
*)
|
||||
library_names_spec='$libname$shrext' ;;
|
||||
esac
|
||||
;;
|
||||
gnu*)
|
||||
library_names_spec='$libname$shrext'
|
||||
;;
|
||||
hpux9* | hpux10* | hpux11*)
|
||||
case $host_cpu in
|
||||
ia64*)
|
||||
shrext=.so
|
||||
;;
|
||||
hppa*64*)
|
||||
shrext=.sl
|
||||
;;
|
||||
*)
|
||||
shrext=.sl
|
||||
;;
|
||||
esac
|
||||
library_names_spec='$libname$shrext'
|
||||
;;
|
||||
interix[3-9]*)
|
||||
library_names_spec='$libname$shrext'
|
||||
;;
|
||||
irix5* | irix6* | nonstopux*)
|
||||
library_names_spec='$libname$shrext'
|
||||
case "$host_os" in
|
||||
irix5* | nonstopux*)
|
||||
libsuff= shlibsuff=
|
||||
;;
|
||||
*)
|
||||
case $LD in
|
||||
*-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= ;;
|
||||
*-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 ;;
|
||||
*-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 ;;
|
||||
*) libsuff= shlibsuff= ;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
linux*oldld* | linux*aout* | linux*coff*)
|
||||
;;
|
||||
linux* | k*bsd*-gnu)
|
||||
library_names_spec='$libname$shrext'
|
||||
;;
|
||||
knetbsd*-gnu)
|
||||
library_names_spec='$libname$shrext'
|
||||
;;
|
||||
netbsd*)
|
||||
library_names_spec='$libname$shrext'
|
||||
;;
|
||||
newsos6)
|
||||
library_names_spec='$libname$shrext'
|
||||
;;
|
||||
nto-qnx*)
|
||||
library_names_spec='$libname$shrext'
|
||||
;;
|
||||
openbsd*)
|
||||
library_names_spec='$libname$shrext$versuffix'
|
||||
;;
|
||||
os2*)
|
||||
libname_spec='$name'
|
||||
shrext=.dll
|
||||
library_names_spec='$libname.a'
|
||||
;;
|
||||
osf3* | osf4* | osf5*)
|
||||
library_names_spec='$libname$shrext'
|
||||
;;
|
||||
rdos*)
|
||||
;;
|
||||
solaris*)
|
||||
library_names_spec='$libname$shrext'
|
||||
;;
|
||||
sunos4*)
|
||||
library_names_spec='$libname$shrext$versuffix'
|
||||
;;
|
||||
sysv4 | sysv4.3*)
|
||||
library_names_spec='$libname$shrext'
|
||||
;;
|
||||
sysv4*MP*)
|
||||
library_names_spec='$libname$shrext'
|
||||
;;
|
||||
sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
|
||||
library_names_spec='$libname$shrext'
|
||||
;;
|
||||
uts4*)
|
||||
library_names_spec='$libname$shrext'
|
||||
;;
|
||||
esac
|
||||
|
||||
sed_quote_subst='s/\(["`$\\]\)/\\\1/g'
|
||||
escaped_wl=`echo "X$wl" | sed -e 's/^X//' -e "$sed_quote_subst"`
|
||||
shlibext=`echo "$shrext" | sed -e 's,^\.,,'`
|
||||
escaped_libname_spec=`echo "X$libname_spec" | sed -e 's/^X//' -e "$sed_quote_subst"`
|
||||
escaped_library_names_spec=`echo "X$library_names_spec" | sed -e 's/^X//' -e "$sed_quote_subst"`
|
||||
escaped_hardcode_libdir_flag_spec=`echo "X$hardcode_libdir_flag_spec" | sed -e 's/^X//' -e "$sed_quote_subst"`
|
||||
|
||||
LC_ALL=C sed -e 's/^\([a-zA-Z0-9_]*\)=/acl_cv_\1=/' <<EOF
|
||||
|
||||
# How to pass a linker flag through the compiler.
|
||||
wl="$escaped_wl"
|
||||
|
||||
# Static library suffix (normally "a").
|
||||
libext="$libext"
|
||||
|
||||
# Shared library suffix (normally "so").
|
||||
shlibext="$shlibext"
|
||||
|
||||
# Format of library name prefix.
|
||||
libname_spec="$escaped_libname_spec"
|
||||
|
||||
# Library names that the linker finds when passed -lNAME.
|
||||
library_names_spec="$escaped_library_names_spec"
|
||||
|
||||
# Flag to hardcode \$libdir into a binary during linking.
|
||||
# This must work even if \$libdir does not exist.
|
||||
hardcode_libdir_flag_spec="$escaped_hardcode_libdir_flag_spec"
|
||||
|
||||
# Whether we need a single -rpath flag with a separated argument.
|
||||
hardcode_libdir_separator="$hardcode_libdir_separator"
|
||||
|
||||
# Set to yes if using DIR/libNAME.so during linking hardcodes DIR into the
|
||||
# resulting binary.
|
||||
hardcode_direct="$hardcode_direct"
|
||||
|
||||
# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
|
||||
# resulting binary.
|
||||
hardcode_minus_L="$hardcode_minus_L"
|
||||
|
||||
EOF
|
1035
configure.ac
Normal file
@ -1,24 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<gresources>
|
||||
<gresource prefix="/icons">
|
||||
<file alias="hexchat.png" preprocess="to-pixdata">icons/hexchat.png</file>
|
||||
<file alias="book.png" preprocess="to-pixdata">icons/book.png</file>
|
||||
|
||||
<file alias="ulist_voice.png" preprocess="to-pixdata">icons/ulist_voice.png</file>
|
||||
<file alias="ulist_halfop.png" preprocess="to-pixdata">icons/ulist_halfop.png</file>
|
||||
<file alias="ulist_op.png" preprocess="to-pixdata">icons/ulist_op.png</file>
|
||||
<file alias="ulist_owner.png" preprocess="to-pixdata">icons/ulist_owner.png</file>
|
||||
<file alias="ulist_founder.png" preprocess="to-pixdata">icons/ulist_founder.png</file>
|
||||
<file alias="ulist_netop.png" preprocess="to-pixdata">icons/ulist_netop.png</file>
|
||||
|
||||
<file alias="tray_normal.png" preprocess="to-pixdata">icons/hexchat.png</file>
|
||||
<file alias="tray_fileoffer.png" preprocess="to-pixdata">icons/tray_fileoffer.png</file>
|
||||
<file alias="tray_highlight.png" preprocess="to-pixdata">icons/tray_highlight.png</file>
|
||||
<file alias="tray_message.png" preprocess="to-pixdata">icons/tray_message.png</file>
|
||||
|
||||
<file alias="tree_channel.png" preprocess="to-pixdata">icons/tree_channel.png</file>
|
||||
<file alias="tree_dialog.png" preprocess="to-pixdata">icons/tree_dialog.png</file>
|
||||
<file alias="tree_server.png" preprocess="to-pixdata">icons/tree_server.png</file>
|
||||
<file alias="tree_util.png" preprocess="to-pixdata">icons/tree_util.png</file>
|
||||
</gresource>
|
||||
</gresources>
|
@ -1,63 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
height="64"
|
||||
width="64">
|
||||
<metadata>
|
||||
<rdf:RDF>
|
||||
<cc:Work>
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>Guglielmi David</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
<cc:license rdf:resource="http://creativecommons.org/licenses/GPL/2.0/" />
|
||||
<dc:rights>
|
||||
<cc:Agent>
|
||||
<dc:title>Peter Zelezny</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:rights>
|
||||
<dc:contributor>
|
||||
<cc:Agent>
|
||||
<dc:title>Samuel Messner</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:contributor>
|
||||
</cc:Work>
|
||||
<cc:License rdf:about="http://creativecommons.org/licenses/GPL/2.0/">
|
||||
<cc:requires rdf:resource="http://web.resource.org/cc/Notice" />
|
||||
<cc:requires rdf:resource="http://web.resource.org/cc/ShareAlike" />
|
||||
<cc:requires rdf:resource="http://web.resource.org/cc/SourceCode" />
|
||||
<cc:permits rdf:resource="http://web.resource.org/cc/Reproduction" />
|
||||
<cc:permits rdf:resource="http://web.resource.org/cc/Distribution" />
|
||||
<cc:permits rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
|
||||
</cc:License>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs>
|
||||
<linearGradient id="hexchatGradient" x1="0" y1="1" x2="0" y2="0">
|
||||
<stop id="hgRedStop" offset="0" style="stop-color: #FF2600; stop-opacity: 1;" />
|
||||
<stop id="hgYellowStop" offset="1" style="stop-color: #FFD600; stop-opacity: 1;" />
|
||||
</linearGradient>
|
||||
<filter inkscape:collect="always" id="dropshadow">
|
||||
<feGaussianBlur inkscape:collect="always" stdDeviation="1.9736701" id="dropshadowGaussian" />
|
||||
</filter>
|
||||
</defs>
|
||||
<path
|
||||
style="fill: #000000; fill-opacity: 1;"
|
||||
d="m 31.62506,4.4248023 c -7.285288,0.0713 -14.595323,0.526836 -15.96875,1.3125 C 12.909458,7.3086297 -0.0321942,29.523731 6.0185229e-5,32.612303 0.0323162,35.700876 13.470952,57.688808 16.25006,59.206053 c 2.779105,1.517245 29.159399,1.258827 31.90625,-0.3125 2.746852,-1.571328 15.688504,-23.786428 15.65625,-26.875 C 63.7803,28.929981 50.372918,6.9107967 47.59381,5.3935523 46.204258,4.6349293 38.910347,4.3535003 31.62506,4.4248023 z m -0.1875,9.2500007 c 3.386631,-0.03246 6.676687,0.05409 8.75,0.28125 l -8.71875,9.71875 -9.0625,-9.5 c 2.055746,-0.283043 5.521157,-0.466366 9.03125,-0.5 z m 17.34375,9.84375 c 2.298293,3.744897 4.302354,7.392556 4.3125,8.34375 0.01126,1.055883 -2.358157,5.507241 -4.875,9.6875 l -9.03125,-8.03125 z m -34.46875,0.25 8.75,9.75 -8.1875,7.875 c -2.482342,-3.992634 -4.707927,-8.110307 -4.71875,-9.125 -0.01021,-0.95736 1.927117,-4.687748 4.15625,-8.5 z m 17.15625,16.90625 9.8125,9.21875 c -4.111037,0.67314 -16.108253,0.781873 -19.46875,0.125 z"
|
||||
id="outline"
|
||||
sodipodi:nodetypes="ssssssssscccscsccccccsccccc" />
|
||||
<path
|
||||
style="fill: url(#hexchatGradient); fill-opacity: 1;"
|
||||
d="m 31.25006,6.4873027 c -6.857093,0.06521 -13.707297,0.469014 -15,1.1875 -2.585405,1.4369712 -14.780358,21.7692653 -14.75,24.5937503 0.03036,2.824486 12.665486,22.924987 15.28125,24.3125 2.615763,1.387513 27.445846,1.186972 30.03125,-0.25 2.585405,-1.436972 14.780359,-21.769265 14.75,-24.59375 C 61.5322,28.912818 48.897074,8.7810649 46.28131,7.3935527 44.973429,6.6997957 38.107152,6.4220967 31.25006,6.4873027 z m 0.0625,5.0625003 c 5.36199,-0.05245 10.696035,0.19201 11.71875,0.75 0.06132,0.03346 0.143803,0.127745 0.21875,0.1875 l -11.28125,12.59375 -0.5,0.53125 -0.46875,-0.53125 -11.75,-12.3125 c 0.10903,-0.09884 0.228263,-0.201843 0.3125,-0.25 1.010846,-0.577879 6.38801,-0.916306 11.75,-0.96875 z m 18.0625,9.46875 c 2.883844,4.661341 5.612556,9.652893 5.625,10.84375 0.01348,1.290331 -3.064699,7.087557 -6.09375,12.09375 l -11.09375,-9.90625 -0.53125,-0.46875 0.5,-0.46875 11.59375,-12.09375 z m -35.78125,0.03125 10.84375,12.0625 0.4375,0.46875 -0.46875,0.4375 -10.28125,9.90625 c -3.04689,-4.86606 -6.049362,-10.36778 -6.0625,-11.625 -0.01271,-1.216102 2.689239,-6.451996 5.53125,-11.25 z m 17.875,17.78125 0.4375,0.4375 12.34375,11.59375 c -0.318014,0.365376 -0.587006,0.638955 -0.78125,0.75 -2.02169,1.155758 -21.423322,1.397228 -23.46875,0.28125 -0.228202,-0.124506 -0.601742,-0.47821 -1,-0.9375 l 12,-11.6875 0.46875,-0.4375 z"
|
||||
id="coloredX" />
|
||||
</svg>
|
Before Width: | Height: | Size: 4.7 KiB |
Before Width: | Height: | Size: 126 KiB |
Before Width: | Height: | Size: 2.4 KiB |
@ -1,58 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
height="64"
|
||||
width="64">
|
||||
<metadata>
|
||||
<rdf:RDF>
|
||||
<cc:Work>
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>Guglielmi David</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
<cc:license rdf:resource="http://creativecommons.org/licenses/GPL/2.0/" />
|
||||
<dc:rights>
|
||||
<cc:Agent>
|
||||
<dc:title>Peter Zelezny</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:rights>
|
||||
<dc:contributor>
|
||||
<cc:Agent>
|
||||
<dc:title>Samuel Messner</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:contributor>
|
||||
</cc:Work>
|
||||
<cc:License rdf:about="http://creativecommons.org/licenses/GPL/2.0/">
|
||||
<cc:requires rdf:resource="http://web.resource.org/cc/Notice" />
|
||||
<cc:requires rdf:resource="http://web.resource.org/cc/ShareAlike" />
|
||||
<cc:requires rdf:resource="http://web.resource.org/cc/SourceCode" />
|
||||
<cc:permits rdf:resource="http://web.resource.org/cc/Reproduction" />
|
||||
<cc:permits rdf:resource="http://web.resource.org/cc/Distribution" />
|
||||
<cc:permits rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
|
||||
</cc:License>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs>
|
||||
<linearGradient id="hexchatGradient" x1="0" y1="0" x2="0" y2="1">
|
||||
<stop id="hgYellowStop" offset="0" style="stop-color: #FFD600" />
|
||||
<stop id="hgRedStop" offset="1" style="stop-color: #FF2600" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<use xlink:href="#outline" style="opacity:0.15" transform="translate(0,2)" id="shadow" />
|
||||
<path
|
||||
style="fill:#000000; fill-opacity: 1;"
|
||||
d="M 31.71875,4.1088109 C 24.433462,4.1801109 17.123427,4.6356469 15.75,5.4213109 13.003148,6.9926379 0.06149557,29.207739 0.09374996,32.296311 0.12600597,35.384884 13.564642,57.372816 16.34375,58.890061 19.122855,60.407306 45.503149,60.148888 48.25,58.577561 50.996852,57.006233 63.938504,34.791133 63.90625,31.702561 63.87399,28.613989 50.466608,6.5948049 47.6875,5.0775609 46.297948,4.3189379 39.004037,4.0375089 31.71875,4.1088109 Z m -0.1875,9.2500001 c 3.386631,-0.03246 6.676687,0.05409 8.75,0.28125 l -8.71875,9.71875 -9.0625,-9.5 c 2.055746,-0.283043 5.521157,-0.466366 9.03125,-0.5 z m 17.34375,9.84375 c 2.298293,3.744897 4.302354,7.392556 4.3125,8.34375 0.01126,1.055883 -2.358157,5.507241 -4.875,9.6875 l -9.03125,-8.03125 z m -34.46875,0.25 8.75,9.75 -8.1875,7.875 c -2.482342,-3.992634 -4.707927,-8.110307 -4.71875,-9.125 -0.01021,-0.95736 1.927117,-4.687748 4.15625,-8.5 z m 17.15625,16.90625 9.8125,9.21875 c -4.111037,0.67314 -16.108253,0.781873 -19.46875,0.125 z"
|
||||
id="outline" />
|
||||
<path
|
||||
style="fill:url(#hexchatGradient); fill-opacity: 1;"
|
||||
d="m 31.34375,6.1713109 c -6.857093,0.06521 -13.707297,0.469014 -15,1.1875 C 13.758345,8.7957819 1.5633917,29.128076 1.5937497,31.952561 c 0.03036,2.824486 12.6654863,22.924987 15.2812503,24.3125 2.615763,1.387513 27.445846,1.186972 30.03125,-0.25 2.585405,-1.436972 14.780359,-21.769265 14.75,-24.59375 C 61.62589,28.596826 48.990764,8.4650729 46.375,7.0775609 45.067119,6.3838039 38.200842,6.1061049 31.34375,6.1713109 Z m 0.0625,5.0625001 c 5.36199,-0.05245 10.696035,0.19201 11.71875,0.75 0.06132,0.03346 0.143803,0.127745 0.21875,0.1875 l -11.28125,12.59375 -0.5,0.53125 -0.46875,-0.53125 -11.75,-12.3125 c 0.10903,-0.09884 0.228263,-0.201843 0.3125,-0.25 1.010846,-0.577879 6.38801,-0.916306 11.75,-0.96875 z m 18.0625,9.46875 c 2.883844,4.661341 5.612556,9.652893 5.625,10.84375 0.01348,1.290331 -3.064699,7.087557 -6.09375,12.09375 l -11.09375,-9.90625 -0.53125,-0.46875 0.5,-0.46875 11.59375,-12.09375 z m -35.78125,0.03125 10.84375,12.0625 0.4375,0.46875 -0.46875,0.4375 -10.28125,9.90625 c -3.04689,-4.86606 -6.0493623,-10.36778 -6.0625003,-11.625 -0.01271,-1.216102 2.6892393,-6.451996 5.5312503,-11.25 z m 17.875,17.78125 0.4375,0.4375 12.34375,11.59375 c -0.318014,0.365376 -0.587006,0.638955 -0.78125,0.75 -2.02169,1.155758 -21.423322,1.397228 -23.46875,0.28125 -0.228202,-0.124506 -0.601742,-0.47821 -1,-0.9375 l 12,-11.6875 0.46875,-0.4375 z"
|
||||
id="coloredX" />
|
||||
</svg>
|
Before Width: | Height: | Size: 4.4 KiB |
@ -1,11 +0,0 @@
|
||||
icondir = join_paths(get_option('datadir'), 'icons/hicolor')
|
||||
install_data(
|
||||
'hexchat.png',
|
||||
rename: 'io.github.Hexchat.png',
|
||||
install_dir: join_paths(icondir, '48x48/apps')
|
||||
)
|
||||
install_data(
|
||||
'hexchat.svg',
|
||||
rename: 'io.github.Hexchat.svg',
|
||||
install_dir: join_paths(icondir, 'scalable/apps')
|
||||
)
|
Before Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 2.1 KiB |
@ -1,10 +0,0 @@
|
||||
man_conf = configuration_data()
|
||||
man_conf.set('VERSION', meson.project_version())
|
||||
|
||||
configure_file(
|
||||
input: 'hexchat.1.in',
|
||||
output: 'hexchat.1',
|
||||
configuration: man_conf,
|
||||
install: true,
|
||||
install_dir: join_paths(get_option('mandir'), 'man1')
|
||||
)
|
@ -1,11 +0,0 @@
|
||||
if get_option('plugin')
|
||||
subdir('pkgconfig')
|
||||
endif
|
||||
|
||||
if get_option('gtk-frontend')
|
||||
subdir('icons')
|
||||
subdir('misc')
|
||||
subdir('man')
|
||||
elif get_option('theme-manager')
|
||||
subdir('misc')
|
||||
endif
|
@ -1,11 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<component type="addon">
|
||||
<id>io.github.Hexchat.Plugin.@NAME@</id>
|
||||
<extends>io.github.Hexchat.desktop</extends>
|
||||
<name>@NAME@ Plugin</name>
|
||||
<summary>@SUMMARY@</summary>
|
||||
<url type="homepage">https://hexchat.github.io/</url>
|
||||
<project_license>@LICENSE@</project_license>
|
||||
<metadata_license>CC0-1.0</metadata_license>
|
||||
<update_contact>tingping_AT_fedoraproject.org</update_contact>
|
||||
</component>
|
@ -1,150 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<component type="desktop">
|
||||
<id>io.github.Hexchat.desktop</id>
|
||||
<name>HexChat</name>
|
||||
<developer_name>HexChat</developer_name>
|
||||
<metadata_license>CC0-1.0</metadata_license>
|
||||
<project_license>GPL-2.0+</project_license>
|
||||
<translation type="gettext">hexchat</translation>
|
||||
<summary>IRC Client</summary>
|
||||
<description>
|
||||
<p>HexChat is an easy to use yet extensible IRC Client. It allows you to securely join multiple networks and talk to users privately or in channels using a customizable interface. You can even transfer files.</p>
|
||||
<p>HexChat supports features such as: DCC, SASL, proxies, spellcheck, alerts, logging, custom themes, and Python/Perl scripts.</p>
|
||||
</description>
|
||||
<url type="homepage">http://hexchat.github.io</url>
|
||||
<url type="bugtracker">https://github.com/hexchat/hexchat</url>
|
||||
<url type="donation">https://goo.gl/jESZvU</url>
|
||||
<url type="help">https://hexchat.readthedocs.io/en/latest/</url>
|
||||
<screenshots>
|
||||
<screenshot type="default">
|
||||
<image>http://i.imgur.com/tLMguQz.png</image>
|
||||
<caption>Main Chat Window</caption>
|
||||
</screenshot>
|
||||
</screenshots>
|
||||
<provides>
|
||||
<!-- Renamed from this -->
|
||||
<id>hexchat.desktop</id>
|
||||
</provides>
|
||||
<releases>
|
||||
<release date="2022-02-12" version="2.16.1">
|
||||
<description>
|
||||
<p>This is a minor release with mostly bug-fixes:</p>
|
||||
<ul>
|
||||
<li>Add `-NOOVERRIDE` flag to the `GUI COLOR` command</li>
|
||||
<li>Add `-q` (quiet) flag to the `EXECWRITE` command</li>
|
||||
<li>Rename installed icon to match app-id (Fixes notification icon)</li>
|
||||
<li>Fix escaping already escaped URLs when opening them</li>
|
||||
<li>Fix Python scripts not being opened as UTF-8</li>
|
||||
<li>Fix `TIMER` command supporting decimals regardless of locale</li>
|
||||
</ul>
|
||||
</description>
|
||||
</release>
|
||||
<release date="2021-10-01" version="2.16.0">
|
||||
<description>
|
||||
<p>This is a feature release:</p>
|
||||
<ul>
|
||||
<li>Add support for IRCv3 SETNAME, invite-notify, account-tag, standard replies, and UTF8ONLY</li>
|
||||
<li>Add support for strikethrough formatting</li>
|
||||
<li>Fix text clipping issues by respecting font line height</li>
|
||||
<li>Fix URLs not being escaped when opened</li>
|
||||
<li>Fix possible hang when showing notifications</li>
|
||||
<li>Print ChanServ notices in the front tab by default</li>
|
||||
<li>Update network list</li>
|
||||
<li>python: Rewrite plugin improving memory usage and compatibility</li>
|
||||
<li>fishlim: Add support for CBC and other improvements</li>
|
||||
</ul>
|
||||
</description>
|
||||
</release>
|
||||
<release date="2019-12-20" version="2.14.3">
|
||||
<description>
|
||||
<p>This is a bug-fix release:</p>
|
||||
<ul>
|
||||
<li>Fix various incorrect parsing of IRC messages relating to trailing parameters</li>
|
||||
<li>Fix SASL negotiation combined with multi-line cap</li>
|
||||
<li>Fix input box theming with Yaru theme</li>
|
||||
<li>python: Work around Python 3.7 regression causing crash on unload</li>
|
||||
<li>sysinfo: Add support for /etc/os-release</li>
|
||||
<li>sysinfo: Ignore irrelevant mounts when calculating storage size</li>
|
||||
</ul>
|
||||
</description>
|
||||
</release>
|
||||
<release date="2018-08-29" version="2.14.2">
|
||||
<description>
|
||||
<p>This is a minor release:</p>
|
||||
<ul>
|
||||
<li>Remove shift+click to close tab binding</li>
|
||||
<li>Always unminimize when opening from tray</li>
|
||||
<li>Fix some translations containing invalid text events</li>
|
||||
<li>Fix sending server passwords starting with ":"</li>
|
||||
</ul>
|
||||
</description>
|
||||
</release>
|
||||
<release date="2018-03-13" version="2.14.1">
|
||||
<description>
|
||||
<p>This is a very minor bug-fix release:</p>
|
||||
<ul>
|
||||
<li>Fix performance regression</li>
|
||||
</ul>
|
||||
</description>
|
||||
</release>
|
||||
<release date="2018-03-10" version="2.14.0">
|
||||
<description>
|
||||
<p>This is largely a bug fix release though it has some large behind the scenes changes:</p>
|
||||
<ul>
|
||||
<li>Rename data files to use *io.github.Hexchat* name</li>
|
||||
<li>Add option (irc_reconnect_rejoin) to disable auto-rejoin on reconnect</li>
|
||||
<li>Add ability to set custom tray icon separate of app icon</li>
|
||||
<li>Fix Enchant 2.0+ support</li>
|
||||
<li>Fix input box theming with Adwaita-dark</li>
|
||||
<li>Fix custom sounds not respecting omit if away option</li>
|
||||
<li>Fix detecting if a tray doesn't exist on x11</li>
|
||||
<li>Fix cutting off ctcp text after ending \01</li>
|
||||
<li>Fix /ignore not accepting full hosts</li>
|
||||
<li>Fix characters getting cut off when their width changes</li>
|
||||
<li>Fix various possible crashes</li>
|
||||
<li>Change preference window to be scroll-able</li>
|
||||
<li>Remove ctrl+w binding by default</li>
|
||||
<li>doat: Fix channels with / in them</li>
|
||||
<li>fishlim: Fix key exchange</li>
|
||||
<li>fishlim: Fix building against LibreSSL</li>
|
||||
<li>sysinfo: Fix pci.ids file not being found on some distros</li>
|
||||
<li>sysinfo: Make libpci optional</li>
|
||||
<li>lua: Avoid loading the same script multiple times</li>
|
||||
<li>Update translations</li>
|
||||
</ul>
|
||||
</description>
|
||||
</release>
|
||||
<release date="2016-12-10" version="2.12.4">
|
||||
<description>
|
||||
<p>This is another bug fix release:</p>
|
||||
<ul>
|
||||
<li>Fix issue with timers causing ping timeouts</li>
|
||||
<li>Fix building against OpenSSL 1.1</li>
|
||||
<li>Fix /exec output printing invalid utf8</li>
|
||||
<li>Replace doat plugin with an internal command</li>
|
||||
<li>Change how tab colors interact with plugins</li>
|
||||
<li>Enable filtering the beep character by default</li>
|
||||
</ul>
|
||||
</description>
|
||||
</release>
|
||||
<release date="2016-10-22" version="2.12.3">
|
||||
<description>
|
||||
<p>This is a minor bug fix release just cleaning up a few issues:</p>
|
||||
<ul>
|
||||
<li>Fix crash with bad translations</li>
|
||||
<li>Add new mhop command</li>
|
||||
<li>Change ping timeout to 60 by default</li>
|
||||
</ul>
|
||||
</description>
|
||||
</release>
|
||||
</releases>
|
||||
<kudos>
|
||||
<kudo>UserDocs</kudo>
|
||||
<kudo>HiDpiIcon</kudo>
|
||||
<kudo>Notifications</kudo>
|
||||
</kudos>
|
||||
<content_rating type="oars-1.1">
|
||||
<content_attribute id="social-chat">intense</content_attribute>
|
||||
</content_rating>
|
||||
<update_contact>tingping_at_fedoraproject.org</update_contact>
|
||||
</component>
|
@ -1,19 +0,0 @@
|
||||
[Desktop Entry]
|
||||
Name=HexChat
|
||||
GenericName=IRC Client
|
||||
Comment=Chat with other people online
|
||||
Keywords=IM;Chat;
|
||||
Exec=@exec_command@
|
||||
Icon=io.github.Hexchat
|
||||
Terminal=false
|
||||
Type=Application
|
||||
Categories=GTK;Network;IRCClient;
|
||||
StartupNotify=true
|
||||
StartupWMClass=Hexchat
|
||||
X-GNOME-UsesNotifications=true
|
||||
MimeType=x-scheme-handler/irc;x-scheme-handler/ircs;
|
||||
Actions=SafeMode;
|
||||
|
||||
[Desktop Action SafeMode]
|
||||
Name=Open Safe Mode
|
||||
Exec=hexchat --no-auto --no-plugins
|
@ -1,127 +0,0 @@
|
||||
appdir = join_paths(get_option('datadir'), 'applications')
|
||||
metainfodir = join_paths(get_option('datadir'), 'metainfo')
|
||||
desktop_utils = find_program('desktop-file-validate', required: false)
|
||||
|
||||
if get_option('gtk-frontend')
|
||||
if get_option('install-appdata')
|
||||
hexchat_appdata = i18n.merge_file(
|
||||
input: 'io.github.Hexchat.appdata.xml.in',
|
||||
output: 'io.github.Hexchat.appdata.xml',
|
||||
po_dir: '../../po',
|
||||
install: true,
|
||||
install_dir: metainfodir
|
||||
)
|
||||
|
||||
appstream_util = find_program('appstream-util', required: false)
|
||||
if appstream_util.found()
|
||||
test('Validate io.github.Hexchat.appdata.xml', appstream_util,
|
||||
args: ['validate-relax', hexchat_appdata]
|
||||
)
|
||||
endif
|
||||
endif
|
||||
|
||||
desktop_conf = configuration_data()
|
||||
if dbus_glib_dep.found()
|
||||
desktop_conf.set('exec_command', 'hexchat --existing %U')
|
||||
else
|
||||
desktop_conf.set('exec_command', 'hexchat %U')
|
||||
endif
|
||||
|
||||
desktop_file = configure_file(
|
||||
input: 'io.github.Hexchat.desktop.in.in',
|
||||
output: 'io.github.Hexchat.desktop.in',
|
||||
configuration: desktop_conf
|
||||
)
|
||||
|
||||
hexchat_desktop = i18n.merge_file(
|
||||
input: desktop_file,
|
||||
output: 'io.github.Hexchat.desktop',
|
||||
po_dir: '../../po',
|
||||
type: 'desktop',
|
||||
install: true,
|
||||
install_dir: appdir
|
||||
)
|
||||
|
||||
if desktop_utils.found()
|
||||
test('Validate io.github.Hexchat.desktop', desktop_utils,
|
||||
args: [hexchat_desktop]
|
||||
)
|
||||
endif
|
||||
endif
|
||||
|
||||
if get_option('theme-manager')
|
||||
htm_desktop = i18n.merge_file(
|
||||
input: 'io.github.Hexchat.ThemeManager.desktop.in',
|
||||
output: 'io.github.Hexchat.ThemeManager.desktop',
|
||||
po_dir: '../../po',
|
||||
type: 'desktop',
|
||||
install: true,
|
||||
install_dir: appdir
|
||||
)
|
||||
|
||||
if desktop_utils.found()
|
||||
test('Validate io.github.Hexchat.ThemeManager.desktop', desktop_utils,
|
||||
args: [htm_desktop]
|
||||
)
|
||||
endif
|
||||
|
||||
install_data('io.github.Hexchat.ThemeManager.xml',
|
||||
install_dir: join_paths(get_option('datadir'), 'mime/packages')
|
||||
)
|
||||
endif
|
||||
|
||||
if get_option('plugin')
|
||||
plugin_metainfo = []
|
||||
|
||||
# FIXME: These should all get translated somewhere
|
||||
if get_option('with-checksum')
|
||||
plugin_metainfo += [
|
||||
['Checksum', 'Calculates a checksum for all sent and recieved DCC files', 'MIT']
|
||||
]
|
||||
endif
|
||||
|
||||
if get_option('with-fishlim')
|
||||
plugin_metainfo += [
|
||||
['Fishlim', 'Allows setting a key for encrypted conversations', 'MIT AND GPL-2.0+']
|
||||
]
|
||||
endif
|
||||
|
||||
if get_option('with-lua') != 'false'
|
||||
plugin_metainfo += [
|
||||
['Lua', 'Provides a scripting interface in Lua', 'MIT']
|
||||
]
|
||||
endif
|
||||
|
||||
if get_option('with-perl') != 'false'
|
||||
plugin_metainfo += [
|
||||
['Perl', 'Provides a scripting interface in Perl', 'GPL-2.0+']
|
||||
]
|
||||
endif
|
||||
|
||||
if get_option('with-python') != 'false'
|
||||
plugin_metainfo += [
|
||||
['Python', 'Provides a scripting interface in Python', 'GPL-2.0+']
|
||||
]
|
||||
endif
|
||||
|
||||
if get_option('with-sysinfo')
|
||||
plugin_metainfo += [
|
||||
['Sysinfo', 'Adds command to display system information', 'GPL-2.0+']
|
||||
]
|
||||
endif
|
||||
|
||||
foreach metainfo : plugin_metainfo
|
||||
name = metainfo[0]
|
||||
conf = configuration_data()
|
||||
conf.set('NAME', name)
|
||||
conf.set('SUMMARY', metainfo[1])
|
||||
conf.set('LICENSE', metainfo[2])
|
||||
|
||||
configure_file(
|
||||
input: 'io.github.Hexchat.Plugin.metainfo.xml.in',
|
||||
output: 'io.github.Hexchat.Plugin.@0@.metainfo.xml'.format(name),
|
||||
configuration: conf,
|
||||
install_dir: get_option('install-plugin-metainfo') ? metainfodir : '',
|
||||
)
|
||||
endforeach
|
||||
endif
|
@ -1,14 +0,0 @@
|
||||
pkg_conf = configuration_data()
|
||||
prefix = get_option('prefix')
|
||||
pkg_conf.set('prefix', prefix)
|
||||
pkg_conf.set('VERSION', meson.project_version())
|
||||
pkg_conf.set('hexchatlibdir', join_paths('${prefix}', plugindir))
|
||||
pkg_conf.set('includedir', join_paths('${prefix}', get_option('includedir')))
|
||||
|
||||
configure_file(
|
||||
input: 'hexchat-plugin.pc.in',
|
||||
output: 'hexchat-plugin.pc',
|
||||
configuration: pkg_conf,
|
||||
install: true,
|
||||
install_dir: join_paths(get_option('libdir'), 'pkgconfig'),
|
||||
)
|
@ -1,14 +0,0 @@
|
||||
; dnf install mingw64-{gtk,openssl}
|
||||
|
||||
[binaries]
|
||||
c = '/usr/bin/x86_64-w64-mingw32-gcc'
|
||||
cpp = '/usr/bin/x86_64-w64-mingw32-g++'
|
||||
ar = '/usr/bin/x86_64-w64-mingw32-gcc-ar'
|
||||
strip = '/usr/bin/x86_64-w64-mingw32-strip'
|
||||
pkgconfig = '/usr/bin/x86_64-w64-mingw32-pkg-config'
|
||||
|
||||
[host_machine]
|
||||
system = 'windows'
|
||||
cpu_family = 'x86_64'
|
||||
cpu = 'x86_64'
|
||||
endian = 'little'
|
@ -1,25 +0,0 @@
|
||||
From 918503d57c6740d20be68a6717158673a2a8b25f Mon Sep 17 00:00:00 2001
|
||||
From: Patrick Griffis <tingping@tingping.se>
|
||||
Date: Sat, 17 Mar 2018 05:57:49 -0400
|
||||
Subject: [PATCH] Support loading Flatpak extensions
|
||||
|
||||
---
|
||||
src/common/plugin.c | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/src/common/plugin.c b/src/common/plugin.c
|
||||
index 3ad3c558..6addf962 100644
|
||||
--- a/src/common/plugin.c
|
||||
+++ b/src/common/plugin.c
|
||||
@@ -450,6 +450,8 @@ plugin_auto_load (session *sess)
|
||||
lib_dir = plugin_get_libdir ();
|
||||
sub_dir = g_build_filename (get_xdir (), "addons", NULL);
|
||||
|
||||
+ for_files ("/app/extensions/lib/hexchat/plugins", "*.so", plugin_auto_load_cb);
|
||||
+
|
||||
#ifdef WIN32
|
||||
/* a long list of bundled plugins that should be loaded automatically,
|
||||
* user plugins should go to <config>, leave Program Files alone! */
|
||||
--
|
||||
2.14.3
|
||||
|
@ -1,78 +0,0 @@
|
||||
{
|
||||
"app-id": "io.github.Hexchat",
|
||||
"branch": "stable",
|
||||
"runtime": "org.gnome.Platform",
|
||||
"runtime-version": "40",
|
||||
"sdk": "org.gnome.Sdk",
|
||||
"command": "hexchat",
|
||||
"finish-args": [
|
||||
"--share=ipc",
|
||||
"--socket=x11",
|
||||
"--share=network",
|
||||
"--socket=pulseaudio",
|
||||
"--filesystem=xdg-download",
|
||||
|
||||
"--talk-name=org.freedesktop.Notifications",
|
||||
|
||||
"--talk-name=org.mpris.MediaPlayer2.*"
|
||||
],
|
||||
"add-extensions": {
|
||||
"io.github.Hexchat.Plugin": {
|
||||
"version": "20.08",
|
||||
"directory": "extensions",
|
||||
"add-ld-path": "lib",
|
||||
"merge-dirs": "lib/hexchat/plugins",
|
||||
"subdirectories": true,
|
||||
"no-autodownload": true,
|
||||
"autodelete": true
|
||||
}
|
||||
},
|
||||
"modules": [
|
||||
"shared-modules/gtk2/gtk2.json",
|
||||
"shared-modules/gtk2/gtk2-common-themes.json",
|
||||
"shared-modules/dbus-glib/dbus-glib.json",
|
||||
"shared-modules/lua5.3/lua-5.3.5.json",
|
||||
"shared-modules/libcanberra/libcanberra.json",
|
||||
"python3-cffi.json",
|
||||
{
|
||||
"name": "lgi",
|
||||
"buildsystem": "meson",
|
||||
"sources": [
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://github.com/pavouk/lgi.git",
|
||||
"commit": "95418635aa8151a516d43166227ea2b9d4c4403f"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "hexchat",
|
||||
"buildsystem": "meson",
|
||||
"config-opts": [
|
||||
"--buildtype=release",
|
||||
"-Ddbus-service-use-appid=true",
|
||||
"-Dwith-perl=false",
|
||||
"-Dwith-lua=lua"
|
||||
],
|
||||
"build-options": {
|
||||
"cflags": "-Wno-error=missing-include-dirs"
|
||||
},
|
||||
"cleanup": [
|
||||
"/share/man"
|
||||
],
|
||||
"post-install": [
|
||||
"install -d /app/extensions"
|
||||
],
|
||||
"sources": [
|
||||
{
|
||||
"type": "dir",
|
||||
"path": ".."
|
||||
},
|
||||
{
|
||||
"type": "patch",
|
||||
"path": "Load-plugins-from-Flatpak-extensions.patch"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
{
|
||||
"name": "python3-cffi",
|
||||
"buildsystem": "simple",
|
||||
"build-commands": [
|
||||
"pip3 install --verbose --exists-action=i --no-index --find-links=\"file://${PWD}\" --prefix=${FLATPAK_DEST} \"cffi\" --no-build-isolation"
|
||||
],
|
||||
"sources": [
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/0f/86/e19659527668d70be91d0369aeaa055b4eb396b0f387a4f92293a20035bd/pycparser-2.20.tar.gz",
|
||||
"sha256": "2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/a8/20/025f59f929bbcaa579704f443a438135918484fffaacfaddba776b374563/cffi-1.14.5.tar.gz",
|
||||
"sha256": "fd78e5fee591709f32ef6edb9a015b4aa1a5022598e36227500c8f4e02328d9c"
|
||||
}
|
||||
]
|
||||
}
|
1
man/Makefile.am
Normal file
@ -0,0 +1 @@
|
||||
man_MANS = hexchat.1
|
@ -1,4 +1,4 @@
|
||||
.TH HEXCHAT "1" "April 2013" "HexChat @VERSION@" "User Commands"
|
||||
.TH HEXCHAT "1" "April 2013" "HexChat 2.9.6" "User Commands"
|
||||
.SH NAME
|
||||
HexChat \- IRC Client
|
||||
.SH DESCRIPTION
|
197
meson.build
@ -1,197 +0,0 @@
|
||||
project('hexchat', 'c',
|
||||
version: '2.16.1',
|
||||
meson_version: '>= 0.47.0',
|
||||
default_options: [
|
||||
'c_std=gnu89',
|
||||
'buildtype=debugoptimized',
|
||||
'warning_level=1',
|
||||
]
|
||||
)
|
||||
|
||||
i18n = import('i18n')
|
||||
gnome = import('gnome')
|
||||
cc = meson.get_compiler('c')
|
||||
|
||||
|
||||
libgio_dep = dependency('gio-2.0', version: '>= 2.34.0')
|
||||
libgmodule_dep = dependency('gmodule-2.0')
|
||||
|
||||
libcanberra_dep = dependency('libcanberra', version: '>= 0.22',
|
||||
required: get_option('libcanberra'))
|
||||
dbus_glib_dep = dependency('dbus-glib-1', required: get_option('dbus'))
|
||||
|
||||
global_deps = []
|
||||
if cc.get_id() == 'msvc'
|
||||
libssl_dep = cc.find_library('libssl')
|
||||
else
|
||||
libssl_dep = dependency('openssl', version: '>= 0.9.8',
|
||||
required: get_option('tls'))
|
||||
endif
|
||||
|
||||
config_h = configuration_data()
|
||||
config_h.set_quoted('PACKAGE_VERSION', meson.project_version())
|
||||
config_h.set_quoted('PACKAGE_NAME', meson.project_name())
|
||||
config_h.set_quoted('GETTEXT_PACKAGE', 'hexchat')
|
||||
config_h.set_quoted('LOCALEDIR', join_paths(get_option('prefix'),
|
||||
get_option('datadir'), 'locale'))
|
||||
config_h.set_quoted('G_LOG_DOMAIN', 'hexchat')
|
||||
config_h.set10('ENABLE_NLS', true)
|
||||
|
||||
# Optional features
|
||||
config_h.set('USE_OPENSSL', libssl_dep.found())
|
||||
config_h.set('USE_LIBCANBERRA', libcanberra_dep.found())
|
||||
config_h.set('USE_DBUS', dbus_glib_dep.found())
|
||||
config_h.set('USE_PLUGIN', get_option('plugin'))
|
||||
|
||||
config_h.set('G_DISABLE_SINGLE_INCLUDES', true)
|
||||
config_h.set('GTK_DISABLE_DEPRECATED', true)
|
||||
config_h.set('GTK_DISABLE_SINGLE_INCLUDES', true)
|
||||
config_h.set('GDK_PIXBUF_DISABLE_SINGLE_INCLUDES', true)
|
||||
config_h.set('GLIB_VERSION_MAX_ALLOWED', 'GLIB_VERSION_2_34')
|
||||
config_h.set('GLIB_VERSION_MIN_REQUIRED', 'GLIB_VERSION_2_34')
|
||||
|
||||
# Detected features
|
||||
config_h.set('HAVE_MEMRCHR', cc.has_function('memrchr'))
|
||||
config_h.set('HAVE_STRINGS_H', cc.has_header('strings.h'))
|
||||
|
||||
config_h.set_quoted('HEXCHATLIBDIR',
|
||||
join_paths(get_option('prefix'), get_option('libdir'), 'hexchat/plugins')
|
||||
)
|
||||
|
||||
if libssl_dep.found()
|
||||
config_h.set('HAVE_X509_GET_SIGNATURE_NID',
|
||||
cc.has_function('X509_get_signature_nid', dependencies: libssl_dep)
|
||||
)
|
||||
config_h.set('HAVE_SSL_CTX_GET_SSL_METHOD',
|
||||
cc.has_function('SSL_CTX_get_ssl_method', dependencies: libssl_dep)
|
||||
)
|
||||
config_h.set('HAVE_DH_SET0_PQG',
|
||||
cc.has_function('DH_set0_pqg', dependencies: libssl_dep)
|
||||
)
|
||||
config_h.set('HAVE_DH_GET0_KEY',
|
||||
cc.has_function('DH_get0_key', dependencies: libssl_dep)
|
||||
)
|
||||
config_h.set('HAVE_DH_SET0_KEY',
|
||||
cc.has_function('DH_set0_key', dependencies: libssl_dep)
|
||||
)
|
||||
config_h.set('HAVE_ERR_REMOVE_THREAD_STATE',
|
||||
cc.has_function('ERR_remove_thread_state', dependencies: libssl_dep)
|
||||
)
|
||||
config_h.set('HAVE_ASN1_STRING_GET0_DATA',
|
||||
cc.has_function('ASN1_STRING_get0_data', dependencies: libssl_dep)
|
||||
)
|
||||
endif
|
||||
|
||||
configure_file(output: 'config.h', configuration: config_h)
|
||||
config_h_include = include_directories('.')
|
||||
|
||||
if host_machine.system() == 'windows'
|
||||
add_project_arguments(
|
||||
'-DWIN32',
|
||||
'-DNTDDI_VERSION=NTDDI_WIN7',
|
||||
'-D_WIN32_WINNT=_WIN32_WINNT_WIN7',
|
||||
language: 'c')
|
||||
endif
|
||||
|
||||
|
||||
global_cflags = []
|
||||
test_cflags = [
|
||||
'-funsigned-char',
|
||||
'-Wno-conversion',
|
||||
'-Wno-pointer-sign',
|
||||
'-Wno-padded',
|
||||
'-Wno-unused-parameter',
|
||||
'-Wno-missing-prototypes',
|
||||
'-Winline',
|
||||
'-Wstrict-prototypes',
|
||||
'-Werror=implicit-function-declaration',
|
||||
'-Werror=pointer-arith',
|
||||
'-Werror=init-self',
|
||||
['-Werror=format-security', '-Werror=format=1'],
|
||||
'-Werror=missing-include-dirs',
|
||||
'-Werror=date-time',
|
||||
]
|
||||
foreach cflag : test_cflags
|
||||
if cc.has_multi_arguments(cflag)
|
||||
global_cflags += cflag
|
||||
endif
|
||||
endforeach
|
||||
if get_option('buildtype') != 'plain'
|
||||
if cc.has_argument('-fstack-protector-strong') and cc.links('''
|
||||
int main (void) {
|
||||
char buffer[16];
|
||||
strcpy(buffer, "foo");
|
||||
return 0;
|
||||
}
|
||||
''', args: '-fstack-protector-all')
|
||||
global_cflags += '-fstack-protector-strong'
|
||||
|
||||
if host_machine.system() == 'windows'
|
||||
global_deps += cc.find_library('ssp')
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
add_project_arguments(global_cflags, language: 'c')
|
||||
|
||||
|
||||
global_ldflags = []
|
||||
test_ldflags = [
|
||||
'-Wl,-z,relro',
|
||||
'-Wl,-z,now',
|
||||
# mingw
|
||||
'-Wl,--nxcompat',
|
||||
]
|
||||
if not (host_machine.system() == 'windows' and get_option('debug'))
|
||||
test_ldflags += '-Wl,--dynamicbase'
|
||||
endif
|
||||
foreach ldflag : test_ldflags
|
||||
if meson.version().version_compare('>= 0.46.0')
|
||||
has_arg = cc.has_link_argument(ldflag)
|
||||
else
|
||||
has_arg = cc.has_argument(ldflag)
|
||||
endif
|
||||
|
||||
if has_arg and cc.links('int main (void) { return 0; }', args: ldflag)
|
||||
global_ldflags += ldflag
|
||||
endif
|
||||
endforeach
|
||||
add_project_link_arguments(global_ldflags, language: 'c')
|
||||
|
||||
subdir('src')
|
||||
if get_option('plugin')
|
||||
subdir('plugins')
|
||||
endif
|
||||
if cc.get_id() != 'msvc'
|
||||
subdir('data')
|
||||
subdir('po') # FIXME: build xgettext
|
||||
|
||||
meson.add_install_script('meson_post_install.py',
|
||||
'@0@'.format(get_option('theme-manager'))
|
||||
)
|
||||
endif
|
||||
|
||||
if meson.version().version_compare('>= 0.53.0')
|
||||
summary({
|
||||
'prefix': get_option('prefix'),
|
||||
'bindir': get_option('bindir'),
|
||||
'libdir': get_option('libdir'),
|
||||
'datadir': get_option('datadir'),
|
||||
}, section: 'Directories')
|
||||
|
||||
summary({
|
||||
'TLS (openssl)': libssl_dep.found(),
|
||||
'Plugin Support': get_option('plugin'),
|
||||
'DBus Support': dbus_glib_dep.found(),
|
||||
'libcanberra': libcanberra_dep.found(),
|
||||
}, section: 'Features')
|
||||
|
||||
summary({
|
||||
'Lua': get_option('with-lua'),
|
||||
'Python': get_option('with-python'),
|
||||
'Perl': get_option('with-perl'),
|
||||
'Perl Legacy API': get_option('with-perl-legacy-api'),
|
||||
'FiSH': get_option('with-fishlim'),
|
||||
'Sysinfo': get_option('with-sysinfo'),
|
||||
'DCC Checksum': get_option('with-checksum'),
|
||||
}, section: 'Plugins')
|
||||
endif
|
@ -1,67 +0,0 @@
|
||||
# Applications
|
||||
option('gtk-frontend', type: 'boolean',
|
||||
description: 'Main graphical interface'
|
||||
)
|
||||
option('text-frontend', type: 'boolean', value: false,
|
||||
description: 'Text interface (not generally useful)'
|
||||
)
|
||||
option('theme-manager', type: 'boolean', value: false,
|
||||
description: 'Utility to help manage themes, requires mono/.net'
|
||||
)
|
||||
|
||||
# Features
|
||||
option('tls', type: 'feature', value: 'enabled',
|
||||
description: 'Support for TLS connections, requires openssl'
|
||||
)
|
||||
option('plugin', type: 'boolean',
|
||||
description: 'Support for loadable plugins'
|
||||
)
|
||||
option('dbus', type: 'feature', value: 'auto',
|
||||
description: 'Support used for single-instance and scripting interface, Unix only'
|
||||
)
|
||||
option('libcanberra', type: 'feature', value: 'auto',
|
||||
description: 'Support for sound alerts, Unix only'
|
||||
)
|
||||
|
||||
# Install options
|
||||
option('dbus-service-use-appid', type: 'boolean', value: false,
|
||||
description: 'Rename dbus service to match app-id, required for Flatpak'
|
||||
)
|
||||
option('install-appdata', type: 'boolean',
|
||||
description: 'Install appdata files for app stores'
|
||||
)
|
||||
option('install-plugin-metainfo', type: 'boolean', value: false,
|
||||
description: 'Installs metainfo files for enabled plugins, useful when distros create split packages'
|
||||
)
|
||||
|
||||
# Plugins
|
||||
option('with-checksum', type: 'boolean',
|
||||
description: 'DCC checksum plugin'
|
||||
)
|
||||
option('with-exec', type: 'boolean',
|
||||
description: '/exec plugin, Windows only'
|
||||
)
|
||||
option('with-fishlim', type: 'boolean',
|
||||
description: 'Fish encryption plugin, requires openssl'
|
||||
)
|
||||
option('with-lua', type: 'string', value: 'luajit',
|
||||
description: 'Lua scripting plugin, value is pkg-config name to use or "false"'
|
||||
)
|
||||
option('with-perl', type: 'string', value: 'perl',
|
||||
description: 'Perl scripting plugin, value is path to perl executable or "false"'
|
||||
)
|
||||
option('with-python', type: 'string', value: 'python3',
|
||||
description: 'Python scripting plugin. value is pkg-config name to use or "false"'
|
||||
)
|
||||
option('with-sysinfo', type: 'boolean',
|
||||
description: 'System information plugin, requires libpci on Unix'
|
||||
)
|
||||
option('with-upd', type: 'boolean',
|
||||
description: 'Update plugin, Windows only'
|
||||
)
|
||||
option('with-winamp', type: 'boolean',
|
||||
description: 'Winamp plugin, Windows only'
|
||||
)
|
||||
option('with-perl-legacy-api', type: 'boolean', value: false,
|
||||
description: 'Enables the legacy IRC perl module for compatibility with old scripts'
|
||||
)
|
@ -1,24 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
|
||||
prefix = os.environ.get('MESON_INSTALL_PREFIX', '/usr/local')
|
||||
datadir = os.path.join(prefix, 'share')
|
||||
with_thememan = sys.argv[1] == 'true'
|
||||
|
||||
# Packaging tools define DESTDIR and this isn't needed for them
|
||||
if 'DESTDIR' not in os.environ:
|
||||
print('Updating icon cache...')
|
||||
subprocess.call(['gtk-update-icon-cache', '-qtf',
|
||||
os.path.join(datadir, 'icons', 'hicolor')])
|
||||
|
||||
print('Updating desktop database...')
|
||||
subprocess.call(['update-desktop-database', '-q',
|
||||
os.path.join(datadir, 'applications')])
|
||||
|
||||
if with_thememan:
|
||||
print('Updating mime database...')
|
||||
subprocess.call(['update-mime-database',
|
||||
os.path.join(datadir, 'mime')])
|
@ -1,30 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>English</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>HexChat</string>
|
||||
<key>CFBundleGetInfoString</key>
|
||||
<string>@VERSION@</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>hexchat.icns</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>org.hexchat</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>@VERSION@</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>@VERSION@</string>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string></string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>10.4</string>
|
||||
</dict>
|
||||
</plist>
|
435
osx/gtkrc
@ -1,435 +0,0 @@
|
||||
# Mac Theme for Xamarin composed by Lanedo GmbH
|
||||
# Copyright 2012 Xamarin Inc.
|
||||
# Authors:
|
||||
# Christian Kellner <christian.kellner@lanedo.com>
|
||||
# Carlos Garnacho <carlos.garnacho@lanedo.com>
|
||||
#
|
||||
# Modified by HexChat
|
||||
#
|
||||
|
||||
gtk-color-scheme =
|
||||
"bg_color: #f5f5f5
|
||||
fg_color: #000
|
||||
base_color: #fff
|
||||
text_color: #000
|
||||
selected_bg_color: #0066FF
|
||||
selected_fg_color: #fff
|
||||
tooltip_bg_color: #fafaba
|
||||
tooltip_fg_color: #000"
|
||||
|
||||
gtk-button-images = 0
|
||||
gtk-menu-images = 0
|
||||
gtk-toolbar-style = 0
|
||||
gtk-enable-mnemonics = 0
|
||||
gtk-icon-sizes = "gtk-small-toolbar=16,16:gtk-large-toolbar=22,22"
|
||||
gtk-toolbar-icon-size = large-toolbar
|
||||
gtk-auto-mnemonics = 1
|
||||
gtk-error-bell = 0
|
||||
gtk-show-input-method-menu = 0
|
||||
gtk-key-theme-name="Mac"
|
||||
|
||||
style "default" {
|
||||
xthickness = 1
|
||||
ythickness = 1
|
||||
|
||||
### colours
|
||||
bg[NORMAL] = @bg_color
|
||||
bg[PRELIGHT] = @bg_color
|
||||
bg[SELECTED] = @selected_bg_color
|
||||
bg[INSENSITIVE] = @bg_color
|
||||
bg[ACTIVE] = @bg_color
|
||||
|
||||
fg[NORMAL] = @fg_color
|
||||
fg[PRELIGHT] = @fg_color
|
||||
fg[SELECTED] = @selected_fg_color
|
||||
fg[INSENSITIVE] = darker (@bg_color)
|
||||
fg[ACTIVE] = @fg_color
|
||||
|
||||
text[NORMAL] = @text_color
|
||||
text[PRELIGHT] = @text_color
|
||||
text[SELECTED] = @selected_fg_color
|
||||
text[INSENSITIVE] = darker (@bg_color)
|
||||
text[ACTIVE] = @text_color
|
||||
|
||||
base[NORMAL] = @base_color
|
||||
base[PRELIGHT] = @selected_bg_color
|
||||
base[SELECTED] = @selected_bg_color
|
||||
base[INSENSITIVE] = @bg_color
|
||||
base[ACTIVE] = shade (1.3, @selected_bg_color)
|
||||
|
||||
### style properties
|
||||
GtkWidget::new-tooltip-style = 1
|
||||
|
||||
GtkEntry::honors-transparent-bg-hint = 1
|
||||
GtkEntry::inner-border = { 2, 2, 2, 2 }
|
||||
|
||||
GtkButton::child-displacement-x = 0
|
||||
GtkButton::child-displacement-y = 0
|
||||
GtkButton::default-border = { 0, 0, 0, 0 }
|
||||
GtkButton::inner-border = { 2, 2, 4, 4 }
|
||||
|
||||
GtkButtonBox::child-min-width = 70
|
||||
GtkButtonBox::child-min-height = 22
|
||||
|
||||
GtkTreeView::odd-row-color = "#f0f4f9"
|
||||
|
||||
GtkScrolledWindow::scrollbar-spacing = 0
|
||||
GtkScrolledWindow::scrollbars-within-bevel = 1
|
||||
GtkScale::slider-length = 14
|
||||
GtkRange::trough-side-details = 1
|
||||
|
||||
GtkTreeView::expander-size = 8
|
||||
GtkExpander::expander-size = 8
|
||||
GtkComboBox::arrow-size = 12
|
||||
|
||||
GtkMenu::vertical-padding = 4
|
||||
GtkMenuItem::horizontal-padding = 9
|
||||
GtkMenuItem::toggle-spacing = 0
|
||||
GtkSeparatorMenuItem::horizontal-padding = 2
|
||||
|
||||
engine "xamarin" {
|
||||
|
||||
arrowstyle = 2
|
||||
rgba = TRUE
|
||||
roundness = 3
|
||||
glazestyle = 0
|
||||
|
||||
menustyle = 0
|
||||
menuitemstyle = 0
|
||||
menubaritemstyle = 0
|
||||
comboboxstyle = 1
|
||||
spinbuttonstyle = 1
|
||||
colorize_scrollbar = FALSE
|
||||
progressbarstyle = 0
|
||||
trough_shades = { 0.842, 0.886 }
|
||||
}
|
||||
}
|
||||
|
||||
style "wide" = "default" {
|
||||
xthickness = 2
|
||||
ythickness = 2
|
||||
}
|
||||
|
||||
style "wider" = "default" {
|
||||
xthickness = 3
|
||||
ythickness = 3
|
||||
}
|
||||
|
||||
|
||||
style "button" {
|
||||
xthickness = 2
|
||||
ythickness = 2
|
||||
|
||||
bg[NORMAL] = @bg_color
|
||||
bg[PRELIGHT] = shade(1.1, @bg_color)
|
||||
bg[ACTIVE] = @bg_color
|
||||
bg[INSENSITIVE] = @bg_color
|
||||
GtkWidget::focus-padding = 0
|
||||
|
||||
engine "quartz" {
|
||||
}
|
||||
}
|
||||
|
||||
style "combo-box-button" {
|
||||
xthickness = 2
|
||||
ythickness = 4
|
||||
|
||||
bg[NORMAL] = @base_color
|
||||
bg[PRELIGHT] = shade(1.1, @base_color)
|
||||
bg[ACTIVE] = @base_color
|
||||
bg[INSENSITIVE] = @base_color
|
||||
GtkWidget::focus-padding = 0
|
||||
|
||||
engine "xamarin" {
|
||||
contrast = 1.0
|
||||
gradient_shades = {0.99, 0.98, 0.97, 0.96}
|
||||
focus_color = shade(0.6, @base_color)
|
||||
textstyle = 1
|
||||
}
|
||||
}
|
||||
|
||||
style "dialog-button" = "default" {
|
||||
xthickness = 3
|
||||
ythickness = 2
|
||||
font_name = "Lucida Grande 13"
|
||||
|
||||
GtkWidget::draw-border = { 2, 2, 2, 2 }
|
||||
GtkWidget::focus-line-width = 1
|
||||
GtkButton::inner-border = { 8, 8, 0, 3 }
|
||||
|
||||
engine "quartz" {
|
||||
buttontype = "aqua"
|
||||
}
|
||||
}
|
||||
|
||||
style "toggle-button" = "button" {
|
||||
bg[NORMAL] = @base_color
|
||||
bg[PRELIGHT] = shade(0.98, @base_color)
|
||||
}
|
||||
|
||||
style "menu" {
|
||||
xthickness = 0
|
||||
ythickness = 0
|
||||
font_name = "Lucida Grande 14"
|
||||
|
||||
bg[PRELIGHT] = @selected_fg_color
|
||||
fg[PRELIGHT] = @selected_fg_color
|
||||
text[PRELIGHT] = @selected_fg_color
|
||||
|
||||
engine "quartz" {
|
||||
}
|
||||
}
|
||||
|
||||
style "menu-item" = "menu" {
|
||||
ythickness = 2
|
||||
GtkWidget::draw-border = { 0, 0, 0, 2 }
|
||||
}
|
||||
|
||||
style "menu-separator" = "menu-item" {
|
||||
ythickness = 3
|
||||
}
|
||||
|
||||
style "toolbar" = "default"
|
||||
{
|
||||
bg[NORMAL] = "#ddd"
|
||||
engine "xamarin" {
|
||||
toolbarstyle = 2
|
||||
}
|
||||
}
|
||||
|
||||
style "toolbar-button"
|
||||
{
|
||||
engine "xamarin" {
|
||||
contrast = 1.0
|
||||
focus_color = @bg_color
|
||||
}
|
||||
}
|
||||
|
||||
style "tooltip"
|
||||
{
|
||||
xthickness = 5
|
||||
ythickness = 5
|
||||
|
||||
fg[NORMAL] = @tooltip_fg_color
|
||||
bg[NORMAL] = @tooltip_bg_color
|
||||
|
||||
engine "xamarin" {
|
||||
roundness = 0
|
||||
}
|
||||
}
|
||||
|
||||
style "treeview" = "default"
|
||||
{
|
||||
GtkTreeView::odd-row-color = "#f5f5f5"
|
||||
|
||||
base[SELECTED] = "#2b5dcd"
|
||||
base[ACTIVE] = "#cacaca"
|
||||
text[SELECTED] = "#FFF"
|
||||
text[ACTIVE] = "#000"
|
||||
|
||||
font_name = "Lucida Grande 12"
|
||||
|
||||
engine "quartz" {
|
||||
}
|
||||
}
|
||||
|
||||
style "tree-header"
|
||||
{
|
||||
ythickness = 0
|
||||
bg[NORMAL] = "#f2f2f2"
|
||||
font_name = "Lucida Grande 11"
|
||||
|
||||
GtkWidget::focus-line-width = 0
|
||||
GtkWidget::draw-border = { 1, 1, 1, 1 }
|
||||
GtkButton::inner-border = { 3, 3, 1, 3 }
|
||||
|
||||
engine "quartz" {
|
||||
}
|
||||
}
|
||||
|
||||
style "icon-view" = "default"
|
||||
{
|
||||
bg[SELECTED] = "#f5f7fa"
|
||||
base[SELECTED] = "#f5f7fa"
|
||||
fg[SELECTED] = "#000"
|
||||
text[SELECTED] = "#000"
|
||||
}
|
||||
|
||||
style "toolbar-combo-box" = "default"
|
||||
{
|
||||
fg[NORMAL] = "#616161"
|
||||
text[NORMAL] = @fg_color
|
||||
bg[NORMAL] = "#fff"
|
||||
base[NORMAL] = "#fff"
|
||||
ythickness = 4
|
||||
xthickness = 2
|
||||
|
||||
engine "xamarin" {
|
||||
comboboxstyle = 0
|
||||
arrowstyle = 2
|
||||
}
|
||||
}
|
||||
|
||||
style "combo-box" = "default"
|
||||
{
|
||||
fg[NORMAL] = "#616161"
|
||||
xthickness = 2
|
||||
ythickness = 4
|
||||
|
||||
engine "xamarin" {
|
||||
arrowstyle = 4
|
||||
}
|
||||
}
|
||||
|
||||
style "combo-box-entry" = "combo-box"
|
||||
{
|
||||
engine "xamarin" {
|
||||
arrowstyle = 3
|
||||
}
|
||||
}
|
||||
|
||||
style "combo-box-label" = "combo-box"
|
||||
{
|
||||
fg[NORMAL] = "#595959"
|
||||
}
|
||||
|
||||
style "combo-box-menu" = "menu" {
|
||||
font_name = "Lucida Grande 12"
|
||||
}
|
||||
|
||||
style "notebook" = "default"
|
||||
{
|
||||
GtkNotebook::tab-overlap = 1
|
||||
#bg[ACTIVE] = @base_color
|
||||
bg[NORMAL] = @base_color
|
||||
|
||||
engine "xamarin" {
|
||||
gradient_shades = { 0.945, 0.945, 0.945, 0.685 }
|
||||
}
|
||||
}
|
||||
|
||||
style "radio-or-check-box"
|
||||
{
|
||||
ythickness = 6
|
||||
#GtkCheckButton::indicator-size = 14
|
||||
GtkCheckButton::indicator-spacing = 4
|
||||
|
||||
engine "quartz" {
|
||||
}
|
||||
}
|
||||
|
||||
style "entry" = "default"
|
||||
{
|
||||
xthickness = 2
|
||||
ythickness = 2
|
||||
GtkEntry::inner-border = { 2, 2, 2, 2 }
|
||||
base[INSENSITIVE] = shade(1.02, @bg_color)
|
||||
|
||||
engine "quartz" {
|
||||
}
|
||||
}
|
||||
|
||||
style "search-entry" = "wider"
|
||||
{
|
||||
xthickness = 6
|
||||
ythickness = 4
|
||||
bg[NORMAL] = @base_color
|
||||
}
|
||||
|
||||
style "scrollbar" = "default"
|
||||
{
|
||||
GtkScrollbar::has-forward-stepper = 0
|
||||
GtkScrollbar::has-backward-stepper = 0
|
||||
GtkRange::slider-width = 15
|
||||
GtkRange::trough-border = 0
|
||||
GtkRange::trough-side-details = 0
|
||||
|
||||
engine "quartz" {
|
||||
}
|
||||
}
|
||||
|
||||
style "progressbar" = "default"
|
||||
{
|
||||
engine "quartz" {
|
||||
}
|
||||
}
|
||||
|
||||
style "scrolled-window" = "default"
|
||||
{
|
||||
xthickness = 1
|
||||
ythickness = 1
|
||||
}
|
||||
|
||||
style "scale" = "default"
|
||||
{
|
||||
bg[SELECTED] = @selected_bg_color
|
||||
|
||||
engine "xamarin" {
|
||||
roundness = 7
|
||||
}
|
||||
}
|
||||
|
||||
style "spin-button" = "wider"
|
||||
{
|
||||
fg[NORMAL] = "#616161"
|
||||
ythickness = 4
|
||||
GtkEntry::inner-border = { 2, 2, 1, 1 }
|
||||
engine "xamarin" {
|
||||
arrowstyle = 3
|
||||
}
|
||||
}
|
||||
|
||||
### Apply the styles
|
||||
class "GtkWidget" style "default"
|
||||
|
||||
class "GtkEntry" style "entry"
|
||||
class "GtkSpinButton" style "spin-button"
|
||||
class "GtkFrame" style "wider"
|
||||
class "GtkRange" style "wide"
|
||||
class "GtkSeparator" style "wide"
|
||||
class "GtkScrollbar" style "scrollbar"
|
||||
class "GtkProgressBar" style "progressbar"
|
||||
class "GtkScrolledWindow" style "scrolled-window"
|
||||
class "GtkNotebook" style "notebook"
|
||||
class "GtkButton" style "button"
|
||||
class "GtkToggleButton" style "toggle-button"
|
||||
class "GtkScale" style "scale"
|
||||
|
||||
#widget "*GtkEntry" style "entry"
|
||||
widget "*search-entry*" style "search-entry"
|
||||
widget "*GtkTextView" style "entry"
|
||||
|
||||
widget_class "<GtkDialog>*<GtkCheckButton>" style "radio-or-check-box"
|
||||
widget_class "<GtkDialog>.<GtkVBox>.<GtkButtonBox>.<GtkButton>*" style "dialog-button"
|
||||
widget_class "<GtkDialog>.<GtkVBox>.<GtkHBox>.<GtkButtonBox>.<GtkButton>*" style "dialog-button"
|
||||
widget "*.toggleFindInFiles" style "toggle-button"
|
||||
widget "*.toggleReplaceInFiles" style "toggle-button"
|
||||
|
||||
widget_class "*<GtkMenu>*" style "menu"
|
||||
widget_class "*<GtkMenuItem>*" style "menu-item"
|
||||
widget_class "*<GtkSeparatorMenuItem>" style "menu-separator"
|
||||
widget "*.gtk-combobox-popup-menu*" style "combo-box-menu"
|
||||
|
||||
widget_class "*<GtkToolbar>*" style "toolbar"
|
||||
widget_class "*ToolButton*" style "toolbar-button"
|
||||
|
||||
widget_class "*.<GtkTreeView>*" style "treeview"
|
||||
widget_class "*.GtkTreeView.GtkButton" style "tree-header"
|
||||
widget_class "*.GtkList.GtkButton" style "tree-header"
|
||||
|
||||
widget_class "*<GtkIconView>" style "icon-view"
|
||||
|
||||
widget_class "*.<GtkComboBox>.*" style "combo-box"
|
||||
widget_class "*.<GtkComboBoxText>.*" style "combo-box-entry"
|
||||
widget_class "*.<GtkComboBoxEntry>.*" style "combo-box-entry"
|
||||
widget_class "*.<GtkComboBoxText>.<GtkEntry>" style "combo-box-entry"
|
||||
widget_class "*.<GtkComboBoxEntry>.<GtkEntry>" style "combo-box-entry"
|
||||
widget_class "*.<GtkComboBoxText>.<GtkToggleButton>" style "combo-box-button"
|
||||
widget_class "*.<GtkComboBoxEntry>.<GtkToggleButton>" style "combo-box-button"
|
||||
widget_class "*.<GtkComboBox>.*.GtkLabel" style "combo-box-label"
|
||||
|
||||
# Comboboxes within toolbars
|
||||
widget_class "*.<GtkToolbar>.*.<GtkComboBox>.*" style "toolbar-combo-box"
|
||||
widget "*MainToolbar*.GtkComboBox.*" style "toolbar-combo-box"
|
||||
|
||||
widget "gtk-tooltip*" style "tooltip"
|
@ -1,68 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<app-bundle>
|
||||
|
||||
<meta>
|
||||
<prefix name="default">/usr/local</prefix>
|
||||
<prefix name="enchant">/usr/local/opt/enchant-applespell</prefix>
|
||||
<destination overwrite="yes">${project}</destination>
|
||||
|
||||
<run-install-name-tool/>
|
||||
<launcher-script>${project}/launcher.sh</launcher-script >
|
||||
<gtk>gtk+-2.0</gtk>
|
||||
</meta>
|
||||
|
||||
<plist>${project}/Info.plist</plist>
|
||||
|
||||
<main-binary>
|
||||
${prefix}/bin/hexchat
|
||||
</main-binary>
|
||||
|
||||
<binary>
|
||||
${prefix}/lib/hexchat/plugins/*.so
|
||||
</binary>
|
||||
|
||||
<binary>
|
||||
${prefix:enchant}/lib/libenchant.dylib
|
||||
</binary>
|
||||
<binary>
|
||||
${prefix:enchant}/lib/enchant/libenchant_applespell.so
|
||||
</binary>
|
||||
|
||||
<binary>
|
||||
${prefix}/lib/${gtkdir}/modules/*.so
|
||||
</binary>
|
||||
<binary>
|
||||
${prefix}/lib/${gtkdir}/${pkg:${gtk}:gtk_binary_version}/engines/libquartz.so
|
||||
</binary>
|
||||
<binary>
|
||||
${prefix}/lib/${gtkdir}/${pkg:${gtk}:gtk_binary_version}/engines/libxamarin.so
|
||||
</binary>
|
||||
<binary>
|
||||
${prefix}/lib/${gtkdir}/${pkg:${gtk}:gtk_binary_version}/printbackends/*.so
|
||||
</binary>
|
||||
<binary>
|
||||
${prefix}/lib/gdk-pixbuf-2.0/${pkg:${gtk}:gtk_binary_version}/loaders/*.so
|
||||
</binary>
|
||||
<binary>
|
||||
${prefix}/lib/pango/${pkg:pango:pango_module_version}/modules/
|
||||
</binary>
|
||||
<data>
|
||||
${prefix}/share/themes/Mac/gtk-2.0-key/gtkrc
|
||||
</data>
|
||||
|
||||
<translations name="gtk20">
|
||||
${prefix}/share/locale
|
||||
</translations>
|
||||
<translations name="hexchat">
|
||||
${prefix}/share/locale
|
||||
</translations>
|
||||
|
||||
<data dest="${bundle}/Contents/Resources/etc/${gtkdir}/gtkrc">
|
||||
${project}/gtkrc
|
||||
</data>
|
||||
|
||||
<data dest="${bundle}/Contents/Resources">
|
||||
${project}/hexchat.icns
|
||||
</data>
|
||||
|
||||
</app-bundle>
|
BIN
osx/hexchat.icns
174
osx/launcher.sh
@ -1,174 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
if test "x$GTK_DEBUG_LAUNCHER" != x; then
|
||||
set -x
|
||||
fi
|
||||
|
||||
if test "x$GTK_DEBUG_GDB" != x; then
|
||||
EXEC="gdb --args"
|
||||
else
|
||||
EXEC=exec
|
||||
fi
|
||||
|
||||
name=`basename "$0"`
|
||||
tmp="$0"
|
||||
tmp=`dirname "$tmp"`
|
||||
tmp=`dirname "$tmp"`
|
||||
bundle=`dirname "$tmp"`
|
||||
bundle_contents="$bundle"/Contents
|
||||
bundle_res="$bundle_contents"/Resources
|
||||
bundle_lib="$bundle_res"/lib
|
||||
bundle_bin="$bundle_res"/bin
|
||||
bundle_data="$bundle_res"/share
|
||||
bundle_etc="$bundle_res"/etc
|
||||
|
||||
export PREFIX="$bundle_res"
|
||||
export DYLD_LIBRARY_PATH="$bundle_lib"
|
||||
export XDG_CONFIG_DIRS="$bundle_etc"/xdg
|
||||
export XDG_DATA_DIRS="$bundle_data"
|
||||
export GTK_DATA_PREFIX="$bundle_res"
|
||||
export GTK_EXE_PREFIX="$bundle_res"
|
||||
export GTK_PATH="$bundle_res"
|
||||
|
||||
export GTK2_RC_FILES="$bundle_etc/gtk-2.0/gtkrc"
|
||||
export GTK_IM_MODULE_FILE="$bundle_etc/gtk-2.0/gtk.immodules"
|
||||
export GDK_PIXBUF_MODULE_FILE="$bundle_etc/gtk-2.0/gdk-pixbuf.loaders"
|
||||
export PANGO_LIBDIR="$bundle_lib"
|
||||
export PANGO_SYSCONFDIR="$bundle_etc"
|
||||
|
||||
export OPENSSL_CONF="/System/Library/OpenSSL/openssl.cnf"
|
||||
|
||||
export HEXCHAT_LIBDIR="$bundle_lib/hexchat/plugins"
|
||||
|
||||
APP=name
|
||||
I18NDIR="$bundle_data/locale"
|
||||
# Set the locale-related variables appropriately:
|
||||
unset LANG LC_MESSAGES LC_MONETARY LC_COLLATE
|
||||
|
||||
# Has a language ordering been set?
|
||||
# If so, set LC_MESSAGES and LANG accordingly; otherwise skip it.
|
||||
# First step uses sed to clean off the quotes and commas, to change - to _, and change the names for the chinese scripts from "Hans" to CN and "Hant" to TW.
|
||||
APPLELANGUAGES=`defaults read .GlobalPreferences AppleLanguages | sed -En -e 's/\-/_/' -e 's/Hant/TW/' -e 's/Hans/CN/' -e 's/[[:space:]]*\"?([[:alnum:]_]+)\"?,?/\1/p' `
|
||||
if test "$APPLELANGUAGES"; then
|
||||
# A language ordering exists.
|
||||
# Test, item per item, to see whether there is an corresponding locale.
|
||||
for L in $APPLELANGUAGES; do
|
||||
#test for exact matches:
|
||||
if test -f "$I18NDIR/${L}/LC_MESSAGES/$APP.mo"; then
|
||||
export LANG=$L
|
||||
break
|
||||
fi
|
||||
#This is a special case, because often the original strings are in US
|
||||
#English and there is no translation file.
|
||||
if test "x$L" == "xen_US"; then
|
||||
export LANG=$L
|
||||
break
|
||||
fi
|
||||
#OK, now test for just the first two letters:
|
||||
if test -f "$I18NDIR/${L:0:2}/LC_MESSAGES/$APP.mo"; then
|
||||
export LANG=${L:0:2}
|
||||
break
|
||||
fi
|
||||
#Same thing, but checking for any english variant.
|
||||
if test "x${L:0:2}" == "xen"; then
|
||||
export LANG=$L
|
||||
break
|
||||
fi;
|
||||
done
|
||||
fi
|
||||
unset APPLELANGUAGES L
|
||||
|
||||
# If we didn't get a language from the language list, try the Collation preference, in case it's the only setting that exists.
|
||||
APPLECOLLATION=`defaults read .GlobalPreferences AppleCollationOrder`
|
||||
if test -z ${LANG} -a -n $APPLECOLLATION; then
|
||||
if test -f "$I18NDIR/${APPLECOLLATION:0:2}/LC_MESSAGES/$APP.mo"; then
|
||||
export LANG=${APPLECOLLATION:0:2}
|
||||
fi
|
||||
fi
|
||||
if test ! -z $APPLECOLLATION; then
|
||||
export LC_COLLATE=$APPLECOLLATION
|
||||
fi
|
||||
unset APPLECOLLATION
|
||||
|
||||
# Continue by attempting to find the Locale preference.
|
||||
APPLELOCALE=`defaults read .GlobalPreferences AppleLocale`
|
||||
|
||||
if test -f "$I18NDIR/${APPLELOCALE:0:5}/LC_MESSAGES/$APP.mo"; then
|
||||
if test -z $LANG; then
|
||||
export LANG="${APPLELOCALE:0:5}"
|
||||
fi
|
||||
|
||||
elif test -z $LANG -a -f "$I18NDIR/${APPLELOCALE:0:2}/LC_MESSAGES/$APP.mo"; then
|
||||
export LANG="${APPLELOCALE:0:2}"
|
||||
fi
|
||||
|
||||
#Next we need to set LC_MESSAGES. If at all possilbe, we want a full
|
||||
#5-character locale to avoid the "Locale not supported by C library"
|
||||
#warning from Gtk -- even though Gtk will translate with a
|
||||
#two-character code.
|
||||
if test -n $LANG; then
|
||||
#If the language code matches the applelocale, then that's the message
|
||||
#locale; otherwise, if it's longer than two characters, then it's
|
||||
#probably a good message locale and we'll go with it.
|
||||
if test $LANG == ${APPLELOCALE:0:5} -o $LANG != ${LANG:0:2}; then
|
||||
export LC_MESSAGES=$LANG
|
||||
#Next try if the Applelocale is longer than 2 chars and the language
|
||||
#bit matches $LANG
|
||||
elif test $LANG == ${APPLELOCALE:0:2} -a $APPLELOCALE > ${APPLELOCALE:0:2}; then
|
||||
export LC_MESSAGES=${APPLELOCALE:0:5}
|
||||
#Fail. Get a list of the locales in $PREFIX/share/locale that match
|
||||
#our two letter language code and pick the first one, special casing
|
||||
#english to set en_US
|
||||
elif test $LANG == "en"; then
|
||||
export LC_MESSAGES="en_US"
|
||||
else
|
||||
LOC=`find $PREFIX/share/locale -name $LANG???`
|
||||
for L in $LOC; do
|
||||
export LC_MESSAGES=$L
|
||||
done
|
||||
fi
|
||||
else
|
||||
#All efforts have failed, so default to US english
|
||||
export LANG="en_US"
|
||||
export LC_MESSAGES="en_US"
|
||||
fi
|
||||
CURRENCY=`echo $APPLELOCALE | sed -En 's/.*currency=([[:alpha:]]+).*/\1/p'`
|
||||
if test "x$CURRENCY" != "x"; then
|
||||
#The user has set a special currency. Gtk doesn't install LC_MONETARY files, but Apple does in /usr/share/locale, so we're going to look there for a locale to set LC_CURRENCY to.
|
||||
if test -f /usr/local/share/$LC_MESSAGES/LC_MONETARY; then
|
||||
if test -a `cat /usr/local/share/$LC_MESSAGES/LC_MONETARY` == $CURRENCY; then
|
||||
export LC_MONETARY=$LC_MESSAGES
|
||||
fi
|
||||
fi
|
||||
if test -z "$LC_MONETARY"; then
|
||||
FILES=`find /usr/share/locale -name LC_MONETARY -exec grep -H $CURRENCY {} \;`
|
||||
if test -n "$FILES"; then
|
||||
export LC_MONETARY=`echo $FILES | sed -En 's%/usr/share/locale/([[:alpha:]_]+)/LC_MONETARY.*%\1%p'`
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
#No currency value means that the AppleLocale governs:
|
||||
if test -z "$LC_MONETARY"; then
|
||||
LC_MONETARY=${APPLELOCALE:0:5}
|
||||
fi
|
||||
#For Gtk, which only looks at LC_ALL:
|
||||
export LC_ALL=$LC_MESSAGES
|
||||
|
||||
unset APPLELOCALE FILES LOC
|
||||
|
||||
if test -f "$bundle_lib/charset.alias"; then
|
||||
export CHARSETALIASDIR="$bundle_lib"
|
||||
fi
|
||||
|
||||
# Extra arguments can be added in environment.sh.
|
||||
EXTRA_ARGS=
|
||||
if test -f "$bundle_res/environment.sh"; then
|
||||
source "$bundle_res/environment.sh"
|
||||
fi
|
||||
|
||||
# Strip out the argument added by the OS.
|
||||
if /bin/expr "x$1" : '^x-psn_' > /dev/null; then
|
||||
shift 1
|
||||
fi
|
||||
|
||||
$EXEC "$bundle_contents/MacOS/$name-bin" "$@" $EXTRA_ARGS
|
@ -1,11 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
rm -rf HexChat.app
|
||||
rm -f *.app.zip
|
||||
|
||||
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
|
||||
zip -9rXq ./HexChat-$(git describe --tags).app.zip ./HexChat.app
|
||||
|
38
plugins/Make.plugin
Normal file
@ -0,0 +1,38 @@
|
||||
# Makefile stub for creating standalone plugin distributions.
|
||||
|
||||
plugin_dist: pg_dist pg_dist/config.status
|
||||
pgi=`cd $(srcdir)/.. && pwd`; cd pg_dist; \
|
||||
$(MAKE) $(AM_MAKEFLAGS) PLUGIN_INCLUDES=-I$$pgi distcheck dist
|
||||
|
||||
pg_dist: pg_distdir pg_dist/configure.in pg_dist/install-sh
|
||||
cd pg_dist \
|
||||
&& libtoolize --copy --force --automake \
|
||||
&& automake --copy --add-missing --foreign \
|
||||
&& autoconf -l ../$(top_srcdir)
|
||||
|
||||
pg_distdir: $(DISTFILES)
|
||||
test -d pg_dist || mkdir pg_dist
|
||||
for dfile in $(DISTFILES); do \
|
||||
test -f $$dfile && cp $$dfile pg_dist \
|
||||
|| test -f $(srcdir)/$$dfile && cp $(srcdir)/$$dfile pg_dist; done
|
||||
sed '/Make.plugin/d' < $(srcdir)/Makefile.am > pg_dist/Makefile.am
|
||||
|
||||
pg_dist/configure.in: $(srcdir)/../plugin-conf.in
|
||||
rm -f pg_dist/configure.in
|
||||
test -f $(srcdir)/config.stub \
|
||||
&& cat $(srcdir)/config.stub > pg_dist/configure.in || true
|
||||
cat $(srcdir)/../plugin-conf.in | \
|
||||
sed 's%@PLUGIN_VERSION@%$(PLUGIN_VERSION)%; \
|
||||
s%@PLUGIN@%$(PLUGIN)%' >> pg_dist/configure.in
|
||||
|
||||
pg_dist/install-sh: pg_distdir
|
||||
cp $(top_srcdir)/install-sh pg_dist
|
||||
|
||||
pg_dist/config.status: pg_dist/configure
|
||||
cd pg_dist \
|
||||
&& test -f config.status && $(SHELL) ./config.status --recheck \
|
||||
|| $(SHELL) ./configure --enable-maintainer-mode
|
||||
|
||||
DISTCLEANFILES = pg_dist/* pg_dist
|
||||
|
||||
#
|
31
plugins/Makefile.am
Normal file
@ -0,0 +1,31 @@
|
||||
# temp. solution while mailcheck & xdcc arn't in SUBDIRS
|
||||
EXTRA_DIST = Make.plugin plugin-conf.in xdcc/xdcc.c xdcc/Makefile.am
|
||||
|
||||
# noinst_HEADERS = hexchat-plugin.h
|
||||
|
||||
if DO_PYTHON
|
||||
pythondir = python
|
||||
endif
|
||||
|
||||
if DO_PERL
|
||||
perldir = perl
|
||||
endif
|
||||
|
||||
if DO_DOAT
|
||||
doatdir = doat
|
||||
endif
|
||||
|
||||
if DO_FISHLIM
|
||||
fishlimdir = fishlim
|
||||
endif
|
||||
|
||||
if DO_CHECKSUM
|
||||
checksumdir = checksum
|
||||
endif
|
||||
|
||||
if DO_SYSINFO
|
||||
sysinfodir = sysinfo
|
||||
endif
|
||||
|
||||
#SUBDIRS = . $(pythondir) $(perldir) mailcheck xdcc
|
||||
SUBDIRS = . $(pythondir) $(perldir) $(checksumdir) $(doatdir) $(fishlimdir) $(sysinfodir)
|
7
plugins/checksum/Makefile.am
Normal file
@ -0,0 +1,7 @@
|
||||
libdir = $(hexchatlibdir)
|
||||
|
||||
lib_LTLIBRARIES = checksum.la
|
||||
checksum_la_SOURCES = checksum.c
|
||||
checksum_la_LDFLAGS = -avoid-version -module
|
||||
checksum_la_LIBADD =
|
||||
AM_CPPFLAGS = $(COMMON_CFLAGS) -I$(srcdir)/../../src/common
|
@ -20,194 +20,217 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <openssl/sha.h>
|
||||
#include <glib.h>
|
||||
#include <glib/gstdio.h>
|
||||
#include <gio/gio.h>
|
||||
|
||||
#ifdef WIN32
|
||||
#ifndef snprintf
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
#define stat _stat64
|
||||
#else
|
||||
/* for INT_MAX */
|
||||
#include <limits.h>
|
||||
#define __USE_LARGEFILE64
|
||||
#define _LARGEFILE_SOURCE
|
||||
#define _LARGEFILE64_SOURCE
|
||||
#endif
|
||||
|
||||
#include "hexchat-plugin.h"
|
||||
|
||||
#define BUFSIZE 32768
|
||||
#define DEFAULT_LIMIT 256 /* default size is 256 MiB */
|
||||
#define SHA256_DIGEST_LENGTH 32
|
||||
#define SHA256_BUFFER_LENGTH 65
|
||||
|
||||
static hexchat_plugin *ph; /* plugin handle */
|
||||
static char name[] = "Checksum";
|
||||
static char desc[] = "Calculate checksum for DCC file transfers";
|
||||
static char version[] = "3.1";
|
||||
|
||||
/* Use of OpenSSL SHA256 interface: http://adamlamers.com/?p=5 */
|
||||
static void
|
||||
set_limit (char *size)
|
||||
sha256_hash_string (unsigned char hash[SHA256_DIGEST_LENGTH], char outputBuffer[65])
|
||||
{
|
||||
int limit = atoi (size);
|
||||
|
||||
if (limit > 0 && limit < INT_MAX)
|
||||
int i;
|
||||
for (i = 0; i < SHA256_DIGEST_LENGTH; i++)
|
||||
{
|
||||
if (hexchat_pluginpref_set_int (ph, "limit", limit))
|
||||
hexchat_printf (ph, "Checksum: File size limit has successfully been set to: %d MiB\n", limit);
|
||||
sprintf (outputBuffer + (i * 2), "%02x", hash[i]);
|
||||
}
|
||||
outputBuffer[64] = 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void
|
||||
sha256 (char *string, char outputBuffer[65])
|
||||
{
|
||||
int i;
|
||||
unsigned char hash[SHA256_DIGEST_LENGTH];
|
||||
SHA256_CTX sha256;
|
||||
|
||||
SHA256_Init (&sha256);
|
||||
SHA256_Update (&sha256, string, strlen (string));
|
||||
SHA256_Final (hash, &sha256);
|
||||
|
||||
for (i = 0; i < SHA256_DIGEST_LENGTH; i++)
|
||||
{
|
||||
sprintf (outputBuffer + (i * 2), "%02x", hash[i]);
|
||||
}
|
||||
outputBuffer[64] = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
sha256_file (char *path, char outputBuffer[65])
|
||||
{
|
||||
int bytesRead;
|
||||
unsigned char *buffer;
|
||||
unsigned char hash[SHA256_DIGEST_LENGTH];
|
||||
SHA256_CTX sha256;
|
||||
|
||||
FILE *file = fopen (path, "rb");
|
||||
if (!file)
|
||||
{
|
||||
return -534;
|
||||
}
|
||||
|
||||
SHA256_Init (&sha256);
|
||||
buffer = malloc (BUFSIZE);
|
||||
bytesRead = 0;
|
||||
|
||||
if (!buffer)
|
||||
{
|
||||
fclose (file);
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
while ((bytesRead = fread (buffer, 1, BUFSIZE, file)))
|
||||
{
|
||||
SHA256_Update (&sha256, buffer, bytesRead);
|
||||
}
|
||||
|
||||
SHA256_Final (hash, &sha256);
|
||||
sha256_hash_string (hash, outputBuffer);
|
||||
|
||||
fclose (file);
|
||||
free (buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
set_limit (char* size)
|
||||
{
|
||||
int buffer = atoi (size);
|
||||
|
||||
if (buffer > 0 && buffer < INT_MAX)
|
||||
{
|
||||
if (hexchat_pluginpref_set_int (ph, "limit", buffer))
|
||||
{
|
||||
hexchat_printf (ph, "File size limit has successfully been set to: %d MiB\n", buffer);
|
||||
}
|
||||
else
|
||||
hexchat_printf (ph, "Checksum: File access error while saving!\n");
|
||||
{
|
||||
hexchat_printf (ph, "File access error while saving!\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hexchat_printf (ph, "Checksum: Invalid input!\n");
|
||||
hexchat_printf (ph, "Invalid input!\n");
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
get_limit (void)
|
||||
get_limit ()
|
||||
{
|
||||
int size = hexchat_pluginpref_get_int (ph, "limit");
|
||||
|
||||
if (size <= 0 || size >= INT_MAX)
|
||||
if (size <= -1 || size >= INT_MAX)
|
||||
{
|
||||
return DEFAULT_LIMIT;
|
||||
}
|
||||
else
|
||||
{
|
||||
return size;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
check_limit (GFile *file)
|
||||
static void
|
||||
print_limit ()
|
||||
{
|
||||
GFileInfo *file_info;
|
||||
goffset file_size;
|
||||
|
||||
file_info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_SIZE, G_FILE_QUERY_INFO_NONE,
|
||||
NULL, NULL);
|
||||
|
||||
if (!file_info)
|
||||
return FALSE;
|
||||
|
||||
file_size = g_file_info_get_size (file_info);
|
||||
g_object_unref (file_info);
|
||||
|
||||
if (file_size > get_limit () * 1048576ll)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
sha256_from_stream (GFileInputStream *file_stream, char out_buf[])
|
||||
{
|
||||
GChecksum *checksum;
|
||||
gssize bytes_read;
|
||||
guint8 digest[SHA256_DIGEST_LENGTH];
|
||||
gsize digest_len = sizeof(digest);
|
||||
guchar buffer[BUFSIZE];
|
||||
gsize i;
|
||||
|
||||
checksum = g_checksum_new (G_CHECKSUM_SHA256);
|
||||
|
||||
while ((bytes_read = g_input_stream_read (G_INPUT_STREAM (file_stream), buffer, sizeof (buffer), NULL, NULL)))
|
||||
{
|
||||
if (bytes_read == -1)
|
||||
{
|
||||
g_checksum_free (checksum);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_checksum_update (checksum, buffer, bytes_read);
|
||||
}
|
||||
|
||||
g_checksum_get_digest (checksum, digest, &digest_len);
|
||||
g_checksum_free (checksum);
|
||||
|
||||
for (i = 0; i < SHA256_DIGEST_LENGTH; i++)
|
||||
{
|
||||
/* out_buf will be exactly SHA256_BUFFER_LENGTH including null */
|
||||
g_sprintf (out_buf + (i * 2), "%02x", digest[i]);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
sha256_from_file (char *filename, char out_buf[])
|
||||
{
|
||||
GFileInputStream *file_stream;
|
||||
char *filename_fs;
|
||||
GFile *file;
|
||||
|
||||
filename_fs = g_filename_from_utf8 (filename, -1, NULL, NULL, NULL);
|
||||
if (!filename_fs)
|
||||
{
|
||||
hexchat_printf (ph, "Checksum: Invalid filename (%s)\n", filename);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
file = g_file_new_for_path (filename_fs);
|
||||
g_free (filename_fs);
|
||||
if (!file)
|
||||
{
|
||||
hexchat_printf (ph, "Checksum: Failed to open %s\n", filename);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!check_limit (file))
|
||||
{
|
||||
hexchat_printf (ph, "Checksum: %s is larger than size limit. You can increase it with /CHECKSUM SET.\n", filename);
|
||||
g_object_unref (file);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
file_stream = g_file_read (file, NULL, NULL);
|
||||
if (!file_stream)
|
||||
{
|
||||
hexchat_printf (ph, "Checksum: Failed to read file %s\n", filename);
|
||||
g_object_unref (file);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!sha256_from_stream (file_stream, out_buf))
|
||||
{
|
||||
hexchat_printf (ph, "Checksum: Failed to generate checksum for %s\n", filename);
|
||||
g_object_unref (file_stream);
|
||||
g_object_unref (file);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_object_unref (file_stream);
|
||||
g_object_unref (file);
|
||||
return TRUE;
|
||||
hexchat_printf (ph, "File size limit for checksums: %d MiB", get_limit ());
|
||||
}
|
||||
|
||||
static int
|
||||
dccrecv_cb (char *word[], void *userdata)
|
||||
{
|
||||
const char *dcc_completed_dir;
|
||||
char *filename, checksum[SHA256_BUFFER_LENGTH];
|
||||
int result;
|
||||
struct stat buffer; /* buffer for storing file info */
|
||||
char sum[65]; /* buffer for checksum */
|
||||
const char *file;
|
||||
char *cfile;
|
||||
|
||||
/* Print in the privmsg tab of the sender */
|
||||
hexchat_set_context (ph, hexchat_find_context (ph, NULL, word[3]));
|
||||
|
||||
if (hexchat_get_prefs (ph, "dcc_completed_dir", &dcc_completed_dir, NULL) == 1 && dcc_completed_dir[0] != '\0')
|
||||
filename = g_build_filename (dcc_completed_dir, word[1], NULL);
|
||||
else
|
||||
filename = g_strdup (word[2]);
|
||||
|
||||
if (sha256_from_file (filename, checksum))
|
||||
if (hexchat_get_prefs (ph, "dcc_completed_dir", &file, NULL) == 1 && file[0] != 0)
|
||||
{
|
||||
hexchat_printf (ph, "SHA-256 checksum for %s (local): %s\n", word[1], checksum);
|
||||
cfile = g_strconcat (file, G_DIR_SEPARATOR_S, word[1], NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
cfile = g_strdup(word[2]);
|
||||
}
|
||||
|
||||
g_free (filename);
|
||||
result = stat (cfile, &buffer);
|
||||
if (result == 0) /* stat returns 0 on success */
|
||||
{
|
||||
if (buffer.st_size <= (unsigned long long) get_limit () * 1048576)
|
||||
{
|
||||
sha256_file (cfile, sum); /* file is the full filename even if completed dir set */
|
||||
/* try to print the checksum in the privmsg tab of the sender */
|
||||
hexchat_set_context (ph, hexchat_find_context (ph, NULL, word[3]));
|
||||
hexchat_printf (ph, "SHA-256 checksum for %s (local): %s\n", word[1], sum);
|
||||
}
|
||||
else
|
||||
{
|
||||
hexchat_set_context (ph, hexchat_find_context (ph, NULL, word[3]));
|
||||
hexchat_printf (ph, "SHA-256 checksum for %s (local): (size limit reached, no checksum calculated, you can increase it with /CHECKSUM INC)\n", word[1]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hexchat_printf (ph, "File access error!\n");
|
||||
}
|
||||
|
||||
g_free (cfile);
|
||||
return HEXCHAT_EAT_NONE;
|
||||
}
|
||||
|
||||
static int
|
||||
dccoffer_cb (char *word[], void *userdata)
|
||||
{
|
||||
char checksum[SHA256_BUFFER_LENGTH];
|
||||
int result;
|
||||
struct stat buffer; /* buffer for storing file info */
|
||||
char sum[65]; /* buffer for checksum */
|
||||
|
||||
/* Print in the privmsg tab of the receiver */
|
||||
hexchat_set_context (ph, hexchat_find_context (ph, NULL, word[3]));
|
||||
|
||||
if (sha256_from_file (word[3], checksum))
|
||||
result = stat (word[3], &buffer);
|
||||
if (result == 0) /* stat returns 0 on success */
|
||||
{
|
||||
hexchat_commandf (ph, "quote PRIVMSG %s :SHA-256 checksum for %s (remote): %s", word[2], word[1], checksum);
|
||||
if (buffer.st_size <= (unsigned long long) get_limit () * 1048576)
|
||||
{
|
||||
sha256_file (word[3], sum); /* word[3] is the full filename */
|
||||
hexchat_commandf (ph, "quote PRIVMSG %s :SHA-256 checksum for %s (remote): %s", word[2], word[1], sum);
|
||||
}
|
||||
else
|
||||
{
|
||||
hexchat_set_context (ph, hexchat_find_context (ph, NULL, word[3]));
|
||||
hexchat_printf (ph, "quote PRIVMSG %s :SHA-256 checksum for %s (remote): (size limit reached, no checksum calculated)", word[2], word[1]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hexchat_printf (ph, "File access error!\n");
|
||||
}
|
||||
|
||||
return HEXCHAT_EAT_NONE;
|
||||
@ -218,7 +241,7 @@ checksum (char *word[], char *word_eol[], void *userdata)
|
||||
{
|
||||
if (!g_ascii_strcasecmp ("GET", word[2]))
|
||||
{
|
||||
hexchat_printf (ph, "File size limit for checksums: %d MiB", get_limit ());
|
||||
print_limit ();
|
||||
}
|
||||
else if (!g_ascii_strcasecmp ("SET", word[2]))
|
||||
{
|
||||
@ -231,7 +254,7 @@ checksum (char *word[], char *word_eol[], void *userdata)
|
||||
hexchat_printf (ph, " SET <filesize> - set the maximum file size (in MiB) to be hashed\n");
|
||||
}
|
||||
|
||||
return HEXCHAT_EAT_ALL;
|
||||
return HEXCHAT_EAT_NONE;
|
||||
}
|
||||
|
||||
int
|
||||
@ -249,7 +272,7 @@ hexchat_plugin_init (hexchat_plugin *plugin_handle, char **plugin_name, char **p
|
||||
hexchat_pluginpref_set_int (ph, "limit", DEFAULT_LIMIT);
|
||||
}
|
||||
|
||||
hexchat_hook_command (ph, "CHECKSUM", HEXCHAT_PRI_NORM, checksum, "Usage: /CHECKSUM GET|SET", NULL);
|
||||
hexchat_hook_command (ph, "CHECKSUM", HEXCHAT_PRI_NORM, checksum, "Usage: /CHECKSUM GET|SET", 0);
|
||||
hexchat_hook_print (ph, "DCC RECV Complete", HEXCHAT_PRI_NORM, dccrecv_cb, NULL);
|
||||
hexchat_hook_print (ph, "DCC Offer", HEXCHAT_PRI_NORM, dccoffer_cb, NULL);
|
||||
|
||||
|
@ -1,8 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup Label="Configuration">
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<PlatformToolset>v120</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
@ -20,19 +19,57 @@
|
||||
<RootNamespace>checksum</RootNamespace>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="..\..\win32\hexchat.props" />
|
||||
<PropertyGroup>
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="..\..\win32\hexchat.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="..\..\win32\hexchat.props" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<TargetName>hcchecksum</TargetName>
|
||||
<OutDir>$(HexChatRel)plugins\</OutDir>
|
||||
<OutDir>$(HexChatBin)</OutDir>
|
||||
<IntDir>$(HexChatObj)$(ProjectName)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<TargetName>hcchecksum</TargetName>
|
||||
<OutDir>$(HexChatBin)</OutDir>
|
||||
<IntDir>$(HexChatObj)$(ProjectName)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;CHECKSUM_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>$(DepsRoot)\include;$(Glib);..\..\src\common;$(HexChatLib);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>$(DepsRoot)\include;$(Glib);..\..\src\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<ModuleDefinitionFile>checksum.def</ModuleDefinitionFile>
|
||||
<AdditionalLibraryDirectories>$(DepsRoot)\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>$(DepLibs);%(AdditionalDependencies)</AdditionalDependencies>
|
||||
@ -40,10 +77,19 @@
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;_WIN64;_AMD64_;NDEBUG;_WINDOWS;_USRDLL;CHECKSUM_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>$(DepsRoot)\include;$(Glib);..\..\src\common;$(HexChatLib);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>$(DepsRoot)\include;$(Glib);..\..\src\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<ModuleDefinitionFile>checksum.def</ModuleDefinitionFile>
|
||||
<AdditionalLibraryDirectories>$(DepsRoot)\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>$(DepLibs);%(AdditionalDependencies)</AdditionalDependencies>
|
||||
@ -56,4 +102,6 @@
|
||||
<None Include="checksum.def" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
</Project>
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
@ -1,7 +0,0 @@
|
||||
shared_module('checksum', 'checksum.c',
|
||||
dependencies: [libgio_dep, hexchat_plugin_dep],
|
||||
install: true,
|
||||
install_dir: plugindir,
|
||||
name_prefix: '',
|
||||
vs_module_defs: 'checksum.def',
|
||||
)
|
332
plugins/dns/dns.c
Normal file
@ -0,0 +1,332 @@
|
||||
/* HexChat Win32 DNS Plugin
|
||||
* Copyright (C) 2003-2004 Peter Zelezny.
|
||||
* Copyright (C) 2012 Berke Viktor.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
/*
|
||||
* Requires MS Visual Studio and IPV6 headers to compile (run nmake).
|
||||
* Compiling with gcc (mingw) will fail due to missing gai_strerror.
|
||||
*/
|
||||
|
||||
#define DNS_VERSION "2.4"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#define USE_IPV6
|
||||
|
||||
#ifdef WIN32
|
||||
#ifdef USE_IPV6
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#else
|
||||
#include <winsock2.h>
|
||||
#endif
|
||||
#include <io.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
|
||||
#include "hexchat-plugin.h"
|
||||
#include "thread.h"
|
||||
|
||||
#define HELP "Usage: DNS <nickname|hostname|numerical address>\n"
|
||||
#define HEAD "\0034[DNS]\017\t"
|
||||
|
||||
#define PIPE_READ 0
|
||||
#define PIPE_WRITE 1
|
||||
#define MAX_HOSTNAME 128
|
||||
|
||||
static hexchat_plugin *ph;
|
||||
static thread *active_thread = NULL;
|
||||
|
||||
|
||||
static int
|
||||
waitline (void *source, char *buf, int bufsize)
|
||||
{
|
||||
int i = 0;
|
||||
int len;
|
||||
|
||||
while(1)
|
||||
{
|
||||
len = 1;
|
||||
/* we can't read() here, due to glib's giowin32 */
|
||||
if (ph->hexchat_read_fd (ph, source, buf + i, &len) != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if (buf[i] == '\n' || bufsize == i + 1)
|
||||
{
|
||||
buf[i] = 0;
|
||||
return i;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
static void *
|
||||
thread_function (void *ud)
|
||||
{
|
||||
#ifdef USE_IPV6
|
||||
struct addrinfo *ent;
|
||||
struct addrinfo *cur;
|
||||
struct addrinfo hints;
|
||||
#else
|
||||
struct hostent *ent;
|
||||
#endif
|
||||
thread *th = ud;
|
||||
int fd = th->pipe_fd[PIPE_WRITE];
|
||||
int ret;
|
||||
char ipstring[MAX_HOSTNAME];
|
||||
char reverse[MAX_HOSTNAME];
|
||||
// int i;
|
||||
|
||||
active_thread = th;
|
||||
|
||||
#ifdef USE_IPV6
|
||||
memset (&hints, 0, sizeof (hints));
|
||||
hints.ai_family = PF_UNSPEC; /* support ipv6 and ipv4 */
|
||||
hints.ai_flags = AI_CANONNAME;
|
||||
// hints.ai_socktype = SOCK_STREAM;
|
||||
|
||||
ret = getaddrinfo (th->userdata, NULL, &hints, &ent);
|
||||
if (ret != 0)
|
||||
{
|
||||
sprintf (ipstring, "1%d\n", ret); /* failed */
|
||||
write (fd, ipstring, strlen (ipstring));
|
||||
// Sleep (3000);
|
||||
active_thread = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// i = 0;
|
||||
cur = ent;
|
||||
while (cur)
|
||||
{
|
||||
/* find the numeric IP number */
|
||||
ipstring[0] = 0;
|
||||
getnameinfo (cur->ai_addr, cur->ai_addrlen,
|
||||
ipstring, sizeof (ipstring), NULL, 0, NI_NUMERICHOST);
|
||||
|
||||
if (cur->ai_canonname)
|
||||
{
|
||||
/* force reverse lookup if canonname & ipstring are the same */
|
||||
if (/*i == 0 &&*/ strcmp (cur->ai_canonname, ipstring) == 0)
|
||||
goto lamecode;
|
||||
}
|
||||
|
||||
if (cur->ai_canonname)
|
||||
{
|
||||
write (fd, "0", 1);
|
||||
write (fd, ipstring, strlen (ipstring));
|
||||
write (fd, "\n", 1);
|
||||
write (fd, cur->ai_canonname, strlen (cur->ai_canonname));
|
||||
} else
|
||||
{
|
||||
lamecode:
|
||||
// ret = 1;
|
||||
// if (i == 0)
|
||||
{
|
||||
/* reverse lookup */
|
||||
reverse[0] = 0;
|
||||
ret = getnameinfo (cur->ai_addr, cur->ai_addrlen,
|
||||
reverse, sizeof (reverse), NULL, 0, NI_NAMEREQD);
|
||||
}
|
||||
|
||||
write (fd, "0", 1);
|
||||
write (fd, ipstring, strlen (ipstring));
|
||||
|
||||
write (fd, "\n", 1);
|
||||
if (ret == 0)
|
||||
write (fd, reverse, strlen (reverse));
|
||||
}
|
||||
write (fd, "\n", 1);
|
||||
|
||||
// i++;
|
||||
cur = cur->ai_next;
|
||||
}
|
||||
|
||||
/* tell the parent we're done */
|
||||
write (fd, "2\n", 2);
|
||||
freeaddrinfo (ent);
|
||||
|
||||
#else
|
||||
ent = gethostbyname (th->userdata);
|
||||
if (ent)
|
||||
{
|
||||
write (fd, "0", 1);
|
||||
write (fd, ent->h_name, strlen (ent->h_name));
|
||||
write (fd, "\n", 1);
|
||||
write (fd, ent->h_name, strlen (ent->h_name));
|
||||
write (fd, "\n", 1);
|
||||
write (fd, "2\n", 2);
|
||||
} else
|
||||
{
|
||||
write (fd, "10\n", 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Sleep (3000);
|
||||
active_thread = NULL; /* race condition, better than nothing */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
dns_close_pipe (int fd)
|
||||
{
|
||||
close (fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* read messages comming from the child (through the pipe) */
|
||||
|
||||
static int
|
||||
dns_read_cb (int fd, int flags, thread *th, void *source)
|
||||
{
|
||||
char buf[512];
|
||||
char buf2[512];
|
||||
|
||||
while (waitline (source, buf, sizeof (buf)))
|
||||
{
|
||||
switch (buf[0])
|
||||
{
|
||||
case '0': /* got data to show */
|
||||
waitline (source, buf2, sizeof (buf2));
|
||||
if (buf2[0] == 0)
|
||||
hexchat_printf(ph, HEAD"\002Numerical\002: %s\n", buf + 1);
|
||||
else
|
||||
hexchat_printf(ph, HEAD"\002Canonical\002: %s \002Numerical\002: %s\n", buf2, buf + 1);
|
||||
return 1;
|
||||
|
||||
case '1': /* failed */
|
||||
hexchat_printf(ph, HEAD"Lookup failed. %s\n", gai_strerrorA (atoi (buf + 1)));
|
||||
|
||||
case '2': /* done */
|
||||
// close (th->pipe_fd[PIPE_WRITE]);
|
||||
// close (th->pipe_fd[PIPE_READ]);
|
||||
hexchat_hook_timer(ph, 3000, dns_close_pipe, (void *)th->pipe_fd[PIPE_WRITE]);
|
||||
hexchat_hook_timer(ph, 4000, dns_close_pipe, (void *)th->pipe_fd[PIPE_READ]);
|
||||
free (th->userdata); /* hostname strdup'ed */
|
||||
free (th);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* find hostname from nickname (search the userlist, current chan only) */
|
||||
|
||||
static char *
|
||||
find_nick_host (char *nick)
|
||||
{
|
||||
hexchat_list *list;
|
||||
char *at;
|
||||
const char *host;
|
||||
|
||||
list = hexchat_list_get (ph, "users");
|
||||
if (!list)
|
||||
return NULL;
|
||||
|
||||
while (hexchat_list_next (ph, list))
|
||||
{
|
||||
if (stricmp (nick, hexchat_list_str (ph, list, "nick")) == 0)
|
||||
{
|
||||
host = hexchat_list_str (ph, list, "host");
|
||||
if (host)
|
||||
{
|
||||
at = strrchr (host, '@');
|
||||
if (at)
|
||||
return at + 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
dns_cmd_cb (char *word[], char *word_eol[], void *ud)
|
||||
{
|
||||
thread *th;
|
||||
char *nickhost;
|
||||
|
||||
if (!word[2][0])
|
||||
{
|
||||
hexchat_print (ph, HELP);
|
||||
return HEXCHAT_EAT_ALL;
|
||||
}
|
||||
|
||||
th = thread_new ();
|
||||
if (th)
|
||||
{
|
||||
nickhost = find_nick_host (word[2]);
|
||||
if (nickhost)
|
||||
{
|
||||
hexchat_printf (ph, HEAD"Looking up %s (%s)...\n", nickhost, word[2]);
|
||||
th->userdata = strdup (nickhost);
|
||||
} else
|
||||
{
|
||||
hexchat_printf (ph, HEAD"Looking up %s...\n", word[2]);
|
||||
th->userdata = strdup (word[2]);
|
||||
}
|
||||
|
||||
if (thread_start (th, thread_function, th))
|
||||
{
|
||||
hexchat_hook_fd(ph, th->pipe_fd[PIPE_READ],
|
||||
HEXCHAT_FD_READ | HEXCHAT_FD_EXCEPTION | HEXCHAT_FD_NOTSOCKET,
|
||||
(void *)dns_read_cb, th);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return HEXCHAT_EAT_ALL;
|
||||
}
|
||||
|
||||
int
|
||||
hexchat_plugin_deinit (hexchat_plugin *plugin_handle)
|
||||
{
|
||||
while (active_thread) /* children will set this var to NULL soon... */
|
||||
{
|
||||
Sleep (1000);
|
||||
}
|
||||
hexchat_printf (ph, "DNS plugin unloaded\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
hexchat_plugin_init
|
||||
(hexchat_plugin *plugin_handle, char **plugin_name,
|
||||
char **plugin_desc, char **plugin_version, char *arg)
|
||||
{
|
||||
/* we need to save this for use with any hexchat_* functions */
|
||||
ph = plugin_handle;
|
||||
|
||||
*plugin_name = "DNS";
|
||||
*plugin_desc = "Threaded IPv4/6 DNS Command";
|
||||
*plugin_version = DNS_VERSION;
|
||||
|
||||
hexchat_hook_command(ph, "DNS", HEXCHAT_PRI_LOW, dns_cmd_cb, HELP, 0);
|
||||
hexchat_printf (ph, "DNS plugin loaded\n");
|
||||
|
||||
return 1; /* return 1 for success */
|
||||
}
|
3
plugins/dns/dns.def
Normal file
@ -0,0 +1,3 @@
|
||||
EXPORTS
|
||||
hexchat_plugin_init
|
||||
hexchat_plugin_deinit
|
111
plugins/dns/dns.vcxproj
Normal file
@ -0,0 +1,111 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup Label="Configuration">
|
||||
<PlatformToolset>v120</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{3786FA8C-3E76-45E3-984E-FCCFF44729C9}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>dns</RootNamespace>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="..\..\win32\hexchat.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="..\..\win32\hexchat.props" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<TargetName>hcdns</TargetName>
|
||||
<OutDir>$(HexChatBin)</OutDir>
|
||||
<IntDir>$(HexChatObj)$(ProjectName)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<TargetName>hcdns</TargetName>
|
||||
<OutDir>$(HexChatBin)</OutDir>
|
||||
<IntDir>$(HexChatObj)$(ProjectName)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;DNS_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>..\..\src\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalLibraryDirectories>$(DepsRoot)\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>$(DepLibs);%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<ModuleDefinitionFile>dns.def</ModuleDefinitionFile>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;_WIN64;_AMD64_;NDEBUG;_WINDOWS;_USRDLL;DNS_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>..\..\src\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalLibraryDirectories>$(DepsRoot)\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>$(DepLibs);%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<ModuleDefinitionFile>dns.def</ModuleDefinitionFile>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<None Include="dns.def" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="dns.c" />
|
||||
<ClCompile Include="thread.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="thread.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
35
plugins/dns/dns.vcxproj.filters
Normal file
@ -0,0 +1,35 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="dns.def">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="dns.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="thread.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="thread.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
34
plugins/dns/thread.c
Normal file
@ -0,0 +1,34 @@
|
||||
#include <io.h>
|
||||
#include <fcntl.h>
|
||||
#include "thread.h"
|
||||
|
||||
thread *
|
||||
thread_new (void)
|
||||
{
|
||||
thread *th;
|
||||
|
||||
th = calloc (1, sizeof (*th));
|
||||
if (!th)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (_pipe (th->pipe_fd, 4096, _O_BINARY) == -1)
|
||||
{
|
||||
free (th);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return th;
|
||||
}
|
||||
|
||||
int
|
||||
thread_start (thread *th, void *(*start_routine)(void *), void *arg)
|
||||
{
|
||||
DWORD id;
|
||||
|
||||
CloseHandle (CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE)start_routine, arg, 0, (DWORD *)&id));
|
||||
th->threadid = id;
|
||||
|
||||
return 1;
|
||||
}
|
11
plugins/dns/thread.h
Normal file
@ -0,0 +1,11 @@
|
||||
#include <windows.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
DWORD threadid;
|
||||
int pipe_fd[2];
|
||||
void *userdata;
|
||||
} thread;
|
||||
|
||||
thread *thread_new (void);
|
||||
int thread_start (thread *th, void *(*start_routine)(void *), void *arg);
|
8
plugins/doat/Makefile.am
Normal file
@ -0,0 +1,8 @@
|
||||
libdir = $(hexchatlibdir)
|
||||
|
||||
lib_LTLIBRARIES = doat.la
|
||||
doat_la_SOURCES = doat.c
|
||||
doat_la_LDFLAGS = -avoid-version -module
|
||||
doat_la_LIBADD =
|
||||
AM_CPPFLAGS = $(COMMON_CFLAGS) -I$(srcdir)/../../src/common
|
||||
|
94
plugins/doat/doat.c
Normal file
@ -0,0 +1,94 @@
|
||||
/* This program is free software. It comes without any warranty, to
|
||||
* the extent permitted by applicable law. You can redistribute it
|
||||
* and/or modify it under the terms of the Do What The Fuck You Want
|
||||
* To Public License, Version 2, as published by Sam Hocevar. See
|
||||
* http://sam.zoy.org/wtfpl/COPYING or http://lwsitu.com/xchat/COPYING
|
||||
* for more details. */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "hexchat-plugin.h"
|
||||
|
||||
static hexchat_plugin *ph;
|
||||
|
||||
static int
|
||||
parse_command( char *word[], char *word_eol[], void *userdata ) {
|
||||
char *channel = NULL, *server = NULL, *token = NULL;
|
||||
/* char *save_ptr1 = NULL;*/
|
||||
char *str1 = NULL;
|
||||
char *delimiter = NULL;
|
||||
|
||||
hexchat_context *ctx = NULL;
|
||||
|
||||
if( word[2] != NULL && word[3] != NULL ) {
|
||||
for( str1 = word[2]; ; str1 = NULL ) {
|
||||
/* token = strtok_r( str1, ",", &save_ptr1 );*/
|
||||
token = strtok( str1, "," );
|
||||
/* printf( "token: %s\n", token );*/
|
||||
|
||||
if( token == NULL ) {
|
||||
break;
|
||||
}
|
||||
|
||||
channel = strdup( token );
|
||||
|
||||
delimiter = strchr( channel, '/' );
|
||||
|
||||
server = NULL;
|
||||
if( delimiter != NULL ) {
|
||||
*delimiter = '\0';
|
||||
|
||||
if( strlen( delimiter + 1 ) > 0 ) {
|
||||
server = strdup( delimiter + 1 );
|
||||
}
|
||||
}
|
||||
|
||||
/* /Network form */
|
||||
if( strlen( channel ) == 0 ) {
|
||||
free( channel );
|
||||
channel = NULL;
|
||||
}
|
||||
|
||||
/* printf( "channel[%s] server[%s]\n", channel, server );*/
|
||||
|
||||
if( (ctx = hexchat_find_context( ph, server, channel ) ) != NULL ) {
|
||||
if( hexchat_set_context( ph, ctx ) ) {
|
||||
hexchat_command( ph, word_eol[3] );
|
||||
}
|
||||
}
|
||||
|
||||
if( channel != NULL ) {
|
||||
free( channel );
|
||||
}
|
||||
|
||||
if( server != NULL ) {
|
||||
free( server );
|
||||
}
|
||||
}
|
||||
}
|
||||
return HEXCHAT_EAT_HEXCHAT;
|
||||
}
|
||||
|
||||
int
|
||||
hexchat_plugin_init( hexchat_plugin * plugin_handle, char **plugin_name,
|
||||
char **plugin_desc, char **plugin_version, char *arg ) {
|
||||
|
||||
ph = plugin_handle;
|
||||
*plugin_name = "Do At";
|
||||
*plugin_version = "1.0001";
|
||||
*plugin_desc = "Perform an arbitrary command on multiple channels";
|
||||
|
||||
hexchat_hook_command( ph, "doat", HEXCHAT_PRI_NORM, parse_command, "DOAT [channel,list,/network] [command], perform a command on multiple contexts", NULL );
|
||||
|
||||
hexchat_print (ph, "Do At plugin loaded\n");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
hexchat_plugin_deinit (void)
|
||||
{
|
||||
hexchat_print (ph, "Do At plugin unloaded\n");
|
||||
return 1;
|
||||
}
|
3
plugins/doat/doat.def
Normal file
@ -0,0 +1,3 @@
|
||||
EXPORTS
|
||||
hexchat_plugin_init
|
||||
hexchat_plugin_deinit
|
103
plugins/doat/doat.vcxproj
Normal file
@ -0,0 +1,103 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup Label="Configuration">
|
||||
<PlatformToolset>v120</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{4980AF24-9D42-427D-A8E6-0DF3B97C455D}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>doat</RootNamespace>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="..\..\win32\hexchat.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="..\..\win32\hexchat.props" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<TargetName>hcdoat</TargetName>
|
||||
<OutDir>$(HexChatBin)</OutDir>
|
||||
<IntDir>$(HexChatObj)$(ProjectName)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<TargetName>hcdoat</TargetName>
|
||||
<OutDir>$(HexChatBin)</OutDir>
|
||||
<IntDir>$(HexChatObj)$(ProjectName)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;DOAT_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>..\..\src\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<ModuleDefinitionFile>doat.def</ModuleDefinitionFile>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;_WIN64;_AMD64_;NDEBUG;_WINDOWS;_USRDLL;DOAT_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>..\..\src\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<ModuleDefinitionFile>doat.def</ModuleDefinitionFile>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="doat.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="doat.def" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
@ -5,18 +5,19 @@
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="win8_provider.cpp">
|
||||
<ClCompile Include="doat.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
<ItemGroup>
|
||||
<None Include="doat.def">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
</Project>
|
502
plugins/ewc/COPYING
Normal file
@ -0,0 +1,502 @@
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 2.1, February 1999
|
||||
|
||||
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
[This is the first released version of the Lesser GPL. It also counts
|
||||
as the successor of the GNU Library Public License, version 2, hence
|
||||
the version number 2.1.]
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
Licenses are intended to guarantee your freedom to share and change
|
||||
free software--to make sure the software is free for all its users.
|
||||
|
||||
This license, the Lesser General Public License, applies to some
|
||||
specially designated software packages--typically libraries--of the
|
||||
Free Software Foundation and other authors who decide to use it. You
|
||||
can use it too, but we suggest you first think carefully about whether
|
||||
this license or the ordinary General Public License is the better
|
||||
strategy to use in any particular case, based on the explanations below.
|
||||
|
||||
When we speak of free software, we are referring to freedom of use,
|
||||
not price. Our General Public Licenses are designed to make sure that
|
||||
you have the freedom to distribute copies of free software (and charge
|
||||
for this service if you wish); that you receive source code or can get
|
||||
it if you want it; that you can change the software and use pieces of
|
||||
it in new free programs; and that you are informed that you can do
|
||||
these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
distributors to deny you these rights or to ask you to surrender these
|
||||
rights. These restrictions translate to certain responsibilities for
|
||||
you if you distribute copies of the library or if you modify it.
|
||||
|
||||
For example, if you distribute copies of the library, whether gratis
|
||||
or for a fee, you must give the recipients all the rights that we gave
|
||||
you. You must make sure that they, too, receive or can get the source
|
||||
code. If you link other code with the library, you must provide
|
||||
complete object files to the recipients, so that they can relink them
|
||||
with the library after making changes to the library and recompiling
|
||||
it. And you must show them these terms so they know their rights.
|
||||
|
||||
We protect your rights with a two-step method: (1) we copyright the
|
||||
library, and (2) we offer you this license, which gives you legal
|
||||
permission to copy, distribute and/or modify the library.
|
||||
|
||||
To protect each distributor, we want to make it very clear that
|
||||
there is no warranty for the free library. Also, if the library is
|
||||
modified by someone else and passed on, the recipients should know
|
||||
that what they have is not the original version, so that the original
|
||||
author's reputation will not be affected by problems that might be
|
||||
introduced by others.
|
||||
|
||||
Finally, software patents pose a constant threat to the existence of
|
||||
any free program. We wish to make sure that a company cannot
|
||||
effectively restrict the users of a free program by obtaining a
|
||||
restrictive license from a patent holder. Therefore, we insist that
|
||||
any patent license obtained for a version of the library must be
|
||||
consistent with the full freedom of use specified in this license.
|
||||
|
||||
Most GNU software, including some libraries, is covered by the
|
||||
ordinary GNU General Public License. This license, the GNU Lesser
|
||||
General Public License, applies to certain designated libraries, and
|
||||
is quite different from the ordinary General Public License. We use
|
||||
this license for certain libraries in order to permit linking those
|
||||
libraries into non-free programs.
|
||||
|
||||
When a program is linked with a library, whether statically or using
|
||||
a shared library, the combination of the two is legally speaking a
|
||||
combined work, a derivative of the original library. The ordinary
|
||||
General Public License therefore permits such linking only if the
|
||||
entire combination fits its criteria of freedom. The Lesser General
|
||||
Public License permits more lax criteria for linking other code with
|
||||
the library.
|
||||
|
||||
We call this license the "Lesser" General Public License because it
|
||||
does Less to protect the user's freedom than the ordinary General
|
||||
Public License. It also provides other free software developers Less
|
||||
of an advantage over competing non-free programs. These disadvantages
|
||||
are the reason we use the ordinary General Public License for many
|
||||
libraries. However, the Lesser license provides advantages in certain
|
||||
special circumstances.
|
||||
|
||||
For example, on rare occasions, there may be a special need to
|
||||
encourage the widest possible use of a certain library, so that it becomes
|
||||
a de-facto standard. To achieve this, non-free programs must be
|
||||
allowed to use the library. A more frequent case is that a free
|
||||
library does the same job as widely used non-free libraries. In this
|
||||
case, there is little to gain by limiting the free library to free
|
||||
software only, so we use the Lesser General Public License.
|
||||
|
||||
In other cases, permission to use a particular library in non-free
|
||||
programs enables a greater number of people to use a large body of
|
||||
free software. For example, permission to use the GNU C Library in
|
||||
non-free programs enables many more people to use the whole GNU
|
||||
operating system, as well as its variant, the GNU/Linux operating
|
||||
system.
|
||||
|
||||
Although the Lesser General Public License is Less protective of the
|
||||
users' freedom, it does ensure that the user of a program that is
|
||||
linked with the Library has the freedom and the wherewithal to run
|
||||
that program using a modified version of the Library.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow. Pay close attention to the difference between a
|
||||
"work based on the library" and a "work that uses the library". The
|
||||
former contains code derived from the library, whereas the latter must
|
||||
be combined with the library in order to run.
|
||||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License Agreement applies to any software library or other
|
||||
program which contains a notice placed by the copyright holder or
|
||||
other authorized party saying it may be distributed under the terms of
|
||||
this Lesser General Public License (also called "this License").
|
||||
Each licensee is addressed as "you".
|
||||
|
||||
A "library" means a collection of software functions and/or data
|
||||
prepared so as to be conveniently linked with application programs
|
||||
(which use some of those functions and data) to form executables.
|
||||
|
||||
The "Library", below, refers to any such software library or work
|
||||
which has been distributed under these terms. A "work based on the
|
||||
Library" means either the Library or any derivative work under
|
||||
copyright law: that is to say, a work containing the Library or a
|
||||
portion of it, either verbatim or with modifications and/or translated
|
||||
straightforwardly into another language. (Hereinafter, translation is
|
||||
included without limitation in the term "modification".)
|
||||
|
||||
"Source code" for a work means the preferred form of the work for
|
||||
making modifications to it. For a library, complete source code means
|
||||
all the source code for all modules it contains, plus any associated
|
||||
interface definition files, plus the scripts used to control compilation
|
||||
and installation of the library.
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running a program using the Library is not restricted, and output from
|
||||
such a program is covered only if its contents constitute a work based
|
||||
on the Library (independent of the use of the Library in a tool for
|
||||
writing it). Whether that is true depends on what the Library does
|
||||
and what the program that uses the Library does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Library's
|
||||
complete source code as you receive it, in any medium, provided that
|
||||
you conspicuously and appropriately publish on each copy an
|
||||
appropriate copyright notice and disclaimer of warranty; keep intact
|
||||
all the notices that refer to this License and to the absence of any
|
||||
warranty; and distribute a copy of this License along with the
|
||||
Library.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy,
|
||||
and you may at your option offer warranty protection in exchange for a
|
||||
fee.
|
||||
|
||||
2. You may modify your copy or copies of the Library or any portion
|
||||
of it, thus forming a work based on the Library, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) The modified work must itself be a software library.
|
||||
|
||||
b) You must cause the files modified to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
c) You must cause the whole of the work to be licensed at no
|
||||
charge to all third parties under the terms of this License.
|
||||
|
||||
d) If a facility in the modified Library refers to a function or a
|
||||
table of data to be supplied by an application program that uses
|
||||
the facility, other than as an argument passed when the facility
|
||||
is invoked, then you must make a good faith effort to ensure that,
|
||||
in the event an application does not supply such function or
|
||||
table, the facility still operates, and performs whatever part of
|
||||
its purpose remains meaningful.
|
||||
|
||||
(For example, a function in a library to compute square roots has
|
||||
a purpose that is entirely well-defined independent of the
|
||||
application. Therefore, Subsection 2d requires that any
|
||||
application-supplied function or table used by this function must
|
||||
be optional: if the application does not supply it, the square
|
||||
root function must still compute square roots.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Library,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Library, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote
|
||||
it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Library.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Library
|
||||
with the Library (or with a work based on the Library) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||
License instead of this License to a given copy of the Library. To do
|
||||
this, you must alter all the notices that refer to this License, so
|
||||
that they refer to the ordinary GNU General Public License, version 2,
|
||||
instead of to this License. (If a newer version than version 2 of the
|
||||
ordinary GNU General Public License has appeared, then you can specify
|
||||
that version instead if you wish.) Do not make any other change in
|
||||
these notices.
|
||||
|
||||
Once this change is made in a given copy, it is irreversible for
|
||||
that copy, so the ordinary GNU General Public License applies to all
|
||||
subsequent copies and derivative works made from that copy.
|
||||
|
||||
This option is useful when you wish to copy part of the code of
|
||||
the Library into a program that is not a library.
|
||||
|
||||
4. You may copy and distribute the Library (or a portion or
|
||||
derivative of it, under Section 2) in object code or executable form
|
||||
under the terms of Sections 1 and 2 above provided that you accompany
|
||||
it with the complete corresponding machine-readable source code, which
|
||||
must be distributed under the terms of Sections 1 and 2 above on a
|
||||
medium customarily used for software interchange.
|
||||
|
||||
If distribution of object code is made by offering access to copy
|
||||
from a designated place, then offering equivalent access to copy the
|
||||
source code from the same place satisfies the requirement to
|
||||
distribute the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
5. A program that contains no derivative of any portion of the
|
||||
Library, but is designed to work with the Library by being compiled or
|
||||
linked with it, is called a "work that uses the Library". Such a
|
||||
work, in isolation, is not a derivative work of the Library, and
|
||||
therefore falls outside the scope of this License.
|
||||
|
||||
However, linking a "work that uses the Library" with the Library
|
||||
creates an executable that is a derivative of the Library (because it
|
||||
contains portions of the Library), rather than a "work that uses the
|
||||
library". The executable is therefore covered by this License.
|
||||
Section 6 states terms for distribution of such executables.
|
||||
|
||||
When a "work that uses the Library" uses material from a header file
|
||||
that is part of the Library, the object code for the work may be a
|
||||
derivative work of the Library even though the source code is not.
|
||||
Whether this is true is especially significant if the work can be
|
||||
linked without the Library, or if the work is itself a library. The
|
||||
threshold for this to be true is not precisely defined by law.
|
||||
|
||||
If such an object file uses only numerical parameters, data
|
||||
structure layouts and accessors, and small macros and small inline
|
||||
functions (ten lines or less in length), then the use of the object
|
||||
file is unrestricted, regardless of whether it is legally a derivative
|
||||
work. (Executables containing this object code plus portions of the
|
||||
Library will still fall under Section 6.)
|
||||
|
||||
Otherwise, if the work is a derivative of the Library, you may
|
||||
distribute the object code for the work under the terms of Section 6.
|
||||
Any executables containing that work also fall under Section 6,
|
||||
whether or not they are linked directly with the Library itself.
|
||||
|
||||
6. As an exception to the Sections above, you may also combine or
|
||||
link a "work that uses the Library" with the Library to produce a
|
||||
work containing portions of the Library, and distribute that work
|
||||
under terms of your choice, provided that the terms permit
|
||||
modification of the work for the customer's own use and reverse
|
||||
engineering for debugging such modifications.
|
||||
|
||||
You must give prominent notice with each copy of the work that the
|
||||
Library is used in it and that the Library and its use are covered by
|
||||
this License. You must supply a copy of this License. If the work
|
||||
during execution displays copyright notices, you must include the
|
||||
copyright notice for the Library among them, as well as a reference
|
||||
directing the user to the copy of this License. Also, you must do one
|
||||
of these things:
|
||||
|
||||
a) Accompany the work with the complete corresponding
|
||||
machine-readable source code for the Library including whatever
|
||||
changes were used in the work (which must be distributed under
|
||||
Sections 1 and 2 above); and, if the work is an executable linked
|
||||
with the Library, with the complete machine-readable "work that
|
||||
uses the Library", as object code and/or source code, so that the
|
||||
user can modify the Library and then relink to produce a modified
|
||||
executable containing the modified Library. (It is understood
|
||||
that the user who changes the contents of definitions files in the
|
||||
Library will not necessarily be able to recompile the application
|
||||
to use the modified definitions.)
|
||||
|
||||
b) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (1) uses at run time a
|
||||
copy of the library already present on the user's computer system,
|
||||
rather than copying library functions into the executable, and (2)
|
||||
will operate properly with a modified version of the library, if
|
||||
the user installs one, as long as the modified version is
|
||||
interface-compatible with the version that the work was made with.
|
||||
|
||||
c) Accompany the work with a written offer, valid for at
|
||||
least three years, to give the same user the materials
|
||||
specified in Subsection 6a, above, for a charge no more
|
||||
than the cost of performing this distribution.
|
||||
|
||||
d) If distribution of the work is made by offering access to copy
|
||||
from a designated place, offer equivalent access to copy the above
|
||||
specified materials from the same place.
|
||||
|
||||
e) Verify that the user has already received a copy of these
|
||||
materials or that you have already sent this user a copy.
|
||||
|
||||
For an executable, the required form of the "work that uses the
|
||||
Library" must include any data and utility programs needed for
|
||||
reproducing the executable from it. However, as a special exception,
|
||||
the materials to be distributed need not include anything that is
|
||||
normally distributed (in either source or binary form) with the major
|
||||
components (compiler, kernel, and so on) of the operating system on
|
||||
which the executable runs, unless that component itself accompanies
|
||||
the executable.
|
||||
|
||||
It may happen that this requirement contradicts the license
|
||||
restrictions of other proprietary libraries that do not normally
|
||||
accompany the operating system. Such a contradiction means you cannot
|
||||
use both them and the Library together in an executable that you
|
||||
distribute.
|
||||
|
||||
7. You may place library facilities that are a work based on the
|
||||
Library side-by-side in a single library together with other library
|
||||
facilities not covered by this License, and distribute such a combined
|
||||
library, provided that the separate distribution of the work based on
|
||||
the Library and of the other library facilities is otherwise
|
||||
permitted, and provided that you do these two things:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work
|
||||
based on the Library, uncombined with any other library
|
||||
facilities. This must be distributed under the terms of the
|
||||
Sections above.
|
||||
|
||||
b) Give prominent notice with the combined library of the fact
|
||||
that part of it is a work based on the Library, and explaining
|
||||
where to find the accompanying uncombined form of the same work.
|
||||
|
||||
8. You may not copy, modify, sublicense, link with, or distribute
|
||||
the Library except as expressly provided under this License. Any
|
||||
attempt otherwise to copy, modify, sublicense, link with, or
|
||||
distribute the Library is void, and will automatically terminate your
|
||||
rights under this License. However, parties who have received copies,
|
||||
or rights, from you under this License will not have their licenses
|
||||
terminated so long as such parties remain in full compliance.
|
||||
|
||||
9. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Library or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Library (or any work based on the
|
||||
Library), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Library or works based on it.
|
||||
|
||||
10. Each time you redistribute the Library (or any work based on the
|
||||
Library), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute, link with or modify the Library
|
||||
subject to these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties with
|
||||
this License.
|
||||
|
||||
11. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Library at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Library by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Library.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under any
|
||||
particular circumstance, the balance of the section is intended to apply,
|
||||
and the section as a whole is intended to apply in other circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
12. If the distribution and/or use of the Library is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Library under this License may add
|
||||
an explicit geographical distribution limitation excluding those countries,
|
||||
so that distribution is permitted only in or among countries not thus
|
||||
excluded. In such case, this License incorporates the limitation as if
|
||||
written in the body of this License.
|
||||
|
||||
13. The Free Software Foundation may publish revised and/or new
|
||||
versions of the Lesser General Public License from time to time.
|
||||
Such new versions will be similar in spirit to the present version,
|
||||
but may differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Library
|
||||
specifies a version number of this License which applies to it and
|
||||
"any later version", you have the option of following the terms and
|
||||
conditions either of that version or of any later version published by
|
||||
the Free Software Foundation. If the Library does not specify a
|
||||
license version number, you may choose any version ever published by
|
||||
the Free Software Foundation.
|
||||
|
||||
14. If you wish to incorporate parts of the Library into other free
|
||||
programs whose distribution conditions are incompatible with these,
|
||||
write to the author to ask for permission. For software which is
|
||||
copyrighted by the Free Software Foundation, write to the Free
|
||||
Software Foundation; we sometimes make exceptions for this. Our
|
||||
decision will be guided by the two goals of preserving the free status
|
||||
of all derivatives of our free software and of promoting the sharing
|
||||
and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
|
||||
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
||||
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||||
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
||||
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
|
||||
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
||||
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
||||
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
||||
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
||||
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Libraries
|
||||
|
||||
If you develop a new library, and you want it to be of the greatest
|
||||
possible use to the public, we recommend making it free software that
|
||||
everyone can redistribute and change. You can do so by permitting
|
||||
redistribution under these terms (or, alternatively, under the terms of the
|
||||
ordinary General Public License).
|
||||
|
||||
To apply these terms, attach the following notices to the library. It is
|
||||
safest to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least the
|
||||
"copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the library's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the library, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the
|
||||
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1990
|
||||
Ty Coon, President of Vice
|
||||
|
||||
That's all there is to it!
|
231
plugins/ewc/ewc.c
Normal file
@ -0,0 +1,231 @@
|
||||
/*
|
||||
EasyWinampControl - A Winamp "What's playing" plugin for HexChat
|
||||
Copyright (C) Yann HAMON & contributors
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <windows.h>
|
||||
#include "hexchat-plugin.h"
|
||||
|
||||
static hexchat_plugin *ph; /* plugin handle */
|
||||
static int enable = 1;
|
||||
|
||||
// For example, circularstrstr("winamp", "pwi", 3) would return 5 (the index of p)
|
||||
int circularstrstr(char* a, char* b, int nb)
|
||||
{
|
||||
int equal = 1;
|
||||
int length;
|
||||
int pos=-1;
|
||||
int i, j;
|
||||
|
||||
length = strlen(a);
|
||||
|
||||
for (i=0; i<length && pos == -1; ++i) {
|
||||
equal = 1;
|
||||
for (j=0; j<nb;j++) {
|
||||
if (a[(i+j)%length] != b[j])
|
||||
equal = 0;
|
||||
}
|
||||
if (equal == 1)
|
||||
pos = i;
|
||||
}
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
void GetCurrentSongsName(HWND hwndWinamp, char* title, int titlesize)
|
||||
{
|
||||
int pos;
|
||||
char *title2;
|
||||
int i, j=0;
|
||||
int length;
|
||||
char *p;
|
||||
|
||||
GetWindowText(hwndWinamp, title, titlesize);
|
||||
length = strlen(title);
|
||||
|
||||
if ((pos = circularstrstr(title, "- Winamp ***", 12)) != -1) {
|
||||
// The option "scroll song title in taskbar" is on
|
||||
title2 = (char*) malloc (titlesize*sizeof(char));
|
||||
|
||||
for (i=(pos+12)%length; i!=pos; i=(i+1)%length)
|
||||
title2[j++] = title[i];
|
||||
|
||||
title2[j] = '\0';
|
||||
|
||||
p = title2;
|
||||
while (p<title2+titlesize && *p != '.')
|
||||
p++;
|
||||
p+=2; // Delete the . and the following white space
|
||||
|
||||
strcpy(title, p);
|
||||
free(title2);
|
||||
}
|
||||
else {
|
||||
p = title;
|
||||
while (p<title+titlesize && *p != '.')
|
||||
p++;
|
||||
p+=2; // Delete the . and the following white space
|
||||
if (p<title+titlesize)
|
||||
strncpy(title, p, titlesize-(p-title));
|
||||
|
||||
// Delete the trailing "- winamp"
|
||||
p = title + titlesize - 1;
|
||||
while (p>title && *p != '-') p--;
|
||||
*p = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Controlling winamp
|
||||
static int wcmd_cb(char *word[], char *word_eol[], void *userdata)
|
||||
{
|
||||
// Everything's here : http://winamp.com/nsdn/winamp2x/dev/sdk/api.php
|
||||
// The previous url seems dead, see http://forums.winamp.com/showthread.php?threadid=180297
|
||||
HWND hwndWinamp = NULL;
|
||||
|
||||
if ((hwndWinamp = FindWindow("Winamp v1.x",NULL)) == NULL) {
|
||||
hexchat_print(ph, "Winamp's window not found - Is winamp really running?\n");
|
||||
}
|
||||
else {
|
||||
if (strcmp(word[1], "") == 0)
|
||||
hexchat_print(ph, "Usage: wcmd [command]\n");
|
||||
else if (strcmp(word[2], "next") == 0) {
|
||||
hexchat_print(ph, "Loading next song...\n");
|
||||
SendMessage (hwndWinamp, WM_COMMAND, 40048, 0);
|
||||
}
|
||||
else if (strcmp(word[2], "prev") == 0) {
|
||||
hexchat_print(ph, "Loading previous song...\n");
|
||||
SendMessage (hwndWinamp, WM_COMMAND, 40044, 0);
|
||||
}
|
||||
else if (strcmp(word[2], "play") == 0) {
|
||||
hexchat_print(ph, "Playin'...\n");
|
||||
SendMessage (hwndWinamp, WM_COMMAND, 40045, 0);
|
||||
}
|
||||
else if (strcmp(word[2], "stop") == 0) {
|
||||
hexchat_print(ph, "Winamp stopped!...\n");
|
||||
SendMessage (hwndWinamp, WM_COMMAND, 40047, 0);
|
||||
}
|
||||
else if (strcmp(word[2], "pause") == 0) {
|
||||
SendMessage (hwndWinamp, WM_COMMAND, 40046, 0);
|
||||
}
|
||||
}
|
||||
|
||||
return HEXCHAT_EAT_ALL;
|
||||
}
|
||||
|
||||
|
||||
// Display current song
|
||||
static int wp_cb(char *word[], char *word_eol[], void *userdata)
|
||||
{
|
||||
HWND hwndWinamp = NULL;
|
||||
int bitrate, length, elapsed, minutes, seconds, eminutes, eseconds, samplerate, nbchannels;
|
||||
char elapsedtime[7];
|
||||
char totaltime[7];
|
||||
char this_title[1024];
|
||||
|
||||
if ((hwndWinamp = FindWindow("Winamp v1.x",NULL)) == NULL)
|
||||
hexchat_print(ph, "Winamp's window not found - Is winamp really running?\n");
|
||||
else {
|
||||
//Winamp's running
|
||||
// Seems buggy when winamp2's agent is running, and winamp not (or winamp3) -> crashes HexChat.
|
||||
SendMessage(hwndWinamp, WM_USER, (WPARAM)0, (LPARAM)125);
|
||||
|
||||
if ((samplerate = SendMessage(hwndWinamp, WM_USER, (WPARAM)0, (LPARAM)126)) == 0) {
|
||||
hexchat_print(ph, "Could not get current song's samplerate... !?\n");
|
||||
return HEXCHAT_EAT_ALL;
|
||||
}
|
||||
if ((bitrate = SendMessage(hwndWinamp, WM_USER, (WPARAM)1, (LPARAM)126)) == 0) {
|
||||
hexchat_print(ph, "Could not get current song's bitrate... !?\n");
|
||||
return HEXCHAT_EAT_ALL;
|
||||
}
|
||||
if ((nbchannels = SendMessage(hwndWinamp, WM_USER, (WPARAM)2, (LPARAM)126)) == 0) {
|
||||
hexchat_print(ph, "Could not get the number of channels... !?\n");
|
||||
return HEXCHAT_EAT_ALL;
|
||||
}
|
||||
if ((length = SendMessage(hwndWinamp, WM_USER, (WPARAM)1, (LPARAM)105)) == 0) {
|
||||
// Could be buggy when streaming audio or video, returned length is unexpected;
|
||||
// How to detect is Winamp is streaming, and display ??:?? in that case?
|
||||
hexchat_print(ph, "Could not get current song's length... !?\n");
|
||||
return HEXCHAT_EAT_ALL;
|
||||
}
|
||||
else {
|
||||
minutes = length/60;
|
||||
seconds = length%60;
|
||||
|
||||
if (seconds>9)
|
||||
wsprintf(totaltime, "%d:%d", minutes, seconds);
|
||||
else
|
||||
wsprintf(totaltime, "%d:0%d", minutes, seconds);
|
||||
}
|
||||
if ((elapsed = SendMessage(hwndWinamp, WM_USER, (WPARAM)0, (LPARAM)105)) == 0) {
|
||||
hexchat_print(ph, "Could not get current song's elapsed time... !?\n");
|
||||
return HEXCHAT_EAT_ALL;
|
||||
}
|
||||
else {
|
||||
eminutes = (elapsed/1000)/60; /* kinda stupid sounding, but e is for elapsed */
|
||||
eseconds = (elapsed/1000)%60;
|
||||
|
||||
if (eseconds>9)
|
||||
wsprintf(elapsedtime, "%d:%d", eminutes, eseconds);
|
||||
else
|
||||
wsprintf(elapsedtime, "%d:0%d", eminutes, eseconds);
|
||||
}
|
||||
|
||||
if ((bitrate = SendMessage(hwndWinamp, WM_USER, (WPARAM)1, (LPARAM)126)) == 0) {
|
||||
hexchat_print(ph, "Could not get current song's bitrate... !?\n");
|
||||
return HEXCHAT_EAT_ALL;
|
||||
}
|
||||
|
||||
GetCurrentSongsName(hwndWinamp, this_title, 1024);
|
||||
|
||||
hexchat_commandf(ph, "dispcurrsong %d %d %d %s %s %s", samplerate, bitrate, nbchannels, elapsedtime, totaltime, this_title);
|
||||
}
|
||||
|
||||
return HEXCHAT_EAT_ALL; /* eat this command so HexChat and other plugins can't process it */
|
||||
}
|
||||
|
||||
|
||||
|
||||
int hexchat_plugin_init(hexchat_plugin *plugin_handle,
|
||||
char **plugin_name,
|
||||
char **plugin_desc,
|
||||
char **plugin_version,
|
||||
char *arg)
|
||||
{
|
||||
/* we need to save this for use with any hexchat_* functions */
|
||||
ph = plugin_handle;
|
||||
|
||||
*plugin_name = "EasyWinampControl";
|
||||
*plugin_desc = "Some commands to remotely control winamp";
|
||||
*plugin_version = "1.2";
|
||||
|
||||
hexchat_hook_command(ph, "wp", HEXCHAT_PRI_NORM, wp_cb,
|
||||
"Usage: wp", 0);
|
||||
|
||||
hexchat_hook_command(ph, "wcmd", HEXCHAT_PRI_NORM, wcmd_cb,
|
||||
"Usage: wcmd [play|pause|stop|prev|next]", 0);
|
||||
|
||||
hexchat_print(ph, "EasyWinampControl plugin loaded\n");
|
||||
|
||||
return 1; /* return 1 for success */
|
||||
}
|
||||
|
||||
int hexchat_plugin_deinit(void)
|
||||
{
|
||||
hexchat_print(ph, "EasyWinampControl plugin unloaded\n");
|
||||
return 1;
|
||||
}
|
18
plugins/ewc/makefile.mak
Normal file
@ -0,0 +1,18 @@
|
||||
include "..\..\src\makeinc.mak"
|
||||
|
||||
all: ewc.obj ewc.def
|
||||
link $(LDFLAGS) $(LIBS) /dll /out:xcewc.dll /def:ewc.def ewc.obj
|
||||
|
||||
ewc.def:
|
||||
echo EXPORTS > ewc.def
|
||||
echo hexchat_plugin_init >> ewc.def
|
||||
echo hexchat_plugin_deinit >> ewc.def
|
||||
|
||||
ewc.obj: ewc.c makefile.mak
|
||||
cl $(CFLAGS) ewc.c
|
||||
|
||||
clean:
|
||||
del *.obj
|
||||
del *.dll
|
||||
del *.exp
|
||||
del *.lib
|
@ -1,8 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup Label="Configuration">
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<PlatformToolset>v120</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
@ -20,28 +19,75 @@
|
||||
<RootNamespace>exec</RootNamespace>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="..\..\win32\hexchat.props" />
|
||||
<PropertyGroup>
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="..\..\win32\hexchat.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="..\..\win32\hexchat.props" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<TargetName>hcexec</TargetName>
|
||||
<OutDir>$(HexChatRel)plugins\</OutDir>
|
||||
<OutDir>$(HexChatBin)</OutDir>
|
||||
<IntDir>$(HexChatObj)$(ProjectName)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<TargetName>hcexec</TargetName>
|
||||
<OutDir>$(HexChatBin)</OutDir>
|
||||
<IntDir>$(HexChatObj)$(ProjectName)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;EXEC_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<AdditionalIncludeDirectories>..\..\src\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<ModuleDefinitionFile>exec.def</ModuleDefinitionFile>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;_WIN64;_AMD64_;NDEBUG;_WINDOWS;_USRDLL;EXEC_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<AdditionalIncludeDirectories>..\..\src\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<ModuleDefinitionFile>exec.def</ModuleDefinitionFile>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
@ -52,4 +98,6 @@
|
||||
<ClCompile Include="exec.c" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
</Project>
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
@ -1,6 +0,0 @@
|
||||
shared_module('exec', 'exec.c',
|
||||
dependencies: hexchat_plugin_dep,
|
||||
install: true,
|
||||
install_dir: plugindir,
|
||||
vs_module_defs: 'exec.def',
|
||||
)
|
16
plugins/fishlim/INSTALL
Normal file
@ -0,0 +1,16 @@
|
||||
|
||||
Install dependencies (on Debian/Ubuntu):
|
||||
|
||||
sudo apt-get install build-essential libglib2.0-dev libssl-dev
|
||||
|
||||
|
||||
Build the plugin with:
|
||||
|
||||
make
|
||||
|
||||
|
||||
Install with:
|
||||
|
||||
sudo make install
|
||||
|
||||
|
9
plugins/fishlim/Makefile.am
Normal file
@ -0,0 +1,9 @@
|
||||
EXTRA_DIST = INSTALL LICENSE README
|
||||
|
||||
libdir = $(hexchatlibdir)
|
||||
|
||||
lib_LTLIBRARIES = fishlim.la
|
||||
fishlim_la_SOURCES = fish.c irc.c keystore.c misc.c plugin_hexchat.c
|
||||
fishlim_la_LDFLAGS = -avoid-version -module
|
||||
fishlim_la_LIBADD =
|
||||
AM_CPPFLAGS = $(COMMON_CFLAGS) -I$(srcdir)/../../src/common
|
@ -1,238 +0,0 @@
|
||||
/* HexChat
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* For Diffie-Hellman key-exchange a 1080bit germain prime is used, the
|
||||
* generator g=2 renders a field Fp from 1 to p-1. Therefore breaking it
|
||||
* means to solve a discrete logarithm problem with no less than 1080bit.
|
||||
*
|
||||
* Base64 format is used to send the public keys over IRC.
|
||||
*
|
||||
* The calculated secret key is hashed with SHA-256, the result is converted
|
||||
* to base64 for final use with blowfish.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "dh1080.h"
|
||||
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/dh.h>
|
||||
#include <openssl/sha.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <glib.h>
|
||||
|
||||
#define DH1080_PRIME_BITS 1080
|
||||
#define DH1080_PRIME_BYTES 135
|
||||
#define SHA256_DIGEST_LENGTH 32
|
||||
#define B64ABC "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
|
||||
#define MEMZERO(x) memset(x, 0x00, sizeof(x))
|
||||
|
||||
/* All clients must use the same prime number to be able to keyx */
|
||||
static const guchar prime1080[DH1080_PRIME_BYTES] =
|
||||
{
|
||||
0xFB, 0xE1, 0x02, 0x2E, 0x23, 0xD2, 0x13, 0xE8, 0xAC, 0xFA, 0x9A, 0xE8, 0xB9, 0xDF, 0xAD, 0xA3, 0xEA,
|
||||
0x6B, 0x7A, 0xC7, 0xA7, 0xB7, 0xE9, 0x5A, 0xB5, 0xEB, 0x2D, 0xF8, 0x58, 0x92, 0x1F, 0xEA, 0xDE, 0x95,
|
||||
0xE6, 0xAC, 0x7B, 0xE7, 0xDE, 0x6A, 0xDB, 0xAB, 0x8A, 0x78, 0x3E, 0x7A, 0xF7, 0xA7, 0xFA, 0x6A, 0x2B,
|
||||
0x7B, 0xEB, 0x1E, 0x72, 0xEA, 0xE2, 0xB7, 0x2F, 0x9F, 0xA2, 0xBF, 0xB2, 0xA2, 0xEF, 0xBE, 0xFA, 0xC8,
|
||||
0x68, 0xBA, 0xDB, 0x3E, 0x82, 0x8F, 0xA8, 0xBA, 0xDF, 0xAD, 0xA3, 0xE4, 0xCC, 0x1B, 0xE7, 0xE8, 0xAF,
|
||||
0xE8, 0x5E, 0x96, 0x98, 0xA7, 0x83, 0xEB, 0x68, 0xFA, 0x07, 0xA7, 0x7A, 0xB6, 0xAD, 0x7B, 0xEB, 0x61,
|
||||
0x8A, 0xCF, 0x9C, 0xA2, 0x89, 0x7E, 0xB2, 0x8A, 0x61, 0x89, 0xEF, 0xA0, 0x7A, 0xB9, 0x9A, 0x8A, 0x7F,
|
||||
0xA9, 0xAE, 0x29, 0x9E, 0xFA, 0x7B, 0xA6, 0x6D, 0xEA, 0xFE, 0xFB, 0xEF, 0xBF, 0x0B, 0x7D, 0x8B
|
||||
};
|
||||
|
||||
static DH *g_dh;
|
||||
|
||||
int
|
||||
dh1080_init (void)
|
||||
{
|
||||
g_return_val_if_fail (g_dh == NULL, 0);
|
||||
|
||||
if ((g_dh = DH_new()))
|
||||
{
|
||||
int codes;
|
||||
BIGNUM *p, *g;
|
||||
|
||||
p = BN_bin2bn (prime1080, DH1080_PRIME_BYTES, NULL);
|
||||
g = BN_new ();
|
||||
|
||||
if (p == NULL || g == NULL)
|
||||
return 1;
|
||||
|
||||
BN_set_word (g, 2);
|
||||
|
||||
#ifndef HAVE_DH_SET0_PQG
|
||||
g_dh->p = p;
|
||||
g_dh->g = g;
|
||||
#else
|
||||
if (!DH_set0_pqg (g_dh, p, NULL, g))
|
||||
return 1;
|
||||
#endif
|
||||
|
||||
if (DH_check (g_dh, &codes))
|
||||
return codes == 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
dh1080_deinit (void)
|
||||
{
|
||||
g_clear_pointer (&g_dh, DH_free);
|
||||
}
|
||||
|
||||
static inline int
|
||||
DH_verifyPubKey (BIGNUM *pk)
|
||||
{
|
||||
int codes;
|
||||
return DH_check_pub_key (g_dh, pk, &codes) && codes == 0;
|
||||
}
|
||||
|
||||
static guchar *
|
||||
dh1080_decode_b64 (const char *data, gsize *out_len)
|
||||
{
|
||||
GString *str = g_string_new (data);
|
||||
guchar *ret;
|
||||
|
||||
if (str->len % 4 == 1 && str->str[str->len - 1] == 'A')
|
||||
g_string_truncate (str, str->len - 1);
|
||||
|
||||
while (str->len % 4 != 0)
|
||||
g_string_append_c (str, '=');
|
||||
|
||||
ret = g_base64_decode_inplace (str->str, out_len);
|
||||
g_string_free (str, FALSE);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static char *
|
||||
dh1080_encode_b64 (const guchar *data, gsize data_len)
|
||||
{
|
||||
char *ret = g_base64_encode (data, data_len);
|
||||
char *p;
|
||||
|
||||
if (!(p = strchr (ret, '=')))
|
||||
{
|
||||
char *new_ret = g_new(char, strlen(ret) + 2);
|
||||
strcpy (new_ret, ret);
|
||||
strcat (new_ret, "A");
|
||||
g_free (ret);
|
||||
ret = new_ret;
|
||||
}
|
||||
else
|
||||
{
|
||||
*p = '\0';
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
dh1080_generate_key (char **priv_key, char **pub_key)
|
||||
{
|
||||
guchar buf[DH1080_PRIME_BYTES];
|
||||
int len;
|
||||
DH *dh;
|
||||
const BIGNUM *dh_priv_key, *dh_pub_key;
|
||||
|
||||
g_assert (priv_key != NULL);
|
||||
g_assert (pub_key != NULL);
|
||||
|
||||
dh = DHparams_dup (g_dh);
|
||||
if (!dh)
|
||||
return 0;
|
||||
|
||||
if (!DH_generate_key (dh))
|
||||
{
|
||||
DH_free (dh);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef HAVE_DH_GET0_KEY
|
||||
dh_pub_key = dh->pub_key;
|
||||
dh_priv_key = dh->priv_key;
|
||||
#else
|
||||
DH_get0_key (dh, &dh_pub_key, &dh_priv_key);
|
||||
#endif
|
||||
|
||||
MEMZERO (buf);
|
||||
len = BN_bn2bin (dh_priv_key, buf);
|
||||
*priv_key = dh1080_encode_b64 (buf, len);
|
||||
|
||||
MEMZERO (buf);
|
||||
len = BN_bn2bin (dh_pub_key, buf);
|
||||
*pub_key = dh1080_encode_b64 (buf, len);
|
||||
|
||||
OPENSSL_cleanse (buf, sizeof (buf));
|
||||
DH_free (dh);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
dh1080_compute_key (const char *priv_key, const char *pub_key, char **secret_key)
|
||||
{
|
||||
char *pub_key_data;
|
||||
gsize pub_key_len;
|
||||
BIGNUM *pk;
|
||||
DH *dh;
|
||||
#ifdef HAVE_DH_SET0_KEY
|
||||
BIGNUM *temp_pub_key = BN_new();
|
||||
#endif
|
||||
|
||||
g_assert (secret_key != NULL);
|
||||
|
||||
/* Verify base64 strings */
|
||||
if (strspn (priv_key, B64ABC) != strlen (priv_key)
|
||||
|| strspn (pub_key, B64ABC) != strlen (pub_key))
|
||||
return 0;
|
||||
|
||||
dh = DHparams_dup (g_dh);
|
||||
|
||||
pub_key_data = dh1080_decode_b64 (pub_key, &pub_key_len);
|
||||
pk = BN_bin2bn (pub_key_data, pub_key_len, NULL);
|
||||
|
||||
if (DH_verifyPubKey (pk))
|
||||
{
|
||||
guchar shared_key[DH1080_PRIME_BYTES] = { 0 };
|
||||
guchar sha256[SHA256_DIGEST_LENGTH] = { 0 };
|
||||
char *priv_key_data;
|
||||
gsize priv_key_len;
|
||||
int shared_len;
|
||||
BIGNUM *priv_key_num;
|
||||
|
||||
priv_key_data = dh1080_decode_b64 (priv_key, &priv_key_len);
|
||||
priv_key_num = BN_bin2bn(priv_key_data, priv_key_len, NULL);
|
||||
#ifndef HAVE_DH_SET0_KEY
|
||||
dh->priv_key = priv_key_num;
|
||||
#else
|
||||
DH_set0_key (dh, temp_pub_key, priv_key_num);
|
||||
#endif
|
||||
|
||||
shared_len = DH_compute_key (shared_key, pk, dh);
|
||||
SHA256(shared_key, shared_len, sha256);
|
||||
*secret_key = dh1080_encode_b64 (sha256, sizeof(sha256));
|
||||
|
||||
OPENSSL_cleanse (priv_key_data, priv_key_len);
|
||||
g_free (priv_key_data);
|
||||
}
|
||||
|
||||
BN_free (pk);
|
||||
DH_free (dh);
|
||||
g_free (pub_key_data);
|
||||
return 1;
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
/* HexChat
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
int dh1080_generate_key (char **, char **);
|
||||
int dh1080_compute_key (const char *, const char *, char **);
|
||||
int dh1080_init (void);
|
||||
void dh1080_deinit (void);
|
||||
|
@ -1,7 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2010 Samuel Lidén Borell <samuel@kodafritt.se>
|
||||
Copyright (c) 2019-2020 <bakasura@protonmail.ch>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@ -23,50 +22,32 @@
|
||||
|
||||
*/
|
||||
|
||||
#ifdef __APPLE__
|
||||
#define __AVAILABILITYMACROS__
|
||||
#define DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/blowfish.h>
|
||||
#include <openssl/rand.h>
|
||||
|
||||
#include "keystore.h"
|
||||
#include "fish.h"
|
||||
#include "utils.h"
|
||||
|
||||
#define IB 64
|
||||
/* rfc 2812; 512 - CR-LF = 510 */
|
||||
static const int MAX_COMMAND_LENGTH = 510;
|
||||
static const char fish_base64[] = "./0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
static const char base64_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
|
||||
static const char fish_base64[64] = "./0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
static const signed char fish_unbase64[256] = {
|
||||
IB,IB,IB,IB,IB,IB,IB,IB, IB,IB,IB,IB,IB,IB,IB,IB,
|
||||
IB,IB,IB,IB,IB,IB,IB,IB, IB,IB,IB,IB,IB,IB,IB,IB,
|
||||
/* ! " # $ % & ' ( ) * + , - . / */
|
||||
// ! " # $ % & ' ( ) * + , - . /
|
||||
IB,IB,IB,IB,IB,IB,IB,IB, IB,IB,IB,IB,IB,IB, 0, 1,
|
||||
/* 0 1 2 3 4 5 6 7 8 9 : ; < = > ? */
|
||||
// 0 1 2 3 4 5 6 7 8 9 : ; < = > ?
|
||||
2, 3, 4, 5, 6, 7, 8, 9, 10,11,IB,IB,IB,IB,IB,IB,
|
||||
/* @ A B C D E F G H I J K L M N O */
|
||||
// @ A B C D E F G H I J K L M N O
|
||||
IB,38,39,40,41,42,43,44, 45,46,47,48,49,50,51,52,
|
||||
/* P Q R S T U V W X Y Z [ \ ] ^ _*/
|
||||
// P Q R S T U V W X Y Z [ \ ] ^ _
|
||||
53,54,55,56,57,58,59,60, 61,62,63,IB,IB,IB,IB,IB,
|
||||
/* ` a b c d e f g h i j k l m n o */
|
||||
// ` a b c d e f g h i j k l m n o
|
||||
IB,12,13,14,15,16,17,18, 19,20,21,22,23,24,25,26,
|
||||
/* p q r s t u v w x y z { | } ~ <del> */
|
||||
// p q r s t u v w x y z { | } ~ <del>
|
||||
27,28,29,30,31,32,33,34, 35,36,37,IB,IB,IB,IB,IB,
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert Int to 4 Bytes (Big-endian)
|
||||
*
|
||||
* @param int source
|
||||
* @param char* dest
|
||||
*/
|
||||
#define GET_BYTES(dest, source) do { \
|
||||
*((dest)++) = ((source) >> 24) & 0xFF; \
|
||||
*((dest)++) = ((source) >> 16) & 0xFF; \
|
||||
@ -74,488 +55,137 @@ static const signed char fish_unbase64[256] = {
|
||||
*((dest)++) = (source) & 0xFF; \
|
||||
} while (0);
|
||||
|
||||
/**
|
||||
* Convert 4 Bytes to Int (Big-endian)
|
||||
*
|
||||
* @param char* source
|
||||
* @param int dest
|
||||
*/
|
||||
#define GET_LONG(dest, source) do { \
|
||||
dest = ((uint8_t)*((source)++) << 24); \
|
||||
dest |= ((uint8_t)*((source)++) << 16); \
|
||||
dest |= ((uint8_t)*((source)++) << 8); \
|
||||
dest |= (uint8_t)*((source)++); \
|
||||
} while (0);
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
#include <openssl/provider.h>
|
||||
static OSSL_PROVIDER *legacy_provider;
|
||||
static OSSL_PROVIDER *default_provider;
|
||||
static OSSL_LIB_CTX* *ossl_ctx;
|
||||
#endif
|
||||
|
||||
int fish_init(void)
|
||||
{
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
ossl_ctx = OSSL_LIB_CTX_new();
|
||||
if (!ossl_ctx)
|
||||
return 0;
|
||||
|
||||
legacy_provider = OSSL_PROVIDER_load(ossl_ctx, "legacy");
|
||||
if (!legacy_provider) {
|
||||
fish_deinit();
|
||||
return 0;
|
||||
}
|
||||
|
||||
default_provider = OSSL_PROVIDER_load(ossl_ctx, "default");
|
||||
if (!default_provider) {
|
||||
fish_deinit();
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
void fish_deinit(void)
|
||||
{
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
if (legacy_provider) {
|
||||
OSSL_PROVIDER_unload(legacy_provider);
|
||||
legacy_provider = NULL;
|
||||
}
|
||||
|
||||
if (default_provider) {
|
||||
OSSL_PROVIDER_unload(default_provider);
|
||||
default_provider = NULL;
|
||||
}
|
||||
|
||||
if (ossl_ctx) {
|
||||
OSSL_LIB_CTX_free(ossl_ctx);
|
||||
ossl_ctx = NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode ECB FiSH Base64
|
||||
*
|
||||
* @param [in] message Bytes to encode
|
||||
* @param [in] message_len Size of bytes to encode
|
||||
* @return Array of char with encoded string
|
||||
*/
|
||||
char *fish_base64_encode(const char *message, size_t message_len) {
|
||||
BF_LONG left = 0, right = 0;
|
||||
int i, j;
|
||||
char *encoded = NULL;
|
||||
char *end = NULL;
|
||||
char *msg = NULL;
|
||||
|
||||
if (message_len == 0)
|
||||
return NULL;
|
||||
|
||||
/* Each 8-byte block becomes 12 bytes (fish base64 format) and add 1 byte for \0 */
|
||||
encoded = g_malloc(((message_len - 1) / 8) * 12 + 12 + 1);
|
||||
end = encoded;
|
||||
|
||||
/* Iterate over each 8-byte block (Blowfish block size) */
|
||||
for (j = 0; j < message_len; j += 8) {
|
||||
msg = (char *) message;
|
||||
|
||||
/* Set left and right longs */
|
||||
GET_LONG(left, msg);
|
||||
GET_LONG(right, msg);
|
||||
|
||||
for (i = 0; i < 6; ++i) {
|
||||
*end++ = fish_base64[right & 0x3fu];
|
||||
right = (right >> 6u);
|
||||
char *fish_encrypt(const char *key, size_t keylen, const char *message) {
|
||||
BF_KEY bfkey;
|
||||
size_t messagelen;
|
||||
size_t i;
|
||||
int j;
|
||||
char *encrypted;
|
||||
char *end;
|
||||
unsigned char bit;
|
||||
unsigned char word;
|
||||
unsigned char d;
|
||||
BF_set_key(&bfkey, keylen, (const unsigned char*)key);
|
||||
|
||||
messagelen = strlen(message);
|
||||
if (messagelen == 0) return NULL;
|
||||
encrypted = malloc(((messagelen-1)/8)*12 + 12 + 1); // each 8-byte block becomes 12 bytes
|
||||
end = encrypted;
|
||||
if (!encrypted) return NULL;
|
||||
|
||||
while (*message) {
|
||||
// Read 8 bytes (a Blowfish block)
|
||||
BF_LONG binary[2] = { 0, 0 };
|
||||
unsigned char c;
|
||||
for (i = 0; i < 8; i++) {
|
||||
c = message[i];
|
||||
binary[i >> 2] |= c << 8*(3 - (i&3));
|
||||
if (c == '\0') break;
|
||||
}
|
||||
|
||||
for (i = 0; i < 6; ++i) {
|
||||
*end++ = fish_base64[left & 0x3fu];
|
||||
left = (left >> 6u);
|
||||
}
|
||||
|
||||
/* The previous for'd ensure fill all bytes of encoded, we don't need will with zeros */
|
||||
message += 8;
|
||||
|
||||
// Encrypt block
|
||||
BF_encrypt(binary, &bfkey);
|
||||
|
||||
// Emit FiSH-BASE64
|
||||
bit = 0;
|
||||
word = 1;
|
||||
for (j = 0; j < 12; j++) {
|
||||
d = fish_base64[(binary[word] >> bit) & 63];
|
||||
*(end++) = d;
|
||||
bit += 6;
|
||||
if (j == 5) {
|
||||
bit = 0;
|
||||
word = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Stop if a null terminator was found
|
||||
if (c == '\0') break;
|
||||
}
|
||||
|
||||
*end = '\0';
|
||||
return encoded;
|
||||
return encrypted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode ECB FiSH Base64
|
||||
*
|
||||
* @param [in] message Base64 encoded string
|
||||
* @param [out] final_len Real length of message
|
||||
* @return Array of char with decoded message
|
||||
*/
|
||||
char *fish_base64_decode(const char *message, size_t *final_len) {
|
||||
BF_LONG left, right;
|
||||
int i;
|
||||
char *bytes = NULL;
|
||||
char *msg = NULL;
|
||||
char *byt = NULL;
|
||||
size_t message_len;
|
||||
|
||||
message_len = strlen(message);
|
||||
|
||||
/* Ensure blocks of 12 bytes each one and valid characters */
|
||||
if (message_len == 0 || message_len % 12 != 0 || strspn(message, fish_base64) != message_len)
|
||||
return NULL;
|
||||
|
||||
/* Each 12 bytes becomes 8-byte block and add 1 byte for \0 */
|
||||
*final_len = ((message_len - 1) / 12) * 8 + 8 + 1;
|
||||
(*final_len)--; /* We support binary data */
|
||||
bytes = (char *) g_malloc0(*final_len);
|
||||
byt = bytes;
|
||||
|
||||
msg = (char *) message;
|
||||
|
||||
while (*msg) {
|
||||
right = 0;
|
||||
left = 0;
|
||||
for (i = 0; i < 6; i++) right |= (uint8_t) fish_unbase64[(int)*msg++] << (i * 6u);
|
||||
for (i = 0; i < 6; i++) left |= (uint8_t) fish_unbase64[(int)*msg++] << (i * 6u);
|
||||
GET_BYTES(byt, left);
|
||||
GET_BYTES(byt, right);
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypt or decrypt data with Blowfish cipher, support binary data.
|
||||
*
|
||||
* Good documentation for EVP:
|
||||
*
|
||||
* - https://wiki.openssl.org/index.php/EVP_Symmetric_Encryption_and_Decryption
|
||||
*
|
||||
* - https://stackoverflow.com/questions/5727646/what-is-the-length-parameter-of-aes-evp-decrypt
|
||||
*
|
||||
* - https://stackoverflow.com/questions/26345175/correct-way-to-free-allocate-the-context-in-the-openssl
|
||||
*
|
||||
* - https://stackoverflow.com/questions/29874150/working-with-evp-and-openssl-coding-in-c
|
||||
*
|
||||
* @param [in] plaintext Bytes to encrypt or decrypt
|
||||
* @param [in] plaintext_len Size of plaintext
|
||||
* @param [in] key Bytes of key
|
||||
* @param [in] keylen Size of key
|
||||
* @param [in] encode 1 or encrypt 0 for decrypt
|
||||
* @param [in] mode EVP_CIPH_ECB_MODE or EVP_CIPH_CBC_MODE
|
||||
* @param [out] ciphertext_len The bytes written
|
||||
* @return Array of char with data encrypted or decrypted
|
||||
*/
|
||||
char *fish_cipher(const char *plaintext, size_t plaintext_len, const char *key, size_t keylen, int encode, int mode, size_t *ciphertext_len) {
|
||||
EVP_CIPHER_CTX *ctx;
|
||||
EVP_CIPHER *cipher = NULL;
|
||||
int bytes_written = 0;
|
||||
unsigned char *ciphertext = NULL;
|
||||
unsigned char *iv_ciphertext = NULL;
|
||||
unsigned char *iv = NULL;
|
||||
size_t block_size = 0;
|
||||
|
||||
*ciphertext_len = 0;
|
||||
|
||||
if (plaintext_len == 0 || keylen == 0 || encode < 0 || encode > 1)
|
||||
return NULL;
|
||||
|
||||
block_size = plaintext_len;
|
||||
|
||||
if (mode == EVP_CIPH_CBC_MODE) {
|
||||
if (encode == 1) {
|
||||
iv = (unsigned char *) g_malloc0(8);
|
||||
RAND_bytes(iv, 8);
|
||||
} else {
|
||||
if (plaintext_len <= 8) /* IV + DATA */
|
||||
return NULL;
|
||||
|
||||
iv = (unsigned char *) plaintext;
|
||||
block_size -= 8;
|
||||
plaintext += 8;
|
||||
plaintext_len -= 8;
|
||||
char *fish_decrypt(const char *key, size_t keylen, const char *data) {
|
||||
BF_KEY bfkey;
|
||||
size_t i;
|
||||
char *decrypted;
|
||||
char *end;
|
||||
unsigned char bit;
|
||||
unsigned char word;
|
||||
unsigned char d;
|
||||
BF_set_key(&bfkey, keylen, (const unsigned char*)key);
|
||||
|
||||
decrypted = malloc(strlen(data)+1);
|
||||
end = decrypted;
|
||||
if (!decrypted) return NULL;
|
||||
|
||||
while (*data) {
|
||||
// Convert from FiSH-BASE64
|
||||
BF_LONG binary[2] = { 0, 0 };
|
||||
bit = 0;
|
||||
word = 1;
|
||||
for (i = 0; i < 12; i++) {
|
||||
d = fish_unbase64[(const unsigned char)*(data++)];
|
||||
if (d == IB) goto decrypt_end;
|
||||
binary[word] |= d << bit;
|
||||
bit += 6;
|
||||
if (i == 5) {
|
||||
bit = 0;
|
||||
word = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
cipher = EVP_CIPHER_fetch(ossl_ctx, "BF-CBC", NULL);
|
||||
#else
|
||||
cipher = (EVP_CIPHER *) EVP_bf_cbc();
|
||||
#endif
|
||||
|
||||
} else if (mode == EVP_CIPH_ECB_MODE) {
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
cipher = EVP_CIPHER_fetch(ossl_ctx, "BF-ECB", NULL);
|
||||
#else
|
||||
cipher = (EVP_CIPHER *) EVP_bf_ecb();
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Zero Padding */
|
||||
if (block_size % 8 != 0) {
|
||||
block_size = block_size + 8 - (block_size % 8);
|
||||
}
|
||||
|
||||
ciphertext = (unsigned char *) g_malloc0(block_size);
|
||||
memcpy(ciphertext, plaintext, plaintext_len);
|
||||
|
||||
/* Create and initialise the context */
|
||||
if (!(ctx = EVP_CIPHER_CTX_new()))
|
||||
return NULL;
|
||||
|
||||
/* Initialise the cipher operation only with mode */
|
||||
if (!EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, encode))
|
||||
return NULL;
|
||||
|
||||
/* Set custom key length */
|
||||
if (!EVP_CIPHER_CTX_set_key_length(ctx, keylen))
|
||||
return NULL;
|
||||
|
||||
/* Finish the initiation the cipher operation */
|
||||
if (1 != EVP_CipherInit_ex(ctx, NULL, NULL, (const unsigned char *) key, iv, encode))
|
||||
return NULL;
|
||||
|
||||
/* We will manage this */
|
||||
EVP_CIPHER_CTX_set_padding(ctx, 0);
|
||||
|
||||
/* Do cipher operation */
|
||||
if (1 != EVP_CipherUpdate(ctx, ciphertext, &bytes_written, ciphertext, block_size))
|
||||
return NULL;
|
||||
|
||||
*ciphertext_len = bytes_written;
|
||||
|
||||
/* Finalise the cipher. Further ciphertext bytes may be written at this stage */
|
||||
if (1 != EVP_CipherFinal_ex(ctx, ciphertext + bytes_written, &bytes_written))
|
||||
return NULL;
|
||||
|
||||
*ciphertext_len += bytes_written;
|
||||
|
||||
/* Clean up */
|
||||
EVP_CIPHER_CTX_free(ctx);
|
||||
|
||||
|
||||
if (mode == EVP_CIPH_CBC_MODE && encode == 1) {
|
||||
/* Join IV + DATA */
|
||||
iv_ciphertext = g_malloc0(8 + *ciphertext_len);
|
||||
|
||||
memcpy(iv_ciphertext, iv, 8);
|
||||
memcpy(&iv_ciphertext[8], ciphertext, *ciphertext_len);
|
||||
*ciphertext_len += 8;
|
||||
|
||||
g_free(ciphertext);
|
||||
g_free(iv);
|
||||
|
||||
return (char *) iv_ciphertext;
|
||||
} else {
|
||||
return (char *) ciphertext;
|
||||
|
||||
// Decrypt block
|
||||
BF_decrypt(binary, &bfkey);
|
||||
|
||||
// Copy to buffer
|
||||
GET_BYTES(end, binary[0]);
|
||||
GET_BYTES(end, binary[1]);
|
||||
}
|
||||
|
||||
decrypt_end:
|
||||
*end = '\0';
|
||||
return decrypted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a fish or standard Base64 encoded string with data encrypted
|
||||
* is binary safe
|
||||
*
|
||||
* @param [in] key Bytes of key
|
||||
* @param [in] keylen Size of key
|
||||
* @param [in] message Bytes to encrypt
|
||||
* @param [in] message_len Size of message
|
||||
* @param [in] mode Chiper mode
|
||||
* @return Array of char with data encrypted
|
||||
* Encrypts a message (see fish_decrypt). The key is searched for in the
|
||||
* key store.
|
||||
*/
|
||||
char *fish_encrypt(const char *key, size_t keylen, const char *message, size_t message_len, enum fish_mode mode) {
|
||||
size_t ciphertext_len = 0;
|
||||
char *ciphertext = NULL;
|
||||
char *b64 = NULL;
|
||||
|
||||
if (keylen == 0 || message_len == 0)
|
||||
return NULL;
|
||||
|
||||
ciphertext = fish_cipher(message, message_len, key, keylen, 1, mode, &ciphertext_len);
|
||||
|
||||
if (ciphertext == NULL || ciphertext_len == 0)
|
||||
return NULL;
|
||||
|
||||
switch (mode) {
|
||||
case FISH_CBC_MODE:
|
||||
b64 = g_base64_encode((const unsigned char *) ciphertext, ciphertext_len);
|
||||
break;
|
||||
|
||||
case FISH_ECB_MODE:
|
||||
b64 = fish_base64_encode((const char *) ciphertext, ciphertext_len);
|
||||
}
|
||||
|
||||
g_free(ciphertext);
|
||||
|
||||
if (b64 == NULL)
|
||||
return NULL;
|
||||
|
||||
return b64;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an array of bytes with data decrypted
|
||||
* is binary safe
|
||||
*
|
||||
* @param [in] key Bytes of key
|
||||
* @param [in] keylen Size of key
|
||||
* @param [in] data Fish or standard Base64 encoded string
|
||||
* @param [in] mode Chiper mode
|
||||
* @param [out] final_len Length of returned array
|
||||
* @return Array of char with data decrypted
|
||||
*/
|
||||
char *fish_decrypt(const char *key, size_t keylen, const char *data, enum fish_mode mode, size_t *final_len) {
|
||||
size_t ciphertext_len = 0;
|
||||
char *ciphertext = NULL;
|
||||
char *plaintext = NULL;
|
||||
|
||||
*final_len = 0;
|
||||
|
||||
if (keylen == 0 || strlen(data) == 0)
|
||||
return NULL;
|
||||
|
||||
switch (mode) {
|
||||
case FISH_CBC_MODE:
|
||||
if (strspn(data, base64_chars) != strlen(data))
|
||||
return NULL;
|
||||
ciphertext = (char *) g_base64_decode(data, &ciphertext_len);
|
||||
break;
|
||||
|
||||
case FISH_ECB_MODE:
|
||||
ciphertext = fish_base64_decode(data, &ciphertext_len);
|
||||
}
|
||||
|
||||
if (ciphertext == NULL || ciphertext_len == 0)
|
||||
return NULL;
|
||||
|
||||
plaintext = fish_cipher(ciphertext, ciphertext_len, key, keylen, 0, mode, final_len);
|
||||
g_free(ciphertext);
|
||||
|
||||
if (*final_len == 0)
|
||||
return NULL;
|
||||
|
||||
return plaintext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Similar to fish_decrypt, but pad with zeros any after the first zero in the decrypted data
|
||||
*
|
||||
* @param [in] key Bytes of key
|
||||
* @param [in] keylen Size of key
|
||||
* @param [in] data Fish or standard Base64 encoded string
|
||||
* @param [in] mode Chiper mode
|
||||
* @return Array of char with data decrypted
|
||||
*/
|
||||
char *fish_decrypt_str(const char *key, size_t keylen, const char *data, enum fish_mode mode) {
|
||||
char *decrypted = NULL;
|
||||
char *plaintext_str = NULL;
|
||||
size_t decrypted_len = 0;
|
||||
|
||||
decrypted = fish_decrypt(key, strlen(key), data, mode, &decrypted_len);
|
||||
|
||||
if (decrypted == NULL || decrypted_len == 0)
|
||||
return NULL;
|
||||
|
||||
plaintext_str = g_strndup(decrypted, decrypted_len);
|
||||
g_free(decrypted);
|
||||
|
||||
return plaintext_str;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if a nick have a key
|
||||
*
|
||||
* @param [in] nick Nickname
|
||||
* @return TRUE if have a key or FALSE if not
|
||||
*/
|
||||
gboolean fish_nick_has_key(const char *nick) {
|
||||
gboolean has_key = FALSE;
|
||||
char *fish_encrypt_for_nick(const char *nick, const char *data) {
|
||||
char *key;
|
||||
enum fish_mode mode;
|
||||
char *encrypted;
|
||||
|
||||
key = keystore_get_key(nick, &mode);
|
||||
if (key) {
|
||||
has_key = TRUE;
|
||||
g_free(key);
|
||||
};
|
||||
|
||||
return has_key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypts a message (see fish_encrypt). The key is searched for in the key store
|
||||
*
|
||||
* @param [in] nick Nickname
|
||||
* @param [in] data Plaintext to encrypt
|
||||
* @param [out] omode Mode of encryption
|
||||
* @param [in] command_len Length of command to use without the message part
|
||||
* @return A list of encoded strings with the message encrypted or NULL if any error occurred
|
||||
*/
|
||||
GSList *fish_encrypt_for_nick(const char *nick, const char *data, enum fish_mode *omode, size_t command_len) {
|
||||
char *key;
|
||||
GSList *encrypted_list = NULL;
|
||||
char *encrypted = NULL;
|
||||
enum fish_mode mode;
|
||||
int max_len, max_chunks_len, chunks_len;
|
||||
|
||||
/* Look for key */
|
||||
key = keystore_get_key(nick, &mode);
|
||||
// Look for key
|
||||
key = keystore_get_key(nick);
|
||||
if (!key) return NULL;
|
||||
|
||||
*omode = mode;
|
||||
|
||||
/* Calculate max length of each line */
|
||||
max_len = MAX_COMMAND_LENGTH - command_len;
|
||||
/* Add '*' */
|
||||
if (mode == FISH_CBC_MODE) max_len--;
|
||||
|
||||
max_chunks_len = max_text_command_len(max_len, mode);
|
||||
|
||||
const char *data_chunk = data;
|
||||
|
||||
while(foreach_utf8_data_chunks(data_chunk, max_chunks_len, &chunks_len)) {
|
||||
encrypted = fish_encrypt(key, strlen(key), data_chunk, chunks_len, mode);
|
||||
|
||||
if (mode == FISH_CBC_MODE) {
|
||||
/* Add '*' for CBC */
|
||||
encrypted_list = g_slist_append(encrypted_list, g_strdup_printf("*%s", encrypted));
|
||||
g_free(encrypted);
|
||||
} else {
|
||||
encrypted_list = g_slist_append(encrypted_list, encrypted);
|
||||
}
|
||||
|
||||
/* Next chunk */
|
||||
data_chunk += chunks_len;
|
||||
}
|
||||
|
||||
return encrypted_list;
|
||||
|
||||
// Encrypt
|
||||
encrypted = fish_encrypt(key, strlen(key), data);
|
||||
|
||||
free(key);
|
||||
return encrypted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypts a message (see fish_decrypt). The key is searched for in the key store
|
||||
*
|
||||
* @param [in] nick Nickname
|
||||
* @param [in] data Plaintext to encrypt
|
||||
* @param [out] omode Mode of encryption
|
||||
* @return Plaintext message or NULL if any error occurred
|
||||
* Decrypts a message (see fish_decrypt). The key is searched for in the
|
||||
* key store.
|
||||
*/
|
||||
char *fish_decrypt_from_nick(const char *nick, const char *data, enum fish_mode *omode) {
|
||||
char *fish_decrypt_from_nick(const char *nick, const char *data) {
|
||||
char *key;
|
||||
char *decrypted;
|
||||
enum fish_mode mode;
|
||||
|
||||
/* Look for key */
|
||||
key = keystore_get_key(nick, &mode);
|
||||
// Look for key
|
||||
key = keystore_get_key(nick);
|
||||
if (!key) return NULL;
|
||||
|
||||
*omode = mode;
|
||||
|
||||
if (mode == FISH_CBC_MODE)
|
||||
++data;
|
||||
|
||||
/* Decrypt */
|
||||
decrypted = fish_decrypt_str(key, strlen(key), data, mode);
|
||||
g_free(key);
|
||||
|
||||
|
||||
// Decrypt
|
||||
decrypted = fish_decrypt(key, strlen(key), data);
|
||||
|
||||
free(key);
|
||||
return decrypted;
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2010 Samuel Lidén Borell <samuel@kodafritt.se>
|
||||
Copyright (c) 2019-2020 <bakasura@protonmail.ch>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@ -26,25 +25,13 @@
|
||||
#ifndef FISH_H
|
||||
#define FISH_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
enum fish_mode {
|
||||
FISH_ECB_MODE = 0x1,
|
||||
FISH_CBC_MODE = 0x2
|
||||
};
|
||||
|
||||
int fish_init(void);
|
||||
void fish_deinit(void);
|
||||
char *fish_base64_encode(const char *message, size_t message_len);
|
||||
char *fish_base64_decode(const char *message, size_t *final_len);
|
||||
char *fish_encrypt(const char *key, size_t keylen, const char *message, size_t message_len, enum fish_mode mode);
|
||||
char *fish_decrypt(const char *key, size_t keylen, const char *data, enum fish_mode mode, size_t *final_len);
|
||||
char *fish_decrypt_str(const char *key, size_t keylen, const char *data, enum fish_mode mode);
|
||||
gboolean fish_nick_has_key(const char *nick);
|
||||
GSList *fish_encrypt_for_nick(const char *nick, const char *data, enum fish_mode *omode, size_t command_len);
|
||||
char *fish_decrypt_from_nick(const char *nick, const char *data, enum fish_mode *omode);
|
||||
char *fish_encrypt(const char *key, size_t keylen, const char *message);
|
||||
char *fish_decrypt(const char *key, size_t keylen, const char *data);
|
||||
char *fish_encrypt_for_nick(const char *nick, const char *data);
|
||||
char *fish_decrypt_from_nick(const char *nick, const char *data);
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -1,8 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup Label="Configuration">
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<PlatformToolset>v120</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
@ -20,19 +19,57 @@
|
||||
<RootNamespace>fishlim</RootNamespace>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="..\..\win32\hexchat.props" />
|
||||
<PropertyGroup>
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="..\..\win32\hexchat.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="..\..\win32\hexchat.props" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<TargetName>hcfishlim</TargetName>
|
||||
<OutDir>$(HexChatRel)plugins\</OutDir>
|
||||
<OutDir>$(HexChatBin)</OutDir>
|
||||
<IntDir>$(HexChatObj)$(ProjectName)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<TargetName>hcfishlim</TargetName>
|
||||
<OutDir>$(HexChatBin)</OutDir>
|
||||
<IntDir>$(HexChatObj)$(ProjectName)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;FISHLIM_EXPORTS;HAVE_DH_SET0_PQG;HAVE_DH_GET0_KEY;HAVE_DH_SET0_KEY;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>$(DepsRoot)\include;$(Glib);..\..\src\common;$(HexChatLib);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;FISHLIM_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<AdditionalIncludeDirectories>$(DepsRoot)\include;$(Glib);..\..\src\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<ModuleDefinitionFile>fishlim.def</ModuleDefinitionFile>
|
||||
<AdditionalLibraryDirectories>$(DepsRoot)\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>$(DepLibs);%(AdditionalDependencies)</AdditionalDependencies>
|
||||
@ -40,10 +77,19 @@
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>WIN32;_WIN64;_AMD64_;NDEBUG;_WINDOWS;_USRDLL;FISHLIM_EXPORTS;HAVE_DH_SET0_PQG;HAVE_DH_GET0_KEY;HAVE_DH_SET0_KEY;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>$(DepsRoot)\include;$(Glib);..\..\src\common;$(HexChatLib);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;_WIN64;_AMD64_;NDEBUG;_WINDOWS;_USRDLL;FISHLIM_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<AdditionalIncludeDirectories>$(DepsRoot)\include;$(Glib);..\..\src\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<ModuleDefinitionFile>fishlim.def</ModuleDefinitionFile>
|
||||
<AdditionalLibraryDirectories>$(DepsRoot)\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>$(DepLibs);%(AdditionalDependencies)</AdditionalDependencies>
|
||||
@ -53,20 +99,21 @@
|
||||
<None Include="fishlim.def" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="dh1080.h" />
|
||||
<ClInclude Include="bool.h" />
|
||||
<ClInclude Include="fish.h" />
|
||||
<ClInclude Include="utils.h" />
|
||||
<ClInclude Include="irc.h" />
|
||||
<ClInclude Include="keystore.h" />
|
||||
<ClInclude Include="misc.h" />
|
||||
<ClInclude Include="plugin_hexchat.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="dh1080.c" />
|
||||
<ClCompile Include="fish.c" />
|
||||
<ClCompile Include="utils.c" />
|
||||
<ClCompile Include="irc.c" />
|
||||
<ClCompile Include="keystore.c" />
|
||||
<ClCompile Include="misc.c" />
|
||||
<ClCompile Include="plugin_hexchat.c" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
</Project>
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
@ -23,41 +23,35 @@
|
||||
<ClInclude Include="bool.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="dh1080.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="fish.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="utils.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="irc.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="keystore.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="misc.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="plugin_hexchat.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="dh1080.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="fish.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="utils.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="irc.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="keystore.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="misc.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="plugin_hexchat.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
|
@ -22,9 +22,8 @@
|
||||
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <glib.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "irc.h"
|
||||
|
||||
/**
|
||||
@ -32,28 +31,26 @@
|
||||
* at spaces. The prefix and command is extracted from the message, and
|
||||
* parameters_offset is set to the index of the first parameter.
|
||||
*/
|
||||
gboolean irc_parse_message(const char *words[],
|
||||
bool irc_parse_message(const char *words[],
|
||||
const char **prefix, const char **command,
|
||||
size_t *parameters_offset) {
|
||||
size_t w = 1;
|
||||
if (prefix) *prefix = NULL;
|
||||
if (command) *command = NULL;
|
||||
|
||||
/* See if the message starts with a prefix (sender user) */
|
||||
// See if the message starts with a prefix (sender user)
|
||||
if (words[w][0] == ':') {
|
||||
if (prefix) *prefix = &words[w][1];
|
||||
w++;
|
||||
}
|
||||
|
||||
/* Check command */
|
||||
if (words[w][0] == '\0') return FALSE;
|
||||
// Check command
|
||||
if (words[w][0] == '\0') return false;
|
||||
if (command) *command = words[w];
|
||||
w++;
|
||||
|
||||
if (parameters_offset)
|
||||
*parameters_offset = w;
|
||||
|
||||
return TRUE;
|
||||
*parameters_offset = w;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -68,15 +65,48 @@ gboolean irc_parse_message(const char *words[],
|
||||
*/
|
||||
char *irc_prefix_get_nick(const char *prefix) {
|
||||
const char *end;
|
||||
char *nick;
|
||||
size_t length;
|
||||
|
||||
if (!prefix) return NULL;
|
||||
|
||||
/* Find end of nick */
|
||||
// Find end of nick
|
||||
end = prefix;
|
||||
while (*end != '\0' && *end != '!' && *end != '@') end++;
|
||||
|
||||
/* Allocate string */
|
||||
// Allocate string
|
||||
length = end - prefix;
|
||||
return g_strndup (prefix, length);
|
||||
nick = malloc(length+1);
|
||||
if (!nick) return NULL;
|
||||
|
||||
// Copy to string
|
||||
memcpy(nick, prefix, length);
|
||||
nick[length] = '\0';
|
||||
return nick;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Compares two nick names. Return 0 if equal. Otherwise the return value is
|
||||
* less than zero if a is less than b or greater than zero if a is greater
|
||||
* than b.
|
||||
*/
|
||||
int irc_nick_cmp(const char *a, const char *b) {
|
||||
char ac;
|
||||
char bc;
|
||||
char diff;
|
||||
for (;;) {
|
||||
ac = *(a++);
|
||||
bc = *(b++);
|
||||
|
||||
// Change into IRC uppercase (see RFC 2812 section 2.2)
|
||||
if (ac >= 'a' && ac <= '~') ac &= ~0x20;
|
||||
if (bc >= 'a' && bc <= '~') bc &= ~0x20;
|
||||
|
||||
diff = ac - bc;
|
||||
if (diff) return diff;
|
||||
if (!ac) return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -25,13 +25,14 @@
|
||||
#ifndef IRC_H
|
||||
#define IRC_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <glib.h>
|
||||
|
||||
gboolean irc_parse_message(const char *words[],
|
||||
bool irc_parse_message(const char *words[],
|
||||
const char **prefix, const char **command,
|
||||
size_t *parameters_offset);
|
||||
char *irc_prefix_get_nick(const char *prefix);
|
||||
int irc_nick_cmp(const char *a, const char *b);
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -22,13 +22,12 @@
|
||||
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <glib.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "irc.h"
|
||||
#include "fish.h"
|
||||
#include "misc.h"
|
||||
#include "keystore.h"
|
||||
#include "plugin_hexchat.h"
|
||||
|
||||
@ -39,7 +38,7 @@ static char *keystore_password = NULL;
|
||||
/**
|
||||
* Opens the key store file: ~/.config/hexchat/addon_fishlim.conf
|
||||
*/
|
||||
static GKeyFile *getConfigFile(void) {
|
||||
static GKeyFile *getConfigFile() {
|
||||
gchar *filename = get_config_filename();
|
||||
|
||||
GKeyFile *keyfile = g_key_file_new();
|
||||
@ -55,30 +54,14 @@ static GKeyFile *getConfigFile(void) {
|
||||
/**
|
||||
* Returns the key store password, or the default.
|
||||
*/
|
||||
static const char *get_keystore_password(void) {
|
||||
static const char *get_keystore_password() {
|
||||
return (keystore_password != NULL ?
|
||||
keystore_password :
|
||||
/* Silly default value... */
|
||||
// Silly default value...
|
||||
"blowinikey");
|
||||
}
|
||||
|
||||
|
||||
static char *escape_nickname(const char *nick) {
|
||||
char *escaped = g_strdup(nick);
|
||||
char *p = escaped;
|
||||
|
||||
while (*p) {
|
||||
if (*p == '[')
|
||||
*p = '~';
|
||||
else if (*p == ']')
|
||||
*p = '!';
|
||||
|
||||
++p;
|
||||
}
|
||||
|
||||
return escaped;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a value for a nick/channel from addon_fishlim.conf. Unlike
|
||||
* g_key_file_get_string, this function is case insensitive.
|
||||
@ -103,65 +86,33 @@ static gchar *get_nick_value(GKeyFile *keyfile, const char *nick, const char *it
|
||||
/**
|
||||
* Extracts a key from the key store file.
|
||||
*/
|
||||
char *keystore_get_key(const char *nick, enum fish_mode *mode) {
|
||||
GKeyFile *keyfile;
|
||||
char *escaped_nick;
|
||||
gchar *value, *key_mode;
|
||||
int encrypted_mode;
|
||||
char *password;
|
||||
char *encrypted;
|
||||
char *decrypted;
|
||||
|
||||
/* Get the key */
|
||||
keyfile = getConfigFile();
|
||||
escaped_nick = escape_nickname(nick);
|
||||
value = get_nick_value(keyfile, escaped_nick, "key");
|
||||
key_mode = get_nick_value(keyfile, escaped_nick, "mode");
|
||||
char *keystore_get_key(const char *nick) {
|
||||
// Get the key
|
||||
GKeyFile *keyfile = getConfigFile();
|
||||
gchar *value = get_nick_value(keyfile, nick, "key");
|
||||
g_key_file_free(keyfile);
|
||||
g_free(escaped_nick);
|
||||
|
||||
/* Determine cipher mode */
|
||||
*mode = FISH_ECB_MODE;
|
||||
if (key_mode) {
|
||||
if (*key_mode == '1')
|
||||
*mode = FISH_ECB_MODE;
|
||||
else if (*key_mode == '2')
|
||||
*mode = FISH_CBC_MODE;
|
||||
g_free(key_mode);
|
||||
}
|
||||
|
||||
if (!value)
|
||||
return NULL;
|
||||
|
||||
if (strncmp(value, "+OK ", 4) == 0) {
|
||||
/* Key is encrypted */
|
||||
encrypted = (char *) value;
|
||||
encrypted += 4;
|
||||
|
||||
encrypted_mode = FISH_ECB_MODE;
|
||||
|
||||
if (*encrypted == '*') {
|
||||
++encrypted;
|
||||
encrypted_mode = FISH_CBC_MODE;
|
||||
}
|
||||
|
||||
password = (char *) get_keystore_password();
|
||||
decrypted = fish_decrypt_str((const char *) password, strlen(password), (const char *) encrypted, encrypted_mode);
|
||||
if (!value) return NULL;
|
||||
|
||||
if (strncmp(value, "+OK ", 4) != 0) {
|
||||
// Key is stored in plaintext
|
||||
return import_glib_string(value);
|
||||
} else {
|
||||
// Key is encrypted
|
||||
const char *encrypted = value+4;
|
||||
const char *password = get_keystore_password();
|
||||
char *decrypted = fish_decrypt(password, strlen(password), encrypted);
|
||||
g_free(value);
|
||||
return decrypted;
|
||||
} else {
|
||||
/* Key is stored in plaintext */
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a nick and the associated key in the key store file.
|
||||
*/
|
||||
static gboolean delete_nick(GKeyFile *keyfile, const char *nick) {
|
||||
static bool delete_nick(GKeyFile *keyfile, const char *nick) {
|
||||
gchar **group;
|
||||
gchar **groups = g_key_file_get_groups(keyfile, NULL);
|
||||
gboolean ok = FALSE;
|
||||
bool ok = false;
|
||||
|
||||
for (group = groups; *group != NULL; group++) {
|
||||
if (!irc_nick_cmp(*group, nick)) {
|
||||
@ -174,105 +125,85 @@ static gboolean delete_nick(GKeyFile *keyfile, const char *nick) {
|
||||
return ok;
|
||||
}
|
||||
|
||||
#if !GLIB_CHECK_VERSION(2,40,0)
|
||||
/**
|
||||
* Writes the key store file to disk.
|
||||
*/
|
||||
static gboolean keyfile_save_to_file (GKeyFile *keyfile, char *filename) {
|
||||
gboolean ok;
|
||||
|
||||
/* Serialize */
|
||||
static bool save_keystore(GKeyFile *keyfile) {
|
||||
char *filename;
|
||||
bool ok;
|
||||
// Serialize
|
||||
gsize file_length;
|
||||
gchar *file_data = g_key_file_to_data(keyfile, &file_length, NULL);
|
||||
if (!file_data)
|
||||
return FALSE;
|
||||
|
||||
/* Write to file */
|
||||
ok = g_file_set_contents (filename, file_data, file_length, NULL);
|
||||
g_free(file_data);
|
||||
return ok;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Writes the key store file to disk.
|
||||
*/
|
||||
static gboolean save_keystore(GKeyFile *keyfile) {
|
||||
char *filename;
|
||||
gboolean ok;
|
||||
|
||||
if (!file_data) return false;
|
||||
|
||||
// Write to file
|
||||
filename = get_config_filename();
|
||||
#if !GLIB_CHECK_VERSION(2,40,0)
|
||||
ok = keyfile_save_to_file (keyfile, filename);
|
||||
#else
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS /* Hide false positive */
|
||||
ok = g_key_file_save_to_file (keyfile, filename, NULL);
|
||||
G_GNUC_END_IGNORE_DEPRECATIONS
|
||||
#endif
|
||||
g_free (filename);
|
||||
|
||||
ok = g_file_set_contents(filename, file_data, file_length, NULL);
|
||||
g_free(filename);
|
||||
g_free(file_data);
|
||||
return ok;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a key in the key store file.
|
||||
*/
|
||||
gboolean keystore_store_key(const char *nick, const char *key, enum fish_mode mode) {
|
||||
bool keystore_store_key(const char *nick, const char *key) {
|
||||
const char *password;
|
||||
char *encrypted;
|
||||
char *wrapped;
|
||||
gboolean ok = FALSE;
|
||||
bool ok = false;
|
||||
GKeyFile *keyfile = getConfigFile();
|
||||
char *escaped_nick = escape_nickname(nick);
|
||||
|
||||
/* Remove old key */
|
||||
delete_nick(keyfile, escaped_nick);
|
||||
|
||||
/* Add new key */
|
||||
// Remove old key
|
||||
delete_nick(keyfile, nick);
|
||||
|
||||
// Add new key
|
||||
password = get_keystore_password();
|
||||
if (password) {
|
||||
/* Encrypt the password */
|
||||
encrypted = fish_encrypt(password, strlen(password), key, strlen(key), FISH_CBC_MODE);
|
||||
// Encrypt the password
|
||||
encrypted = fish_encrypt(password, strlen(password), key);
|
||||
if (!encrypted) goto end;
|
||||
|
||||
/* Prepend "+OK " */
|
||||
wrapped = g_strconcat("+OK *", encrypted, NULL);
|
||||
// Prepend "+OK "
|
||||
wrapped = g_strconcat("+OK ", encrypted, NULL);
|
||||
g_free(encrypted);
|
||||
|
||||
/* Store encrypted in file */
|
||||
g_key_file_set_string(keyfile, escaped_nick, "key", wrapped);
|
||||
g_free(wrapped);
|
||||
// Store encrypted in file
|
||||
g_key_file_set_string(keyfile, nick, "key", wrapped);
|
||||
free(wrapped);
|
||||
} else {
|
||||
/* Store unencrypted in file */
|
||||
g_key_file_set_string(keyfile, escaped_nick, "key", key);
|
||||
// Store unencrypted in file
|
||||
g_key_file_set_string(keyfile, nick, "key", key);
|
||||
}
|
||||
|
||||
/* Store cipher mode */
|
||||
g_key_file_set_integer(keyfile, escaped_nick, "mode", mode);
|
||||
|
||||
/* Save key store file */
|
||||
// Save key store file
|
||||
ok = save_keystore(keyfile);
|
||||
|
||||
end:
|
||||
g_key_file_free(keyfile);
|
||||
g_free(escaped_nick);
|
||||
return ok;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a nick from the key store.
|
||||
*/
|
||||
gboolean keystore_delete_nick(const char *nick) {
|
||||
bool keystore_delete_nick(const char *nick) {
|
||||
GKeyFile *keyfile = getConfigFile();
|
||||
char *escaped_nick = escape_nickname(nick);
|
||||
|
||||
/* Delete entry */
|
||||
gboolean ok = delete_nick(keyfile, escaped_nick);
|
||||
// Delete entry
|
||||
bool ok = delete_nick(keyfile, nick);
|
||||
|
||||
/* Save */
|
||||
// Save
|
||||
if (ok) save_keystore(keyfile);
|
||||
|
||||
g_key_file_free(keyfile);
|
||||
g_free(escaped_nick);
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
||||
void keystore_secure_free(void *ptr, size_t size) {
|
||||
secure_erase(ptr, size);
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
|
||||
|
@ -25,14 +25,14 @@
|
||||
#ifndef KEYSTORE_H
|
||||
#define KEYSTORE_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include <glib.h>
|
||||
#include "fish.h"
|
||||
char *keystore_get_key(const char *nick);
|
||||
bool keystore_store_key(const char *nick, const char *key);
|
||||
bool keystore_delete_nick(const char *nick);
|
||||
|
||||
char *keystore_get_key(const char *nick, enum fish_mode *mode);
|
||||
gboolean keystore_store_key(const char *nick, const char *key, enum fish_mode mode);
|
||||
gboolean keystore_delete_nick(const char *nick);
|
||||
void keystore_secure_free(void *ptr, size_t size);
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -1,23 +0,0 @@
|
||||
if not libssl_dep.found()
|
||||
error('fish plugin requires openssl')
|
||||
endif
|
||||
|
||||
# Run tests
|
||||
subdir('tests')
|
||||
|
||||
fishlim_sources = [
|
||||
'dh1080.c',
|
||||
'fish.c',
|
||||
'utils.c',
|
||||
'irc.c',
|
||||
'keystore.c',
|
||||
'plugin_hexchat.c'
|
||||
]
|
||||
|
||||
shared_module('fishlim', fishlim_sources,
|
||||
dependencies: [libgio_dep, hexchat_plugin_dep, libssl_dep],
|
||||
install: true,
|
||||
install_dir: plugindir,
|
||||
name_prefix: '',
|
||||
vs_module_defs: 'fishlim.def',
|
||||
)
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2020 <bakasura@protonmail.ch>
|
||||
Copyright (c) 2010 Samuel Lidén Borell <samuel@kodafritt.se>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@ -22,18 +22,33 @@
|
||||
|
||||
*/
|
||||
|
||||
#ifndef PLUGIN_HEXCHAT_FISHLIM_UTILS_H
|
||||
#define PLUGIN_HEXCHAT_FISHLIM_UTILS_H
|
||||
#include <glib.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "misc.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include "fish.h"
|
||||
|
||||
unsigned long base64_len(size_t plaintext_len);
|
||||
unsigned long base64_fish_len(size_t plaintext_len);
|
||||
unsigned long cbc_len(size_t plaintext_len);
|
||||
unsigned long ecb_len(size_t plaintext_len);
|
||||
unsigned long encoded_len(size_t plaintext_len, enum fish_mode mode);
|
||||
int max_text_command_len(size_t max_len, enum fish_mode mode);
|
||||
const char *foreach_utf8_data_chunks(const char *data, int max_chunk_len, int *chunk_len);
|
||||
void secure_erase(void *ptr, size_t size) {
|
||||
// "volatile" prevents this code from being optimized away
|
||||
volatile char* volptr = ptr;
|
||||
while (size--) *volptr++ = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-allocates a string with the native allocator.
|
||||
*/
|
||||
char *import_glib_string(gchar *gstr) {
|
||||
size_t size;
|
||||
char *native;
|
||||
if (g_mem_is_system_malloc()) return gstr;
|
||||
|
||||
size = strlen(gstr)+1;
|
||||
native = malloc(size);
|
||||
memcpy(native, gstr, size);
|
||||
|
||||
secure_erase(gstr, size);
|
||||
g_free(gstr);
|
||||
return native;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
@ -1,4 +1,5 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2010 Samuel Lidén Borell <samuel@kodafritt.se>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
@ -21,31 +22,15 @@
|
||||
|
||||
*/
|
||||
|
||||
#include "fish.h"
|
||||
#ifndef MISC_H
|
||||
#define MISC_H
|
||||
|
||||
/**
|
||||
* Extracts a key from the key store file.
|
||||
*/
|
||||
char *
|
||||
keystore_get_key(const char *nick, enum fish_mode *mode)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
void secure_erase(void *ptr, size_t size);
|
||||
|
||||
#ifdef __G_LIB_H__
|
||||
char *import_glib_string(gchar *gstr);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Sets a key in the key store file.
|
||||
*/
|
||||
gboolean
|
||||
keystore_store_key(const char *nick, const char *key, enum fish_mode mode)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a nick from the key store.
|
||||
*/
|
||||
gboolean
|
||||
keystore_delete_nick(const char *nick)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
@ -1,8 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2010-2011 Samuel Lidén Borell <samuel@kodafritt.se>
|
||||
Copyright (c) 2015 <the.cypher@gmail.com>
|
||||
Copyright (c) 2019-2020 <bakasura@protonmail.ch>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@ -24,258 +22,56 @@
|
||||
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <glib.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
// #pragma GCC visibility push(default)
|
||||
#include "hexchat-plugin.h"
|
||||
#define HEXCHAT_MAX_WORDS 32
|
||||
// #pragma GCC visibility pop
|
||||
|
||||
//#define EXPORT __attribute((visibility("default")))
|
||||
//#define EXPORT
|
||||
|
||||
#include "fish.h"
|
||||
#include "dh1080.h"
|
||||
#include "keystore.h"
|
||||
#include "irc.h"
|
||||
|
||||
static const char *fish_modes[] = {"", "ECB", "CBC", NULL};
|
||||
|
||||
static const char plugin_name[] = "FiSHLiM";
|
||||
static const char plugin_desc[] = "Encryption plugin for the FiSH protocol. Less is More!";
|
||||
static const char plugin_version[] = "1.0.0";
|
||||
|
||||
static const char usage_setkey[] = "Usage: SETKEY [<nick or #channel>] [<mode>:]<password>, sets the key for a channel or nick. Modes: ECB, CBC";
|
||||
static const char usage_delkey[] = "Usage: DELKEY [<nick or #channel>], deletes the key for a channel or nick";
|
||||
static const char usage_keyx[] = "Usage: KEYX [<nick>], performs DH1080 key-exchange with <nick>";
|
||||
static const char usage_topic[] = "Usage: TOPIC+ <topic>, sets a new encrypted topic for the current channel";
|
||||
static const char usage_notice[] = "Usage: NOTICE+ <nick or #channel> <notice>";
|
||||
static const char usage_msg[] = "Usage: MSG+ <nick or #channel> <message>";
|
||||
static const char plugin_version[] = "0.0.16";
|
||||
|
||||
static const char usage_setkey[] = "Usage: SETKEY [<nick or #channel>] <password>, sets the key for a channel or nick";
|
||||
static const char usage_delkey[] = "Usage: DELKEY <nick or #channel>, deletes the key for a channel or nick";
|
||||
|
||||
static hexchat_plugin *ph;
|
||||
static GHashTable *pending_exchanges;
|
||||
|
||||
|
||||
/**
|
||||
* Compare two nicks using the current plugin
|
||||
*/
|
||||
int irc_nick_cmp(const char *a, const char *b) {
|
||||
return hexchat_nickcmp (ph, a, b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the path to the key store file.
|
||||
*/
|
||||
gchar *get_config_filename(void) {
|
||||
char *filename_fs, *filename_utf8;
|
||||
|
||||
filename_utf8 = g_build_filename(hexchat_get_info(ph, "configdir"), "addon_fishlim.conf", NULL);
|
||||
filename_fs = g_filename_from_utf8 (filename_utf8, -1, NULL, NULL, NULL);
|
||||
|
||||
g_free (filename_utf8);
|
||||
return filename_fs;
|
||||
}
|
||||
|
||||
static inline gboolean irc_is_query (const char *name) {
|
||||
const char *chantypes = hexchat_list_str (ph, NULL, "chantypes");
|
||||
|
||||
return strchr (chantypes, name[0]) == NULL;
|
||||
}
|
||||
|
||||
static hexchat_context *find_context_on_network (const char *name) {
|
||||
hexchat_list *channels;
|
||||
hexchat_context *ret = NULL;
|
||||
int id;
|
||||
|
||||
if (hexchat_get_prefs(ph, "id", NULL, &id) != 2)
|
||||
return NULL;
|
||||
|
||||
channels = hexchat_list_get(ph, "channels");
|
||||
if (!channels)
|
||||
return NULL;
|
||||
|
||||
while (hexchat_list_next(ph, channels)) {
|
||||
int chan_id = hexchat_list_int(ph, channels, "id");
|
||||
const char *chan_name = hexchat_list_str(ph, channels, "channel");
|
||||
|
||||
if (chan_id == id && chan_name && irc_nick_cmp (chan_name, name) == 0) {
|
||||
ret = (hexchat_context*)hexchat_list_str(ph, channels, "context");
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
hexchat_list_free(ph, channels);
|
||||
return ret;
|
||||
gchar *get_config_filename() {
|
||||
return g_build_filename(hexchat_get_info(ph, "configdir"), "addon_fishlim.conf", NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrive the field for own user in current context
|
||||
* @return the field value
|
||||
* Appends data to a string. Returns true if there was sufficient memory.
|
||||
* Frees *s and returns false if an error occurs.
|
||||
*/
|
||||
char *get_my_info(const char *field, gboolean find_in_other_context) {
|
||||
char *result = NULL;
|
||||
const char *own_nick;
|
||||
hexchat_list *list;
|
||||
hexchat_context *ctx_current, *ctx_channel;
|
||||
|
||||
/* Display message */
|
||||
own_nick = hexchat_get_info(ph, "nick");
|
||||
|
||||
if (!own_nick)
|
||||
return NULL;
|
||||
|
||||
/* Get field for own nick if any */
|
||||
list = hexchat_list_get(ph, "users");
|
||||
if (list) {
|
||||
while (hexchat_list_next(ph, list)) {
|
||||
if (irc_nick_cmp(own_nick, hexchat_list_str(ph, list, "nick")) == 0)
|
||||
result = g_strdup(hexchat_list_str(ph, list, field));
|
||||
}
|
||||
hexchat_list_free(ph, list);
|
||||
static bool append(char **s, size_t *length, const char *data) {
|
||||
size_t datalen = strlen(data);
|
||||
char *extended = realloc(*s, *length + datalen + 1);
|
||||
if (!extended) {
|
||||
free(*s);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Try to get from a channel (we are outside a channel) */
|
||||
if (!find_in_other_context) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
list = hexchat_list_get(ph, "channels");
|
||||
if (list) {
|
||||
ctx_current = hexchat_get_context(ph);
|
||||
while (hexchat_list_next(ph, list)) {
|
||||
ctx_channel = (hexchat_context *) hexchat_list_str(ph, list, "context");
|
||||
|
||||
hexchat_set_context(ph, ctx_channel);
|
||||
result = get_my_info(field, FALSE);
|
||||
hexchat_set_context(ph, ctx_current);
|
||||
|
||||
if (result) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
hexchat_list_free(ph, list);
|
||||
}
|
||||
|
||||
return result;
|
||||
memcpy(extended + *length, data, datalen + 1);
|
||||
*s = extended;
|
||||
*length += datalen;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrive the prefix character for own nick in current context
|
||||
* @return @ or + or NULL
|
||||
*/
|
||||
char *get_my_own_prefix(void) {
|
||||
return get_my_info("prefix", FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrive the mask for own nick in current context
|
||||
* @return Host name in the form: user@host (or NULL if not known)
|
||||
*/
|
||||
char *get_my_own_host(void) {
|
||||
return get_my_info("host", TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the length of prefix for current user in current context
|
||||
*
|
||||
* @return Length of prefix
|
||||
*/
|
||||
int get_prefix_length(void) {
|
||||
char *own_host;
|
||||
int prefix_len = 0;
|
||||
|
||||
/* ':! ' + 'nick' + 'ident@host', e.g. ':user!~name@mynet.com ' */
|
||||
prefix_len = 3 + strlen(hexchat_get_info(ph, "nick"));
|
||||
own_host = get_my_own_host();
|
||||
if (own_host) {
|
||||
prefix_len += strlen(own_host);
|
||||
} else {
|
||||
/* https://stackoverflow.com/questions/8724954/what-is-the-maximum-number-of-characters-for-a-host-name-in-unix */
|
||||
prefix_len += 64;
|
||||
}
|
||||
g_free(own_host);
|
||||
|
||||
return prefix_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to decrypt the first occurrence of fish message
|
||||
*
|
||||
* @param message Message to decrypt
|
||||
* @param key Key of message
|
||||
* @return Array of char with decrypted message or NULL. The returned string
|
||||
* should be freed with g_free() when no longer needed.
|
||||
*/
|
||||
char *decrypt_raw_message(const char *message, const char *key) {
|
||||
const char *prefixes[] = {"+OK ", "mcps ", NULL};
|
||||
char *start = NULL, *end = NULL;
|
||||
char *left = NULL, *right = NULL;
|
||||
char *encrypted = NULL, *decrypted = NULL;
|
||||
int length = 0;
|
||||
int index_prefix;
|
||||
enum fish_mode mode;
|
||||
GString *message_decrypted;
|
||||
char *result = NULL;
|
||||
|
||||
if (message == NULL || key == NULL)
|
||||
return NULL;
|
||||
|
||||
for (index_prefix = 0; index_prefix < 2; index_prefix++) {
|
||||
start = g_strstr_len(message, strlen(message), prefixes[index_prefix]);
|
||||
if (start) {
|
||||
/* Length ALWAYS will be less that original message
|
||||
* add '[CBC] ' length */
|
||||
message_decrypted = g_string_sized_new(strlen(message) + 6);
|
||||
|
||||
/* Left part of message */
|
||||
left = g_strndup(message, start - message);
|
||||
g_string_append(message_decrypted, left);
|
||||
g_free(left);
|
||||
|
||||
/* Encrypted part */
|
||||
start += strlen(prefixes[index_prefix]);
|
||||
end = g_strstr_len(start, strlen(message), " ");
|
||||
if (end) {
|
||||
length = end - start;
|
||||
right = end;
|
||||
}
|
||||
|
||||
if (length > 0) {
|
||||
encrypted = g_strndup(start, length);
|
||||
} else {
|
||||
encrypted = g_strdup(start);
|
||||
}
|
||||
decrypted = fish_decrypt_from_nick(key, encrypted, &mode);
|
||||
g_free(encrypted);
|
||||
|
||||
if (decrypted == NULL) {
|
||||
g_string_free(message_decrypted, TRUE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Add encrypted flag */
|
||||
g_string_append(message_decrypted, "[");
|
||||
g_string_append(message_decrypted, fish_modes[mode]);
|
||||
g_string_append(message_decrypted, "] ");
|
||||
/* Decrypted message */
|
||||
g_string_append(message_decrypted, decrypted);
|
||||
g_free(decrypted);
|
||||
|
||||
/* Right part of message */
|
||||
if (right) {
|
||||
g_string_append(message_decrypted, right);
|
||||
}
|
||||
|
||||
result = message_decrypted->str;
|
||||
g_string_free(message_decrypted, FALSE);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*static int handle_debug(char *word[], char *word_eol[], void *userdata) {
|
||||
hexchat_printf(ph, "debug incoming: ");
|
||||
@ -290,178 +86,104 @@ char *decrypt_raw_message(const char *message, const char *key) {
|
||||
* Called when a message is to be sent.
|
||||
*/
|
||||
static int handle_outgoing(char *word[], char *word_eol[], void *userdata) {
|
||||
char *prefix;
|
||||
enum fish_mode mode;
|
||||
char *message;
|
||||
GString *command;
|
||||
GSList *encrypted_list, *encrypted_item;
|
||||
|
||||
const char *own_nick;
|
||||
// Encrypt the message if possible
|
||||
const char *channel = hexchat_get_info(ph, "channel");
|
||||
|
||||
/* Check if we can encrypt */
|
||||
if (!fish_nick_has_key(channel)) return HEXCHAT_EAT_NONE;
|
||||
|
||||
command = g_string_new("");
|
||||
g_string_printf(command, "PRIVMSG %s :+OK ", channel);
|
||||
|
||||
encrypted_list = fish_encrypt_for_nick(channel, word_eol[1], &mode, get_prefix_length() + command->len);
|
||||
if (!encrypted_list) {
|
||||
g_string_free(command, TRUE);
|
||||
return HEXCHAT_EAT_NONE;
|
||||
}
|
||||
|
||||
/* Get prefix for own nick if any */
|
||||
prefix = get_my_own_prefix();
|
||||
|
||||
/* Add encrypted flag */
|
||||
message = g_strconcat("[", fish_modes[mode], "] ", word_eol[1], NULL);
|
||||
|
||||
/* Display message */
|
||||
hexchat_emit_print(ph, "Your Message", hexchat_get_info(ph, "nick"), message, prefix, NULL);
|
||||
g_free(message);
|
||||
|
||||
/* Send encrypted messages */
|
||||
encrypted_item = encrypted_list;
|
||||
while (encrypted_item)
|
||||
{
|
||||
hexchat_commandf(ph, "%s%s", command->str, (char *)encrypted_item->data);
|
||||
|
||||
encrypted_item = encrypted_item->next;
|
||||
}
|
||||
|
||||
g_free(prefix);
|
||||
g_string_free(command, TRUE);
|
||||
g_slist_free_full(encrypted_list, g_free);
|
||||
|
||||
char *encrypted = fish_encrypt_for_nick(channel, word_eol[1]);
|
||||
if (!encrypted) return HEXCHAT_EAT_NONE;
|
||||
|
||||
// Display message
|
||||
own_nick = hexchat_get_info(ph, "nick");
|
||||
hexchat_emit_print(ph, "Your Message", own_nick, word_eol[1], NULL);
|
||||
|
||||
// Send message
|
||||
hexchat_commandf(ph, "PRIVMSG %s :+OK %s", channel, encrypted);
|
||||
|
||||
free(encrypted);
|
||||
return HEXCHAT_EAT_HEXCHAT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a channel message or private message is received.
|
||||
*/
|
||||
static int handle_incoming(char *word[], char *word_eol[], hexchat_event_attrs *attrs, void *userdata) {
|
||||
static int handle_incoming(char *word[], char *word_eol[], void *userdata) {
|
||||
const char *prefix;
|
||||
const char *command;
|
||||
const char *recipient;
|
||||
const char *raw_message = word_eol[1];
|
||||
const char *encrypted;
|
||||
const char *peice;
|
||||
char *sender_nick;
|
||||
char *decrypted;
|
||||
size_t parameters_offset;
|
||||
GString *message;
|
||||
char *message;
|
||||
size_t w;
|
||||
size_t ew;
|
||||
size_t uw;
|
||||
size_t length;
|
||||
|
||||
if (!irc_parse_message((const char **)word, &prefix, &command, ¶meters_offset))
|
||||
if (!irc_parse_message((const char **)word, &prefix, &command, &w))
|
||||
return HEXCHAT_EAT_NONE;
|
||||
|
||||
/* Topic (command 332) has an extra parameter */
|
||||
if (!strcmp(command, "332"))
|
||||
parameters_offset++;
|
||||
|
||||
/* Extract sender nick and recipient nick/channel and try to decrypt */
|
||||
recipient = word[parameters_offset];
|
||||
decrypted = decrypt_raw_message(raw_message, recipient);
|
||||
if (decrypted == NULL) {
|
||||
sender_nick = irc_prefix_get_nick(prefix);
|
||||
decrypted = decrypt_raw_message(raw_message, sender_nick);
|
||||
g_free(sender_nick);
|
||||
|
||||
// Topic (command 332) has an extra parameter
|
||||
if (!strcmp(command, "332")) w++;
|
||||
|
||||
// Look for encrypted data
|
||||
for (ew = w+1; ew < HEXCHAT_MAX_WORDS-1; ew++) {
|
||||
const char *s = (ew == w+1 ? word[ew]+1 : word[ew]);
|
||||
if (strcmp(s, "+OK") == 0 || strcmp(s, "mcps") == 0) goto has_encrypted_data;
|
||||
}
|
||||
|
||||
/* Nothing to decrypt */
|
||||
if (decrypted == NULL)
|
||||
return HEXCHAT_EAT_NONE;
|
||||
|
||||
/* Build decrypted message */
|
||||
|
||||
/* decrypted + 'RECV ' + '@time=YYYY-MM-DDTHH:MM:SS.fffffZ ' */
|
||||
message = g_string_sized_new (strlen(decrypted) + 5 + 33);
|
||||
g_string_append (message, "RECV ");
|
||||
|
||||
if (attrs->server_time_utc)
|
||||
{
|
||||
GTimeVal tv = { (glong)attrs->server_time_utc, 0 };
|
||||
char *timestamp = g_time_val_to_iso8601 (&tv);
|
||||
|
||||
g_string_append (message, "@time=");
|
||||
g_string_append (message, timestamp);
|
||||
g_string_append (message, " ");
|
||||
g_free (timestamp);
|
||||
}
|
||||
|
||||
g_string_append (message, decrypted);
|
||||
g_free(decrypted);
|
||||
|
||||
/* Fake server message
|
||||
* RECV command will throw this function again, if message have multiple
|
||||
* encrypted data, we will decrypt all */
|
||||
hexchat_command(ph, message->str);
|
||||
g_string_free (message, TRUE);
|
||||
|
||||
return HEXCHAT_EAT_HEXCHAT;
|
||||
}
|
||||
|
||||
static int handle_keyx_notice(char *word[], char *word_eol[], void *userdata) {
|
||||
const char *dh_message = word[4];
|
||||
const char *dh_pubkey = word[5];
|
||||
hexchat_context *query_ctx;
|
||||
const char *prefix;
|
||||
char *sender, *secret_key, *priv_key = NULL;
|
||||
enum fish_mode mode = FISH_ECB_MODE;
|
||||
|
||||
if (!*dh_message || !*dh_pubkey || strlen(dh_pubkey) != 181)
|
||||
return HEXCHAT_EAT_NONE;
|
||||
|
||||
if (!irc_parse_message((const char**)word, &prefix, NULL, NULL) || !prefix)
|
||||
return HEXCHAT_EAT_NONE;
|
||||
|
||||
sender = irc_prefix_get_nick(prefix);
|
||||
query_ctx = find_context_on_network(sender);
|
||||
if (query_ctx)
|
||||
g_assert(hexchat_set_context(ph, query_ctx) == 1);
|
||||
|
||||
dh_message++; /* : prefix */
|
||||
|
||||
if (g_strcmp0 (word[6], "CBC") == 0)
|
||||
mode = FISH_CBC_MODE;
|
||||
|
||||
if (!strcmp(dh_message, "DH1080_INIT")) {
|
||||
char *pub_key;
|
||||
|
||||
hexchat_printf(ph, "Received public key from %s (%s), sending mine...", sender, fish_modes[mode]);
|
||||
if (dh1080_generate_key(&priv_key, &pub_key)) {
|
||||
hexchat_commandf(ph, "quote NOTICE %s :DH1080_FINISH %s%s", sender, pub_key, (mode == FISH_CBC_MODE) ? " CBC" : "");
|
||||
g_free(pub_key);
|
||||
return HEXCHAT_EAT_NONE;
|
||||
has_encrypted_data: ;
|
||||
// Extract sender nick and recipient nick/channel
|
||||
sender_nick = irc_prefix_get_nick(prefix);
|
||||
recipient = word[w];
|
||||
|
||||
// Try to decrypt with these (the keys are searched for in the key store)
|
||||
encrypted = word[ew+1];
|
||||
decrypted = fish_decrypt_from_nick(recipient, encrypted);
|
||||
if (!decrypted) decrypted = fish_decrypt_from_nick(sender_nick, encrypted);
|
||||
|
||||
// Check for error
|
||||
if (!decrypted) goto decrypt_error;
|
||||
|
||||
// Build unecrypted message
|
||||
message = NULL;
|
||||
length = 0;
|
||||
if (!append(&message, &length, "RECV")) goto decrypt_error;
|
||||
|
||||
for (uw = 1; uw < HEXCHAT_MAX_WORDS; uw++) {
|
||||
if (word[uw][0] != '\0' && !append(&message, &length, " ")) goto decrypt_error;
|
||||
|
||||
if (uw == ew) {
|
||||
// Add the encrypted data
|
||||
peice = decrypted;
|
||||
uw++; // Skip "OK+"
|
||||
|
||||
if (ew == w+1) {
|
||||
// Prefix with colon, which gets stripped out otherwise
|
||||
if (!append(&message, &length, ":")) goto decrypt_error;
|
||||
}
|
||||
|
||||
} else {
|
||||
hexchat_print(ph, "Failed to generate keys");
|
||||
goto cleanup;
|
||||
// Add unencrypted data (for example, a prefix from a bouncer or bot)
|
||||
peice = word[uw];
|
||||
}
|
||||
} else if (!strcmp (dh_message, "DH1080_FINISH")) {
|
||||
char *sender_lower = g_ascii_strdown(sender, -1);
|
||||
/* FIXME: Properly respect irc casing */
|
||||
priv_key = g_hash_table_lookup(pending_exchanges, sender_lower);
|
||||
g_hash_table_steal(pending_exchanges, sender_lower);
|
||||
g_free(sender_lower);
|
||||
|
||||
if (!priv_key) {
|
||||
hexchat_printf(ph, "Received a key exchange response for unknown user: %s", sender);
|
||||
goto cleanup;
|
||||
}
|
||||
} else {
|
||||
/* Regular notice */
|
||||
g_free(sender);
|
||||
return HEXCHAT_EAT_NONE;
|
||||
|
||||
if (!append(&message, &length, peice)) goto decrypt_error;
|
||||
}
|
||||
|
||||
if (dh1080_compute_key(priv_key, dh_pubkey, &secret_key)) {
|
||||
keystore_store_key(sender, secret_key, mode);
|
||||
hexchat_printf(ph, "Stored new key for %s (%s)", sender, fish_modes[mode]);
|
||||
g_free(secret_key);
|
||||
} else {
|
||||
hexchat_print(ph, "Failed to create secret key!");
|
||||
}
|
||||
|
||||
cleanup:
|
||||
g_free(sender);
|
||||
g_free(priv_key);
|
||||
return HEXCHAT_EAT_ALL;
|
||||
free(decrypted);
|
||||
|
||||
// Simulate unencrypted message
|
||||
//hexchat_printf(ph, "simulating: %s\n", message);
|
||||
hexchat_command(ph, message);
|
||||
|
||||
free(message);
|
||||
free(sender_nick);
|
||||
return HEXCHAT_EAT_HEXCHAT;
|
||||
|
||||
decrypt_error:
|
||||
free(decrypted);
|
||||
free(sender_nick);
|
||||
return HEXCHAT_EAT_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -470,39 +192,30 @@ cleanup:
|
||||
static int handle_setkey(char *word[], char *word_eol[], void *userdata) {
|
||||
const char *nick;
|
||||
const char *key;
|
||||
enum fish_mode mode;
|
||||
|
||||
/* Check syntax */
|
||||
|
||||
// Check syntax
|
||||
if (*word[2] == '\0') {
|
||||
hexchat_printf(ph, "%s\n", usage_setkey);
|
||||
return HEXCHAT_EAT_HEXCHAT;
|
||||
}
|
||||
|
||||
|
||||
if (*word[3] == '\0') {
|
||||
/* /setkey password */
|
||||
// /setkey password
|
||||
nick = hexchat_get_info(ph, "channel");
|
||||
key = word_eol[2];
|
||||
} else {
|
||||
/* /setkey #channel password */
|
||||
// /setkey #channel password
|
||||
nick = word[2];
|
||||
key = word_eol[3];
|
||||
}
|
||||
|
||||
mode = FISH_ECB_MODE;
|
||||
if (g_ascii_strncasecmp("cbc:", key, 4) == 0) {
|
||||
key = key+4;
|
||||
mode = FISH_CBC_MODE;
|
||||
} else if (g_ascii_strncasecmp("ecb:", key, 4) == 0) {
|
||||
key = key+4;
|
||||
}
|
||||
|
||||
/* Set password */
|
||||
if (keystore_store_key(nick, key, mode)) {
|
||||
hexchat_printf(ph, "Stored key for %s (%s)\n", nick, fish_modes[mode]);
|
||||
|
||||
// Set password
|
||||
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");
|
||||
hexchat_printf(ph, "\00305Failed to store key in blow.ini\n", nick, key);
|
||||
}
|
||||
|
||||
|
||||
return HEXCHAT_EAT_HEXCHAT;
|
||||
}
|
||||
|
||||
@ -510,268 +223,26 @@ static int handle_setkey(char *word[], char *word_eol[], void *userdata) {
|
||||
* Command handler for /delkey
|
||||
*/
|
||||
static int handle_delkey(char *word[], char *word_eol[], void *userdata) {
|
||||
char *nick = NULL;
|
||||
int ctx_type = 0;
|
||||
|
||||
/* Delete key from input */
|
||||
if (*word[2] != '\0') {
|
||||
nick = g_strstrip(g_strdup(word_eol[2]));
|
||||
} else { /* Delete key from current context */
|
||||
nick = g_strdup(hexchat_get_info(ph, "channel"));
|
||||
ctx_type = hexchat_list_int(ph, NULL, "type");
|
||||
|
||||
/* Only allow channel or dialog */
|
||||
if (ctx_type < 2 || ctx_type > 3) {
|
||||
hexchat_printf(ph, "%s\n", usage_delkey);
|
||||
return HEXCHAT_EAT_HEXCHAT;
|
||||
}
|
||||
const char *nick;
|
||||
|
||||
// Check syntax
|
||||
if (*word[2] == '\0' || *word[3] != '\0') {
|
||||
hexchat_printf(ph, "%s\n", usage_delkey);
|
||||
return HEXCHAT_EAT_HEXCHAT;
|
||||
}
|
||||
|
||||
/* Delete the given nick from the key store */
|
||||
|
||||
nick = word_eol[2];
|
||||
|
||||
// Delete the given nick from the key store
|
||||
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");
|
||||
hexchat_printf(ph, "\00305Failed to delete key in blow.ini!\n", nick);
|
||||
}
|
||||
g_free(nick);
|
||||
|
||||
|
||||
return HEXCHAT_EAT_HEXCHAT;
|
||||
}
|
||||
|
||||
static int handle_keyx(char *word[], char *word_eol[], void *userdata) {
|
||||
const char *target = word[2];
|
||||
hexchat_context *query_ctx = NULL;
|
||||
char *pub_key, *priv_key;
|
||||
int ctx_type;
|
||||
|
||||
if (*target)
|
||||
query_ctx = find_context_on_network(target);
|
||||
else {
|
||||
target = hexchat_get_info(ph, "channel");
|
||||
query_ctx = hexchat_get_context (ph);
|
||||
}
|
||||
|
||||
if (query_ctx) {
|
||||
g_assert(hexchat_set_context(ph, query_ctx) == 1);
|
||||
ctx_type = hexchat_list_int(ph, NULL, "type");
|
||||
}
|
||||
|
||||
if ((query_ctx && ctx_type != 3) || (!query_ctx && !irc_is_query(target))) {
|
||||
hexchat_print(ph, "You can only exchange keys with individuals");
|
||||
return HEXCHAT_EAT_ALL;
|
||||
}
|
||||
|
||||
if (dh1080_generate_key(&priv_key, &pub_key)) {
|
||||
g_hash_table_replace (pending_exchanges, g_ascii_strdown(target, -1), priv_key);
|
||||
|
||||
hexchat_commandf(ph, "quote NOTICE %s :DH1080_INIT %s CBC", target, pub_key);
|
||||
hexchat_printf(ph, "Sent public key to %s (CBC), waiting for reply...", target);
|
||||
|
||||
g_free(pub_key);
|
||||
} else {
|
||||
hexchat_print(ph, "Failed to generate keys");
|
||||
}
|
||||
|
||||
return HEXCHAT_EAT_ALL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Command handler for /topic+
|
||||
*/
|
||||
static int handle_crypt_topic(char *word[], char *word_eol[], void *userdata) {
|
||||
const char *target;
|
||||
const char *topic = word_eol[2];
|
||||
enum fish_mode mode;
|
||||
GString *command;
|
||||
GSList *encrypted_list;
|
||||
|
||||
if (!*topic) {
|
||||
hexchat_print(ph, usage_topic);
|
||||
return HEXCHAT_EAT_ALL;
|
||||
}
|
||||
|
||||
if (hexchat_list_int(ph, NULL, "type") != 2) {
|
||||
hexchat_printf(ph, "Please change to the channel window where you want to set the topic!");
|
||||
return HEXCHAT_EAT_ALL;
|
||||
}
|
||||
|
||||
target = hexchat_get_info(ph, "channel");
|
||||
|
||||
/* Check if we can encrypt */
|
||||
if (!fish_nick_has_key(target)) {
|
||||
hexchat_printf(ph, "/topic+ error, no key found for %s", target);
|
||||
return HEXCHAT_EAT_ALL;
|
||||
}
|
||||
|
||||
command = g_string_new("");
|
||||
g_string_printf(command, "TOPIC %s +OK ", target);
|
||||
|
||||
encrypted_list = fish_encrypt_for_nick(target, topic, &mode, get_prefix_length() + command->len);
|
||||
if (!encrypted_list) {
|
||||
g_string_free(command, TRUE);
|
||||
hexchat_printf(ph, "/topic+ error, can't encrypt %s", target);
|
||||
return HEXCHAT_EAT_ALL;
|
||||
}
|
||||
|
||||
hexchat_commandf(ph, "%s%s", command->str, (char *) encrypted_list->data);
|
||||
|
||||
g_string_free(command, TRUE);
|
||||
g_slist_free_full(encrypted_list, g_free);
|
||||
|
||||
return HEXCHAT_EAT_ALL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Command handler for /notice+
|
||||
*/
|
||||
static int handle_crypt_notice(char *word[], char *word_eol[], void *userdata) {
|
||||
const char *target = word[2];
|
||||
const char *notice = word_eol[3];
|
||||
char *notice_flag;
|
||||
enum fish_mode mode;
|
||||
GString *command;
|
||||
GSList *encrypted_list, *encrypted_item;
|
||||
|
||||
if (!*target || !*notice) {
|
||||
hexchat_print(ph, usage_notice);
|
||||
return HEXCHAT_EAT_ALL;
|
||||
}
|
||||
|
||||
/* Check if we can encrypt */
|
||||
if (!fish_nick_has_key(target)) {
|
||||
hexchat_printf(ph, "/notice+ error, no key found for %s.", target);
|
||||
return HEXCHAT_EAT_ALL;
|
||||
}
|
||||
|
||||
command = g_string_new("");
|
||||
g_string_printf(command, "quote NOTICE %s :+OK ", target);
|
||||
|
||||
encrypted_list = fish_encrypt_for_nick(target, notice, &mode, get_prefix_length() + command->len);
|
||||
if (!encrypted_list) {
|
||||
g_string_free(command, TRUE);
|
||||
hexchat_printf(ph, "/notice+ error, can't encrypt %s", target);
|
||||
return HEXCHAT_EAT_ALL;
|
||||
}
|
||||
|
||||
notice_flag = g_strconcat("[", fish_modes[mode], "] ", notice, NULL);
|
||||
hexchat_emit_print(ph, "Notice Send", target, notice_flag);
|
||||
|
||||
/* Send encrypted messages */
|
||||
encrypted_item = encrypted_list;
|
||||
while (encrypted_item) {
|
||||
hexchat_commandf(ph, "%s%s", command->str, (char *) encrypted_item->data);
|
||||
|
||||
encrypted_item = encrypted_item->next;
|
||||
}
|
||||
|
||||
g_free(notice_flag);
|
||||
g_string_free(command, TRUE);
|
||||
g_slist_free_full(encrypted_list, g_free);
|
||||
|
||||
return HEXCHAT_EAT_ALL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Command handler for /msg+
|
||||
*/
|
||||
static int handle_crypt_msg(char *word[], char *word_eol[], void *userdata) {
|
||||
const char *target = word[2];
|
||||
const char *message = word_eol[3];
|
||||
char *message_flag;
|
||||
char *prefix;
|
||||
hexchat_context *query_ctx;
|
||||
enum fish_mode mode;
|
||||
GString *command;
|
||||
GSList *encrypted_list, *encrypted_item;
|
||||
|
||||
if (!*target || !*message) {
|
||||
hexchat_print(ph, usage_msg);
|
||||
return HEXCHAT_EAT_ALL;
|
||||
}
|
||||
|
||||
/* Check if we can encrypt */
|
||||
if (!fish_nick_has_key(target)) {
|
||||
hexchat_printf(ph, "/msg+ error, no key found for %s", target);
|
||||
return HEXCHAT_EAT_ALL;
|
||||
}
|
||||
|
||||
command = g_string_new("");
|
||||
g_string_printf(command, "PRIVMSG %s :+OK ", target);
|
||||
|
||||
encrypted_list = fish_encrypt_for_nick(target, message, &mode, get_prefix_length() + command->len);
|
||||
if (!encrypted_list) {
|
||||
g_string_free(command, TRUE);
|
||||
hexchat_printf(ph, "/msg+ error, can't encrypt %s", target);
|
||||
return HEXCHAT_EAT_ALL;
|
||||
}
|
||||
|
||||
/* Send encrypted messages */
|
||||
encrypted_item = encrypted_list;
|
||||
while (encrypted_item) {
|
||||
hexchat_commandf(ph, "%s%s", command->str, (char *) encrypted_item->data);
|
||||
|
||||
encrypted_item = encrypted_item->next;
|
||||
}
|
||||
|
||||
g_string_free(command, TRUE);
|
||||
g_slist_free_full(encrypted_list, g_free);
|
||||
|
||||
query_ctx = find_context_on_network(target);
|
||||
if (query_ctx) {
|
||||
g_assert(hexchat_set_context(ph, query_ctx) == 1);
|
||||
|
||||
prefix = get_my_own_prefix();
|
||||
|
||||
/* Add encrypted flag */
|
||||
message_flag = g_strconcat("[", fish_modes[mode], "] ", message, NULL);
|
||||
hexchat_emit_print(ph, "Your Message", hexchat_get_info(ph, "nick"), message_flag, prefix, NULL);
|
||||
g_free(prefix);
|
||||
g_free(message_flag);
|
||||
} else {
|
||||
hexchat_emit_print(ph, "Message Send", target, message);
|
||||
}
|
||||
|
||||
return HEXCHAT_EAT_ALL;
|
||||
}
|
||||
|
||||
static int handle_crypt_me(char *word[], char *word_eol[], void *userdata) {
|
||||
const char *channel = hexchat_get_info(ph, "channel");
|
||||
enum fish_mode mode;
|
||||
GString *command;
|
||||
GSList *encrypted_list, *encrypted_item;
|
||||
|
||||
/* Check if we can encrypt */
|
||||
if (!fish_nick_has_key(channel)) {
|
||||
return HEXCHAT_EAT_NONE;
|
||||
}
|
||||
|
||||
command = g_string_new("");
|
||||
g_string_printf(command, "PRIVMSG %s :\001ACTION +OK ", channel);
|
||||
|
||||
/* 2 = ' \001' */
|
||||
encrypted_list = fish_encrypt_for_nick(channel, word_eol[2], &mode, get_prefix_length() + command->len + 2);
|
||||
if (!encrypted_list) {
|
||||
g_string_free(command, TRUE);
|
||||
hexchat_printf(ph, "/me error, can't encrypt %s", channel);
|
||||
return HEXCHAT_EAT_ALL;
|
||||
}
|
||||
|
||||
hexchat_emit_print(ph, "Your Action", hexchat_get_info(ph, "nick"), word_eol[2], NULL);
|
||||
|
||||
/* Send encrypted messages */
|
||||
encrypted_item = encrypted_list;
|
||||
while (encrypted_item) {
|
||||
hexchat_commandf(ph, "%s%s \001", command->str, (char *) encrypted_item->data);
|
||||
|
||||
encrypted_item = encrypted_item->next;
|
||||
}
|
||||
|
||||
g_string_free(command, TRUE);
|
||||
g_slist_free_full(encrypted_list, g_free);
|
||||
|
||||
return HEXCHAT_EAT_ALL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the plugin name version information.
|
||||
*/
|
||||
@ -791,48 +262,30 @@ int hexchat_plugin_init(hexchat_plugin *plugin_handle,
|
||||
const char **version,
|
||||
char *arg) {
|
||||
ph = plugin_handle;
|
||||
|
||||
|
||||
/* Send our info to HexChat */
|
||||
*name = plugin_name;
|
||||
*desc = plugin_desc;
|
||||
*version = plugin_version;
|
||||
|
||||
|
||||
/* Register commands */
|
||||
hexchat_hook_command(ph, "SETKEY", HEXCHAT_PRI_NORM, handle_setkey, usage_setkey, NULL);
|
||||
hexchat_hook_command(ph, "DELKEY", HEXCHAT_PRI_NORM, handle_delkey, usage_delkey, NULL);
|
||||
hexchat_hook_command(ph, "KEYX", HEXCHAT_PRI_NORM, handle_keyx, usage_keyx, NULL);
|
||||
hexchat_hook_command(ph, "TOPIC+", HEXCHAT_PRI_NORM, handle_crypt_topic, usage_topic, NULL);
|
||||
hexchat_hook_command(ph, "NOTICE+", HEXCHAT_PRI_NORM, handle_crypt_notice, usage_notice, NULL);
|
||||
hexchat_hook_command(ph, "MSG+", HEXCHAT_PRI_NORM, handle_crypt_msg, usage_msg, NULL);
|
||||
hexchat_hook_command(ph, "ME", HEXCHAT_PRI_NORM, handle_crypt_me, NULL, NULL);
|
||||
|
||||
|
||||
/* Add handlers */
|
||||
hexchat_hook_command(ph, "", HEXCHAT_PRI_NORM, handle_outgoing, NULL, NULL);
|
||||
hexchat_hook_server(ph, "NOTICE", HEXCHAT_PRI_HIGHEST, handle_keyx_notice, NULL);
|
||||
hexchat_hook_server_attrs(ph, "NOTICE", HEXCHAT_PRI_NORM, handle_incoming, NULL);
|
||||
hexchat_hook_server_attrs(ph, "PRIVMSG", HEXCHAT_PRI_NORM, handle_incoming, NULL);
|
||||
/* hexchat_hook_server(ph, "RAW LINE", HEXCHAT_PRI_NORM, handle_debug, NULL); */
|
||||
hexchat_hook_server_attrs(ph, "TOPIC", HEXCHAT_PRI_NORM, handle_incoming, NULL);
|
||||
hexchat_hook_server_attrs(ph, "332", HEXCHAT_PRI_NORM, handle_incoming, NULL);
|
||||
|
||||
if (!fish_init())
|
||||
return 0;
|
||||
|
||||
if (!dh1080_init())
|
||||
return 0;
|
||||
|
||||
pending_exchanges = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
|
||||
|
||||
hexchat_hook_server(ph, "NOTICE", HEXCHAT_PRI_NORM, handle_incoming, NULL);
|
||||
hexchat_hook_server(ph, "PRIVMSG", HEXCHAT_PRI_NORM, handle_incoming, NULL);
|
||||
//hexchat_hook_server(ph, "RAW LINE", HEXCHAT_PRI_NORM, handle_debug, NULL);
|
||||
hexchat_hook_server(ph, "TOPIC", HEXCHAT_PRI_NORM, handle_incoming, NULL);
|
||||
hexchat_hook_server(ph, "332", HEXCHAT_PRI_NORM, handle_incoming, NULL);
|
||||
|
||||
hexchat_printf(ph, "%s plugin loaded\n", plugin_name);
|
||||
/* Return success */
|
||||
return 1;
|
||||
}
|
||||
|
||||
int hexchat_plugin_deinit(void) {
|
||||
g_clear_pointer(&pending_exchanges, g_hash_table_destroy);
|
||||
dh1080_deinit();
|
||||
fish_deinit();
|
||||
|
||||
hexchat_printf(ph, "%s plugin unloaded\n", plugin_name);
|
||||
return 1;
|
||||
}
|
||||
|
@ -25,8 +25,7 @@
|
||||
#ifndef PLUGIN_HEXCHAT_H
|
||||
#define PLUGIN_HEXCHAT_H
|
||||
|
||||
gchar *get_config_filename(void);
|
||||
int irc_nick_cmp (const char *, const char *);
|
||||
gchar *get_config_filename();
|
||||
|
||||
#endif
|
||||
|
||||
|
91
plugins/fishlim/test.c
Normal file
@ -0,0 +1,91 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2010 Samuel Lidén Borell <samuel@kodafritt.se>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <glib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "fish.h"
|
||||
|
||||
// We can't use the HexChat plugin API from here...
|
||||
gchar *get_config_filename() {
|
||||
const gchar *homedir = g_get_home_dir();
|
||||
return g_build_filename(homedir, ".xchat2", "blow.ini", NULL);
|
||||
}
|
||||
|
||||
|
||||
static int decrypt(int nick_count, char *nicks[]) {
|
||||
char encrypted[8192];
|
||||
while (fgets(encrypted, sizeof(encrypted), stdin)) {
|
||||
char *msg;
|
||||
for (int i = 0; i < nick_count; i++) {
|
||||
msg = fish_decrypt_from_nick(nicks[i], encrypted);
|
||||
if (msg) goto success;
|
||||
}
|
||||
fprintf(stderr, "None of the recipients were found in the key store!\n");
|
||||
return 1;
|
||||
success:
|
||||
fprintf(stderr, "Decrypted text >>>%s<<<\n", msg);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int encrypt(int nick_count, char *nicks[]) {
|
||||
char message[8192];
|
||||
while (fgets(message, sizeof(message), stdin)) {
|
||||
// Remove newline character
|
||||
char *newline = strchr(message, '\n');
|
||||
if (newline) *newline = '\0';
|
||||
|
||||
bool error = false;
|
||||
for (int i = 0; i < nick_count; i++) {
|
||||
char *encrypted = fish_encrypt_for_nick(nicks[i], message);
|
||||
if (encrypted) {
|
||||
fprintf(stderr, "Encrypted [%s]: >>>%s<<<\n", nicks[i], encrypted);
|
||||
} else {
|
||||
error = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (error) {
|
||||
fprintf(stderr, "Some of the recipients were't found in the key store!\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if (argc < 2) {
|
||||
fprintf(stderr, "usage: %s [-e] nick...\n", argv[0]);
|
||||
return 2;
|
||||
}
|
||||
|
||||
if (strcmp(argv[1], "-e") == 0) {
|
||||
return encrypt(argc-2, &argv[2]);
|
||||
} else {
|
||||
return decrypt(argc-1, &argv[1]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,16 +0,0 @@
|
||||
fishlim_test_sources = [
|
||||
'tests.c',
|
||||
'mock-keystore.c',
|
||||
'../fish.c',
|
||||
'../utils.c',
|
||||
]
|
||||
|
||||
fishlim_tests = executable('fishlim_tests', fishlim_test_sources,
|
||||
dependencies: [libgio_dep, libssl_dep, hexchat_plugin_dep],
|
||||
include_directories: include_directories('..'),
|
||||
)
|
||||
|
||||
test('Fishlim Tests', fishlim_tests,
|
||||
protocol: 'tap',
|
||||
timeout: 600,
|
||||
)
|
@ -1,285 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2020 <bakasura@protonmail.ch>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <glib.h>
|
||||
|
||||
#include "fish.h"
|
||||
#include "utils.h"
|
||||
|
||||
/**
|
||||
* Auxiliary function: Generate a random string
|
||||
* @param out Preallocated string to fill
|
||||
* @param len Size of bytes to fill
|
||||
*/
|
||||
static void
|
||||
random_string(char *out, size_t len)
|
||||
{
|
||||
GRand *rand = NULL;
|
||||
int i = 0;
|
||||
|
||||
rand = g_rand_new();
|
||||
for (i = 0; i < len; ++i) {
|
||||
out[i] = g_rand_int_range(rand, 1, 256);
|
||||
}
|
||||
|
||||
out[len] = 0;
|
||||
|
||||
g_rand_free(rand);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check encrypt and decrypt in ECB mode
|
||||
*/
|
||||
static void
|
||||
test_ecb(void)
|
||||
{
|
||||
char *b64 = NULL;
|
||||
char *de = NULL;
|
||||
int key_len, message_len = 0;
|
||||
char key[57];
|
||||
char message[1000];
|
||||
|
||||
/* Generate key 32–448 bits (Yes, I start with 8 bits) */
|
||||
for (key_len = 1; key_len < 57; ++key_len) {
|
||||
|
||||
random_string(key, key_len);
|
||||
|
||||
for (message_len = 1; message_len < 1000; ++message_len) {
|
||||
random_string(message, message_len);
|
||||
|
||||
/* Encrypt */
|
||||
b64 = fish_encrypt(key, key_len, message, message_len, FISH_ECB_MODE);
|
||||
g_assert_nonnull(b64);
|
||||
|
||||
/* Decrypt */
|
||||
/* Linear */
|
||||
de = fish_decrypt_str(key, key_len, b64, FISH_ECB_MODE);
|
||||
g_assert_cmpstr (de, ==, message);
|
||||
g_free(de);
|
||||
|
||||
/* Mixed */
|
||||
de = fish_decrypt_str(key, key_len, b64, FISH_ECB_MODE);
|
||||
g_assert_cmpstr (de, ==, message);
|
||||
g_free(de);
|
||||
|
||||
g_free(b64);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check encrypt and decrypt in CBC mode
|
||||
*/
|
||||
static void
|
||||
test_cbc(void)
|
||||
{
|
||||
char *b64 = NULL;
|
||||
char *de = NULL;
|
||||
int key_len, message_len = 0;
|
||||
char key[57];
|
||||
char message[1000];
|
||||
|
||||
/* Generate key 32–448 bits (Yes, I start with 8 bits) */
|
||||
for (key_len = 1; key_len < 57; ++key_len) {
|
||||
|
||||
random_string(key, key_len);
|
||||
|
||||
for (message_len = 1; message_len < 1000; ++message_len) {
|
||||
random_string(message, message_len);
|
||||
|
||||
/* Encrypt */
|
||||
b64 = fish_encrypt(key, key_len, message, message_len, FISH_CBC_MODE);
|
||||
g_assert_nonnull(b64);
|
||||
|
||||
/* Decrypt */
|
||||
/* Linear */
|
||||
de = fish_decrypt_str(key, key_len, b64, FISH_CBC_MODE);
|
||||
g_assert_cmpstr (de, ==, message);
|
||||
g_free(de);
|
||||
|
||||
g_free(b64);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the calculation of final length from an encoded string in Base64
|
||||
*/
|
||||
static void
|
||||
test_base64_len (void)
|
||||
{
|
||||
char *b64 = NULL;
|
||||
char message[1000];
|
||||
int message_end = sizeof (message) - 1;
|
||||
|
||||
random_string(message, message_end);
|
||||
|
||||
for (; message_end >= 0; --message_end) {
|
||||
message[message_end] = '\0'; /* Truncate instead of generating new strings */
|
||||
b64 = g_base64_encode((const unsigned char *) message, message_end);
|
||||
g_assert_nonnull(b64);
|
||||
g_assert_cmpuint(strlen(b64), == , base64_len(message_end));
|
||||
g_free(b64);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the calculation of final length from an encoded string in BlowcryptBase64
|
||||
*/
|
||||
static void
|
||||
test_base64_fish_len (void)
|
||||
{
|
||||
char *b64 = NULL;
|
||||
int message_len = 0;
|
||||
char message[1000];
|
||||
|
||||
for (message_len = 1; message_len < 1000; ++message_len) {
|
||||
random_string(message, message_len);
|
||||
b64 = fish_base64_encode(message, message_len);
|
||||
g_assert_nonnull(b64);
|
||||
g_assert_cmpuint(strlen(b64), == , base64_fish_len(message_len));
|
||||
g_free(b64);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the calculation of final length from an encrypted string in ECB mode
|
||||
*/
|
||||
static void
|
||||
test_base64_ecb_len(void)
|
||||
{
|
||||
char *b64 = NULL;
|
||||
int key_len, message_len = 0;
|
||||
char key[57];
|
||||
char message[1000];
|
||||
|
||||
/* Generate key 32–448 bits (Yes, I start with 8 bits) */
|
||||
for (key_len = 1; key_len < 57; ++key_len) {
|
||||
|
||||
random_string(key, key_len);
|
||||
|
||||
for (message_len = 1; message_len < 1000; ++message_len) {
|
||||
random_string(message, message_len);
|
||||
b64 = fish_encrypt(key, key_len, message, message_len, FISH_ECB_MODE);
|
||||
g_assert_nonnull(b64);
|
||||
g_assert_cmpuint(strlen(b64), == , ecb_len(message_len));
|
||||
g_free(b64);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the calculation of final length from an encrypted string in CBC mode
|
||||
*/
|
||||
static void
|
||||
test_base64_cbc_len(void)
|
||||
{
|
||||
char *b64 = NULL;
|
||||
int key_len, message_len = 0;
|
||||
char key[57];
|
||||
char message[1000];
|
||||
|
||||
/* Generate key 32–448 bits (Yes, I start with 8 bits) */
|
||||
for (key_len = 1; key_len < 57; ++key_len) {
|
||||
|
||||
random_string(key, key_len);
|
||||
|
||||
for (message_len = 1; message_len < 1000; ++message_len) {
|
||||
random_string(message, message_len);
|
||||
b64 = fish_encrypt(key, key_len, message, message_len, FISH_CBC_MODE);
|
||||
g_assert_nonnull(b64);
|
||||
g_assert_cmpuint(strlen(b64), == , cbc_len(message_len));
|
||||
g_free(b64);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the calculation of length limit for a plaintext in each encryption mode
|
||||
*/
|
||||
static void
|
||||
test_max_text_command_len(void)
|
||||
{
|
||||
int max_encoded_len, plaintext_len;
|
||||
enum fish_mode mode;
|
||||
|
||||
for (max_encoded_len = 0; max_encoded_len < 10000; ++max_encoded_len) {
|
||||
for (mode = FISH_ECB_MODE; mode <= FISH_CBC_MODE; ++mode) {
|
||||
plaintext_len = max_text_command_len(max_encoded_len, mode);
|
||||
g_assert_cmpuint(encoded_len(plaintext_len, mode), <= , max_encoded_len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the calculation of length limit for a plaintext in each encryption mode
|
||||
*/
|
||||
static void
|
||||
test_foreach_utf8_data_chunks(void)
|
||||
{
|
||||
GRand *rand = NULL;
|
||||
GString *chunks = NULL;
|
||||
int max_chunks_len, chunks_len;
|
||||
char ascii_message[1001];
|
||||
char *data_chunk = NULL;
|
||||
|
||||
rand = g_rand_new();
|
||||
max_chunks_len = g_rand_int_range(rand, 2, 301);
|
||||
random_string(ascii_message, 1000);
|
||||
|
||||
data_chunk = ascii_message;
|
||||
|
||||
chunks = g_string_new(NULL);
|
||||
|
||||
while (foreach_utf8_data_chunks(data_chunk, max_chunks_len, &chunks_len)) {
|
||||
g_string_append(chunks, g_strndup(data_chunk, chunks_len));
|
||||
/* Next chunk */
|
||||
data_chunk += chunks_len;
|
||||
}
|
||||
/* Check data loss */
|
||||
g_assert_cmpstr(chunks->str, == , ascii_message);
|
||||
|
||||
g_string_free(chunks, TRUE);
|
||||
g_rand_free (rand);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[]) {
|
||||
|
||||
g_test_init(&argc, &argv, NULL);
|
||||
|
||||
g_test_add_func("/fishlim/ecb", test_ecb);
|
||||
g_test_add_func("/fishlim/cbc", test_cbc);
|
||||
g_test_add_func("/fishlim/base64_len", test_base64_len);
|
||||
g_test_add_func("/fishlim/base64_fish_len", test_base64_fish_len);
|
||||
g_test_add_func("/fishlim/base64_ecb_len", test_base64_ecb_len);
|
||||
g_test_add_func("/fishlim/base64_cbc_len", test_base64_cbc_len);
|
||||
g_test_add_func("/fishlim/max_text_command_len", test_max_text_command_len);
|
||||
g_test_add_func("/fishlim/foreach_utf8_data_chunks", test_foreach_utf8_data_chunks);
|
||||
|
||||
fish_init();
|
||||
int ret = g_test_run();
|
||||
fish_deinit();
|
||||
return ret;
|
||||
}
|
@ -1,151 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2020 <bakasura@protonmail.ch>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "utils.h"
|
||||
#include "fish.h"
|
||||
|
||||
/**
|
||||
* Calculate the length of Base64-encoded string
|
||||
*
|
||||
* @param plaintext_len Size of clear text to encode
|
||||
* @return Size of encoded string
|
||||
*/
|
||||
unsigned long base64_len(size_t plaintext_len) {
|
||||
int length_unpadded = (4 * plaintext_len) / 3;
|
||||
/* Add padding */
|
||||
return length_unpadded % 4 != 0 ? length_unpadded + (4 - length_unpadded % 4) : length_unpadded;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the length of BlowcryptBase64-encoded string
|
||||
*
|
||||
* @param plaintext_len Size of clear text to encode
|
||||
* @return Size of encoded string
|
||||
*/
|
||||
unsigned long base64_fish_len(size_t plaintext_len) {
|
||||
int length_unpadded = (12 * plaintext_len) / 8;
|
||||
/* Add padding */
|
||||
return length_unpadded % 12 != 0 ? length_unpadded + (12 - length_unpadded % 12) : length_unpadded;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the length of fish-encrypted string in CBC mode
|
||||
*
|
||||
* @param plaintext_len Size of clear text to encode
|
||||
* @return Size of encoded string
|
||||
*/
|
||||
unsigned long cbc_len(size_t plaintext_len) {
|
||||
/*IV + DATA + Zero Padding */
|
||||
return base64_len(8 + (plaintext_len % 8 != 0 ? plaintext_len + 8 - (plaintext_len % 8) : plaintext_len));
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the length of fish-encrypted string in ECB mode
|
||||
*
|
||||
* @param plaintext_len Size of clear text to encode
|
||||
* @return Size of encoded string
|
||||
*/
|
||||
unsigned long ecb_len(size_t plaintext_len) {
|
||||
return base64_fish_len(plaintext_len);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the length of encrypted string in 'mode' mode
|
||||
*
|
||||
* @param plaintext_len Length of plaintext
|
||||
* @param mode Encryption mode
|
||||
* @return Size of encoded string
|
||||
*/
|
||||
unsigned long encoded_len(size_t plaintext_len, enum fish_mode mode) {
|
||||
switch (mode) {
|
||||
|
||||
case FISH_CBC_MODE:
|
||||
return cbc_len(plaintext_len);
|
||||
break;
|
||||
|
||||
case FISH_ECB_MODE:
|
||||
return ecb_len(plaintext_len);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the maximum length of plaintext for a 'max_len' limit taking care the overload of encryption
|
||||
*
|
||||
* @param max_len Limit for plaintext
|
||||
* @param mode Encryption mode
|
||||
* @return Maximum allowed plaintext length
|
||||
*/
|
||||
int max_text_command_len(size_t max_len, enum fish_mode mode) {
|
||||
int len;
|
||||
|
||||
for (len = max_len; encoded_len(len, mode) > max_len; --len);
|
||||
return len;
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterate over 'data' in chunks of 'max_chunk_len' taking care the UTF-8 characters
|
||||
*
|
||||
* @param data Data to iterate
|
||||
* @param max_chunk_len Size of biggest chunk
|
||||
* @param [out] chunk_len Current chunk length
|
||||
* @return Pointer to current chunk position or NULL if not have more chunks
|
||||
*/
|
||||
const char *foreach_utf8_data_chunks(const char *data, int max_chunk_len, int *chunk_len) {
|
||||
int data_len, last_chunk_len = 0;
|
||||
|
||||
if (!*data) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Last chunk of data */
|
||||
data_len = strlen(data);
|
||||
if (data_len <= max_chunk_len) {
|
||||
*chunk_len = data_len;
|
||||
return data;
|
||||
}
|
||||
|
||||
*chunk_len = 0;
|
||||
const char *utf8_character = data;
|
||||
|
||||
/* Not valid UTF-8, but maybe valid text, just split into max length */
|
||||
if (!g_utf8_validate(data, -1, NULL)) {
|
||||
*chunk_len = max_chunk_len;
|
||||
return utf8_character;
|
||||
}
|
||||
|
||||
while (*utf8_character && *chunk_len <= max_chunk_len) {
|
||||
last_chunk_len = *chunk_len;
|
||||
*chunk_len = (g_utf8_next_char(utf8_character) - data) * sizeof(*utf8_character);
|
||||
utf8_character = g_utf8_next_char(utf8_character);
|
||||
}
|
||||
|
||||
/* We need the previous length before overflow the limit */
|
||||
*chunk_len = last_chunk_len;
|
||||
|
||||
return utf8_character;
|
||||
}
|
69
plugins/gtkpref/gtkpref.c
Normal file
@ -0,0 +1,69 @@
|
||||
/* HexChat
|
||||
* Copyright (c) 2011-2012 Berke Viktor.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "hexchat-plugin.h"
|
||||
|
||||
static hexchat_plugin *ph; /* plugin handle */
|
||||
|
||||
static void
|
||||
launch_tool ()
|
||||
{
|
||||
STARTUPINFO si;
|
||||
PROCESS_INFORMATION pi;
|
||||
|
||||
ZeroMemory (&si, sizeof (si));
|
||||
si.cb = sizeof (si);
|
||||
ZeroMemory (&pi, sizeof (pi));
|
||||
|
||||
if (!CreateProcess ( NULL, "gtk2-prefs.exe", NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
|
||||
{
|
||||
hexchat_print (ph, "Error launching the GTK+ Preference Tool! Maybe the executable is missing?");
|
||||
}
|
||||
|
||||
CloseHandle (pi.hProcess);
|
||||
CloseHandle (pi.hThread);
|
||||
}
|
||||
|
||||
int
|
||||
hexchat_plugin_init (hexchat_plugin *plugin_handle, char **plugin_name, char **plugin_desc, char **plugin_version, char *arg)
|
||||
{
|
||||
ph = plugin_handle;
|
||||
|
||||
*plugin_name = "GTKPref";
|
||||
*plugin_desc = "GTK+ Preference Tool Launcher";
|
||||
*plugin_version = "1.0";
|
||||
|
||||
hexchat_hook_command (ph, "GTKPREF", HEXCHAT_PRI_NORM, launch_tool, 0, 0);
|
||||
hexchat_command (ph, "MENU -ietc\\gtkpref.png ADD \"Settings/GTK+ Preferences\" \"GTKPREF\"");
|
||||
|
||||
return 1; /* return 1 for success */
|
||||
}
|
||||
|
||||
int
|
||||
hexchat_plugin_deinit (void)
|
||||
{
|
||||
hexchat_command (ph, "MENU DEL \"Settings/GTK+ Preferences\"");
|
||||
|
||||
return 1;
|
||||
}
|
18
plugins/gtkpref/makefile.mak
Normal file
@ -0,0 +1,18 @@
|
||||
include "..\..\src\makeinc.mak"
|
||||
|
||||
all: gtkpref.obj gtkpref.def
|
||||
link $(LDFLAGS) $(LIBS) /dll /out:xcgtkpref.dll /def:gtkpref.def gtkpref.obj
|
||||
|
||||
gtkpref.def:
|
||||
echo EXPORTS > gtkpref.def
|
||||
echo hexchat_plugin_init >> gtkpref.def
|
||||
echo hexchat_plugin_deinit >> gtkpref.def
|
||||
|
||||
gtkpref.obj: gtkpref.c makefile.mak
|
||||
cl $(CFLAGS) $(GLIB) /I.. gtkpref.c
|
||||
|
||||
clean:
|
||||
del *.obj
|
||||
del *.dll
|
||||
del *.exp
|
||||
del *.lib
|
1767
plugins/lua/lua.c
@ -1,54 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup Label="Configuration">
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
</PropertyGroup>
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{4C0F3940-2EEE-4646-82F7-6CE75B9A72F4}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>lua</RootNamespace>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="..\..\win32\hexchat.props" />
|
||||
<PropertyGroup>
|
||||
<TargetName>$(LuaOutput)</TargetName>
|
||||
<OutDir>$(HexChatRel)plugins\</OutDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;$(OwnFlags);%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>$(Glib);$(LuaInclude);..\..\src\common;$(HexChatLib);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>"$(LuaLib).lib";$(DepLibs);%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(DepsRoot)\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>WIN32;_WIN64;_AMD64_;NDEBUG;_WINDOWS;_USRDLL;$(OwnFlags);%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>$(Glib);$(LuaInclude);..\..\src\common;$(HexChatLib);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>"$(LuaLib).lib";$(DepLibs);%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(DepsRoot)\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="lua.c" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
</Project>
|
@ -1,12 +0,0 @@
|
||||
if cc.get_id() == 'msvc'
|
||||
lua_dep = cc.find_library('lua51')
|
||||
else
|
||||
lua_dep = dependency(get_option('with-lua'))
|
||||
endif
|
||||
|
||||
shared_module('lua', 'lua.c',
|
||||
dependencies: [libgio_dep, hexchat_plugin_dep, lua_dep],
|
||||
install: true,
|
||||
install_dir: plugindir,
|
||||
name_prefix: '',
|
||||
)
|
25
plugins/mailcheck/Makefile.am
Normal file
@ -0,0 +1,25 @@
|
||||
## Process with automake to produce Makefile.in
|
||||
|
||||
# To create a standalone tarball of your plugin run the plugin_dist
|
||||
# target. Note: you must configure the main source tree with
|
||||
# --enable-maintainer-mode
|
||||
|
||||
# These two must be defined.
|
||||
PLUGIN=mailcheck
|
||||
PLUGIN_VERSION=0.1
|
||||
|
||||
# This file must be in the form PLUGIN-config.h.in, it can be empty but
|
||||
# must exist
|
||||
EXTRA_DIST = mailcheck-config.h.in
|
||||
|
||||
# Remember to include this line in your Makefile.am
|
||||
include @top_srcdir@/plugins/Make.plugin
|
||||
|
||||
libdir = $(hexchatdir)/plugins
|
||||
|
||||
lib_LTLIBRARIES = mailcheck.la
|
||||
mailcheck_la_SOURCES = mailcheck.c
|
||||
mailcheck_la_LDFLAGS = -avoid-version -module
|
||||
INCLUDES = $(COMMON_CFLAGS) $(PLUGIN_INCLUDES)
|
||||
|
||||
DISTCLEANFILES = pg_dir/*
|
94
plugins/mailcheck/mailcheck.c
Normal file
@ -0,0 +1,94 @@
|
||||
/* HexChat 2.0 plugin: Mail checker */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "hexchat-plugin.h"
|
||||
|
||||
|
||||
static hexchat_plugin *ph; /* plugin handle */
|
||||
|
||||
static int
|
||||
mail_items(char *file)
|
||||
{
|
||||
FILE *fp;
|
||||
int items;
|
||||
char buf[512];
|
||||
|
||||
fp = fopen(file, "r");
|
||||
if(!fp)
|
||||
return 1;
|
||||
|
||||
items = 0;
|
||||
while(fgets(buf, sizeof buf, fp))
|
||||
{
|
||||
if(!strncmp(buf, "From ", 5))
|
||||
items++;
|
||||
}
|
||||
fclose(fp);
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
static void
|
||||
xchat_mail_check (void)
|
||||
{
|
||||
static int last_size = -1;
|
||||
int size;
|
||||
struct stat st;
|
||||
char buf[512];
|
||||
char *maildir;
|
||||
|
||||
maildir = getenv("MAIL");
|
||||
if(!maildir)
|
||||
{
|
||||
snprintf (buf, sizeof(buf), "/var/spool/mail/%s", getenv("USER"));
|
||||
maildir = buf;
|
||||
}
|
||||
|
||||
if(stat(maildir, &st) < 0)
|
||||
return;
|
||||
|
||||
size = st.st_size;
|
||||
|
||||
if(last_size == -1)
|
||||
{
|
||||
last_size = size;
|
||||
return;
|
||||
}
|
||||
|
||||
if(size > last_size)
|
||||
{
|
||||
hexchat_printf(ph,
|
||||
"-\0033-\0039-\017\tYou have new mail (%d messages, %d bytes total).",
|
||||
mail_items(maildir), size);
|
||||
}
|
||||
|
||||
last_size = size;
|
||||
}
|
||||
|
||||
static int timeout_cb(void *userdata)
|
||||
{
|
||||
xchat_mail_check();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int hexchat_plugin_init(hexchat_plugin *plugin_handle,
|
||||
char **plugin_name, char **plugin_desc, char **plugin_version,
|
||||
char *arg)
|
||||
{
|
||||
ph = plugin_handle;
|
||||
|
||||
*plugin_name = "MailCheck";
|
||||
*plugin_desc = "Checks your mailbox every 30 seconds";
|
||||
*plugin_version = "0.1";
|
||||
|
||||
hexchat_hook_timer(ph, 30000, timeout_cb, 0);
|
||||
|
||||
return 1;
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
plugindir = join_paths(get_option('libdir'), 'hexchat/plugins')
|
||||
|
||||
if host_machine.system() == 'windows'
|
||||
if get_option('with-exec')
|
||||
subdir('exec')
|
||||
endif
|
||||
|
||||
if get_option('with-upd')
|
||||
subdir('upd')
|
||||
endif
|
||||
|
||||
if get_option('with-winamp')
|
||||
subdir('winamp')
|
||||
endif
|
||||
endif
|
||||
|
||||
if get_option('with-checksum')
|
||||
subdir('checksum')
|
||||
endif
|
||||
|
||||
if get_option('with-fishlim')
|
||||
subdir('fishlim')
|
||||
endif
|
||||
|
||||
if get_option('with-lua') != 'false'
|
||||
subdir('lua')
|
||||
endif
|
||||
|
||||
if get_option('with-perl') != 'false'
|
||||
subdir('perl')
|
||||
endif
|
||||
|
||||
if get_option('with-python') != 'false'
|
||||
subdir('python')
|
||||
endif
|
||||
|
||||
if get_option('with-sysinfo')
|
||||
subdir('sysinfo')
|
||||
endif
|
167
plugins/mpcinfo/functions.c
Normal file
@ -0,0 +1,167 @@
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/*
|
||||
typedef int (*MYPROC)(HWND,HWND,char*,char*,BOOL,BOOL);
|
||||
|
||||
int dllProc(char *name, char *data){
|
||||
HINSTANCE hinstLib;
|
||||
hinstLib = LoadLibrary("mpcinfo");
|
||||
//MYPROC proc;
|
||||
int res;
|
||||
if (hinstLib != NULL){
|
||||
//proc = ;
|
||||
if ((MYPROC) GetProcAddress(hinstLib, name)!=NULL){
|
||||
res=(MYPROC)(NULL,NULL,data,NULL,TRUE,TRUE);
|
||||
}
|
||||
else{fprintf(stderr,"can't get proc: %s\n",name);res=-2;}
|
||||
}
|
||||
else{fprintf(stderr,"can't access dll\n");return -1;}
|
||||
FreeLibrary(hinstLib);
|
||||
return res;
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
int dllProc(char *name, char *data)
|
||||
{
|
||||
static HMODULE lib = NULL;
|
||||
if (!lib)
|
||||
{
|
||||
lib = LoadLibraryA ("mpcinfo");
|
||||
if (!lib)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
FreeLibrary (lib);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
*/
|
||||
|
||||
char *split(char *text, char seperator){
|
||||
//if (DEBUG==1) putlog("splitting");
|
||||
int i;int pos=-1;
|
||||
for (i=0;i<strlen(text);i++){
|
||||
if (text[i]==seperator){pos=i;i=strlen(text)+1;}
|
||||
}
|
||||
if (pos==-1) return text;
|
||||
text[pos]=0;
|
||||
return &(text[pos+1]);
|
||||
}
|
||||
|
||||
int endsWith(char *text, char *suffix){
|
||||
char *tmp=strstr(text,suffix);
|
||||
if (tmp==NULL) return 0;
|
||||
if (strlen(tmp)==strlen(suffix)) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int inStr(char *s1, int sl1, char *s2){
|
||||
//if (DEBUG==1) putlog("checking instr");
|
||||
int i;int j;
|
||||
for(i=0;i<sl1-strlen(s2);i++){
|
||||
for (j=0;j<strlen(s2);j++){
|
||||
if (s1[i+j]!=s2[j]) j=strlen(s2)+2;
|
||||
}
|
||||
if (j==strlen(s2)) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static char *subString(char *text, int first, int length, int spcKill){
|
||||
//if (DEBUG==1) putlog("creating substring");
|
||||
char *ret=(char*) calloc (length+1,sizeof(char)); //malloc(sizeof(char)*(length+1));
|
||||
int i;
|
||||
ret[length]=0;
|
||||
for (i=0;i<length;i++){
|
||||
ret[i]=text[i+first];
|
||||
//if (ret[i]==0) ret[i]='0';
|
||||
}
|
||||
if (spcKill==1){
|
||||
for (i=length-1;i>=0;i--){
|
||||
if (ret[i]==32) ret[i]=0;
|
||||
else i=-1;
|
||||
}
|
||||
}
|
||||
//if (DEBUG==1) putlog("substring created");
|
||||
return ret;
|
||||
}
|
||||
|
||||
static char *substring(char *text, int first, int length){return subString(text,first,length,0);}
|
||||
|
||||
|
||||
char *readLine(FILE *f){
|
||||
//if (DEBUG==1) putlog("reading line from file");
|
||||
char *buffer=(char*)calloc(1024,sizeof(char)); //malloc(sizeof(char)*1024);
|
||||
int pos=0;
|
||||
int cc=0;
|
||||
while((cc!=EOF)&&(pos<1024)&&(cc!=10)){
|
||||
cc=fgetc(f);
|
||||
if ((cc!=10)&&(cc!=13)){
|
||||
if (cc==EOF) buffer[pos]=0;
|
||||
else buffer[pos]=(char)cc;pos++;
|
||||
}
|
||||
}
|
||||
if (buffer[pos]==EOF) hexchat_printf(ph,"EOF: %i\n",pos);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
char *toUpper(char *text){
|
||||
//if (DEBUG==1) putlog("converting text to upper case");
|
||||
char *ret=(char*) calloc(strlen(text)+1,sizeof(char));
|
||||
int i;
|
||||
for (i=0;i<strlen(text);i++) ret[i]=toupper(text[i]);
|
||||
ret[strlen(text)]=0;
|
||||
//if (DEBUG==1) putlog("uc done");
|
||||
return ret;
|
||||
}
|
||||
|
||||
static char *str3cat(char *s1, char *s2, char *s3){
|
||||
//if (DEBUG==1) putlog("cating 3 strings");
|
||||
char *ret=(char*)calloc(strlen(s1)+strlen(s2)+strlen(s3)+1,sizeof(char));
|
||||
strcpy(ret,s1);strcat(ret,s2);strcat(ret,s3);
|
||||
ret[strlen(s1)+strlen(s2)+strlen(s3)]=0;
|
||||
//if (DEBUG==1) putlog("strings cated");
|
||||
return ret;
|
||||
}
|
||||
|
||||
char *replace(char *text, char *from, char *to){
|
||||
//if (DEBUG==1) putlog("replacing");
|
||||
char *ret=(char*)calloc( strlen(text)+(strlen(to)-strlen(from)),sizeof(char));
|
||||
char *left;
|
||||
char *right;
|
||||
int pos=inStr(text,strlen(text),from);
|
||||
if (pos!=-1){
|
||||
left=substring(text,0,pos);
|
||||
right=substring(text,pos+strlen(from),strlen(text)-(pos+strlen(from)));
|
||||
ret=str3cat(left,to,right);
|
||||
return replace(ret,from,to);
|
||||
}
|
||||
//if (DEBUG==1) putlog("replaced");
|
||||
return text;
|
||||
}
|
||||
|
||||
char *intReplaceF(char *text, char *from, int to, char *form){
|
||||
//if (DEBUG==1) putlog("replaceF");
|
||||
char *buffer=(char*) calloc(16,sizeof(char));
|
||||
sprintf(buffer,form,to);
|
||||
//if (DEBUG==1) putlog("replaceF done");
|
||||
return replace(text,from,buffer);
|
||||
}
|
||||
|
||||
char *intReplace(char *text, char *from, int to){return intReplaceF(text,from,to,"%i");}
|