echo "$EOF" >> $GITHUB_ENV
- name: Build
- uses: openwrt/gh-action-sdk@v5
+ uses: openwrt/gh-action-sdk@v7
env:
ARCH: ${{ matrix.arch }}-${{ env.BRANCH }}
FEEDNAME: packages_ci
INDEX: 1
KEY_BUILD: ${{ env.KEY_BUILD }}
+ V: s
- name: Move created packages to project dir
+ if: always()
run: cp bin/packages/${{ matrix.arch }}/packages_ci/* . || true
- name: Collect metadata
+ if: always()
run: |
MERGE_ID=$(git rev-parse --short HEAD)
echo "MERGE_ID=$MERGE_ID" >> $GITHUB_ENV
echo "ARCHIVE_NAME=${{matrix.arch}}-PR$PRNUMBER-$MERGE_ID" >> $GITHUB_ENV
- name: Generate metadata
+ if: always()
run: |
cat << _EOF_ > PKG-INFO
Metadata-Version: 2.1
cat PKG-INFO
- name: Store packages
+ if: always()
uses: actions/upload-artifact@v3
with:
name: ${{env.ARCHIVE_NAME}}-packages
PKG-INFO
- name: Store logs
+ if: always()
uses: actions/upload-artifact@v3
with:
name: ${{env.ARCHIVE_NAME}}-logs
PKG-INFO
- name: Remove logs
+ if: always()
run: sudo rm -rf logs/ || true
- name: Check if any packages were built
include $(TOPDIR)/rules.mk
GO_VERSION_MAJOR_MINOR:=1.21
-GO_VERSION_PATCH:=3
+GO_VERSION_PATCH:=4
PKG_NAME:=golang
PKG_VERSION:=$(GO_VERSION_MAJOR_MINOR)$(if $(GO_VERSION_PATCH),.$(GO_VERSION_PATCH))
PKG_SOURCE:=go$(PKG_VERSION).src.tar.gz
PKG_SOURCE_URL:=$(GO_SOURCE_URLS)
-PKG_HASH:=186f2b6f8c8b704e696821b09ab2041a5c1ee13dcbc3156a13adcf75931ee488
+PKG_HASH:=47b26a83d2b65a3c1c1bcace273b69bee49a7a7b5168a7604ded3d26a37bd787
PKG_MAINTAINER:=Jeffery To <jeffery.to@gmail.com>
PKG_LICENSE:=BSD-3-Clause
include $(TOPDIR)/rules.mk
PKG_NAME:=lua-eco
-PKG_VERSION:=3.0.1
+PKG_VERSION:=3.1.0
PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL=https://github.com/zhaojh329/lua-eco/releases/download/v$(PKG_VERSION)
-PKG_HASH:=96f008932e319739df2fe99dc1cba7e9a1a389015a4b96ad0f63d95bb6422b09
+PKG_HASH:=bb48af3f65a2c5d69b06b32ec2734bcb77cc6315b208be4fe3b0ae5fc0a82a33
PKG_MAINTAINER:=Jianhui Zhao <zhaojh329@gmail.com>
PKG_LICENSE:=MIT
Package/lua-eco-netlink=$(call Package/lua-eco/Module,netlink,+lua-eco-socket)
Package/lua-eco-ip=$(call Package/lua-eco/Module,ip utils,+lua-eco-netlink)
Package/lua-eco-nl80211=$(call Package/lua-eco/Module,nl80211,+lua-eco-netlink)
+Package/lua-eco-ssh=$(call Package/lua-eco/Module,ssh,+lua-eco-socket +libssh2)
define Package/lua-eco-ssl/config
choice
$(INSTALL_BIN) $(PKG_BUILD_DIR)/nl80211.so $(1)/usr/local/lib/lua/5.3/eco/core
endef
+define Package/lua-eco-ssh/install
+ $(INSTALL_DIR) $(1)/usr/local/lib/lua/5.3/eco/core
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/ssh.lua $(1)/usr/local/lib/lua/5.3/eco
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/ssh.so $(1)/usr/local/lib/lua/5.3/eco/core
+endef
+
$(eval $(call BuildPackage,lua-eco))
$(eval $(call BuildPackage,lua-eco-log))
$(eval $(call BuildPackage,lua-eco-base64))
$(eval $(call BuildPackage,lua-eco-netlink))
$(eval $(call BuildPackage,lua-eco-ip))
$(eval $(call BuildPackage,lua-eco-nl80211))
+$(eval $(call BuildPackage,lua-eco-ssh))
include $(TOPDIR)/rules.mk
PKG_NAME:=luajit2
-PKG_VERSION:=2.1-20231006
+PKG_VERSION:=2.1-20231117
PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://github.com/openresty/luajit2/archive/refs/tags/v$(PKG_VERSION).tar.gz?
-PKG_HASH:=41530b3f00d3f284e771cfd09add2a0c672f1214f8780644ca9261da9e4d9310
+PKG_HASH:=cc92968c57c00303eb9eaebf65cc8b29a0f851670f16bb514896ab5057ae381f
PKG_MAINTAINER:=Javier Marcet <javier@marcet.info>
PKG_LICENSE:=MIT
include $(TOPDIR)/rules.mk
PKG_NAME:=node
-PKG_VERSION:=v20.9.0
+PKG_VERSION:=v20.10.0
PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
PKG_SOURCE_URL:=https://nodejs.org/dist/$(PKG_VERSION)
-PKG_HASH:=a23d96810abf0455426b349d47ce5310f33095b7bc0571b9cc510f481c3a4519
+PKG_HASH:=32eb256eebd8cacd5574e6631e54b42be7ec8ebe25ad47a8ca685403bad15535
PKG_MAINTAINER:=Hirokazu MORIKAWA <morikw2@gmail.com>, Adrian Panella <ianchi74@outlook.com>
PKG_LICENSE:=MIT
--- a/lib/internal/modules/cjs/loader.js
+++ b/lib/internal/modules/cjs/loader.js
-@@ -1378,7 +1378,8 @@ Module._initPaths = function() {
+@@ -1537,7 +1537,8 @@ Module._initPaths = function() {
path.resolve(process.execPath, '..') :
path.resolve(process.execPath, '..', '..');
PKG_NAME:=perl
PKG_VERSION:=$(PERL_VERSION)
-PKG_RELEASE:=10
-
-PKG_SOURCE_URL:=\
- https://cpan.metacpan.org/src/5.0 \
- https://cpan.uib.no/src/5.0 \
- https://mirrors.rit.edu/CPAN/src/5.0 \
- https://mirror.transip.net/CPAN/src/5.0 \
- https://mirrors.sonic.net/cpan/src/5.0 \
- https://www.cpan.org/src/5.0
+PKG_RELEASE:=1
+
+PKG_SOURCE_URL:=https://www.cpan.org/src/5.0
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
-PKG_HASH:=fea7162d4cca940a387f0587b93f6737d884bf74d8a9d7cfd978bc12cd0b202d
+PKG_HASH:=eca551caec3bc549a4e590c0015003790bdd1a604ffe19cc78ee631d51f7072e
PKG_LICENSE:=GPL-1.0-or-later Artistic-1.0-Perl
PKG_LICENSE_FILES:=Copying Artistic README
-PKG_MAINTAINER:=Marcel Denia <naoir@gmx.net>, \
- Philip Prindeville <philipp@redfish-solutions.com>
+PKG_MAINTAINER:=Marcel Denia <naoir@gmx.net>, Philip Prindeville <philipp@redfish-solutions.com>
PKG_CPE_ID:=cpe:/a:perl:perl
# Build settings
d_atanh='define'
d_atolf='undef'
d_atoll='define'
+d_attribute_always_inline='define'
d_attribute_deprecated='define'
d_attribute_format='define'
d_attribute_malloc='define'
d_attribute_noreturn='define'
d_attribute_pure='define'
d_attribute_unused='define'
+d_attribute_visibility='define'
d_attribute_warn_unused_result='define'
d_backtrace='define'
d_bcmp='define'
d_fd_set='define'
d_fdclose='undef'
d_fdim='define'
+d_ffs='define'
+d_ffsl='define'
d_fgetpos='define'
d_finite='define'
d_finitel='undef'
d_gdbmndbm_h_uses_prototypes='undef'
d_getaddrinfo='define'
d_getcwd='define'
+d_getenv_preserves_other_thread='define'
d_getespwnam='undef'
d_getfsstat='undef'
d_getgrent='define'
d_nextafter='define'
d_nice='define'
d_nl_langinfo='define'
+d_nl_langinfo_l='define'
+d_non_int_bitfields='define'
d_nv_zero_is_allbits_zero='define'
d_old_pthread_create_joinable='undef'
d_oldpthreads='undef'
d_semop='define'
d_sendmsg='define'
d_setegid='define'
+d_setenv='define'
d_seteuid='define'
d_setgrent='define'
d_setgrent_r='undef'
d_setitimer='define'
d_setlinebuf='define'
d_setlocale='define'
+d_setlocale_accepts_any_locale_name='undef'
d_setlocale_r='undef'
d_setnent='define'
d_setnetent_r='undef'
d_snprintf='define'
d_sockaddr_in6="$owrt:ipv6"
d_sockaddr_sa_len='undef'
+d_sockaddr_storage='define'
d_sockatmark='undef'
d_sockatmarkproto='undef'
d_socket='define'
d_strtoull='define'
d_strtouq='define'
d_strxfrm='define'
+d_strxfrm_l='define'
d_suidsafe='undef'
d_symlink='define'
d_syscall='define'
d_telldir='define'
d_telldirproto='define'
d_tgamma='define'
+d_thread_local='define'
d_thread_safe_nl_langinfo_l='define'
d_time='define'
d_timegm='define'
d_times='define'
d_tm_tm_gmtoff='define'
d_tm_tm_zone='define'
+d_towlower='define'
+d_towupper='define'
d_trunc='define'
d_truncate='define'
d_truncl='define'
d_vsnprintf='define'
d_wait4='define'
d_waitpid='define'
+d_wcrtomb='define'
d_wcscmp='define'
d_wcstombs='define'
d_wcsxfrm='define'
i_sysstat='define'
i_sysstatfs='define'
i_sysstatvfs='define'
+i_syssyscall='define'
i_systime='define'
i_systimek='undef'
i_systimes='define'
i_varhdr='stdarg.h'
i_vfork='undef'
i_wchar='define'
+i_wctype='define'
i_xlocale='undef'
ignore_versioned_solibs='y'
inc_version_list=' '
spitshell='cat'
src='.'
ssizetype='ssize_t'
+st_dev_sign='1'
+st_dev_size='8'
st_ino_sign='1'
st_ino_size='8'
startperl='#!/usr/bin/perl'
use5005threads='undef'
usecbacktrace='undef'
usecrosscompile='define'
+usedefaultstrict='undef'
usedevel='undef'
usedl='define'
usedtrace='undef'
vi=''
voidflags='15'
xlibpth='/usr/lib/386 /lib/386'
+xlocale_needed='undef'
yacc='yacc'
yaccflags=''
zcat=''
}
($owrt:libc eq 'musl') {
- # musl does not provide a working setlocale(). It accepts arbitrary locales
- # and makes them act as if they were C.UTF-8.
- d_setlocale='undef'
-
d_stdio_ptr_lval='undef'
d_stdio_ptr_lval_sets_cnt='undef'
d_stdiobase='undef'
# Set the version here
PERL_REVISION=5
-PERL_VERSION=28
-PERL_SUBVERSION=1
+PERL_VERSION=38
+PERL_SUBVERSION=0
# (api_revison, api_version, api_subversion) = (revision, version, 0) usually
PERL_API_REVISION=5
-PERL_API_VERSION=28
+PERL_API_VERSION=38
PERL_API_SUBVERSION=0
-known_extensions='B Compress/Raw/Zlib Cwd DB_File Data/Dumper Devel/DProf Devel/PPPort Devel/Peek Digest/MD5 Digest/SHA Encode Fcntl File/Glob Filter/Util/Call GDBM_File Hash/Util I18N/Langinfo IO IPC/SysV List/Util MIME/Base64 Math/BigInt/FastCalc NDBM_File ODBM_File Opcode POSIX PerlIO/encoding PerlIO/scalar PerlIO/via SDBM_File Socket Storable Sys/Hostname Sys/Syslog Text/Soundex Time/HiRes Time/Piece Unicode/Normalize Win32 Win32API/File Win32CORE XS/APItest XS/Typemap attrs re threads threads/shared Hash/Util/FieldHash'
-extensions='B Compress/Raw/Bzip2 Compress/Raw/Zlib Cwd DB_File Data/Dumper Devel/PPPort Devel/Peek Digest/MD5 Digest/SHA Encode Fcntl File/DosGlob File/Glob Filter/Util/Call GDBM_File Hash/Util Hash/Util/FieldHash I18N/Langinfo IO IPC/SysV List/Util MIME/Base64 Math/BigInt/FastCalc Opcode POSIX PerlIO/encoding PerlIO/mmap PerlIO/scalar PerlIO/via SDBM_File Socket Storable Sys/Hostname Sys/Syslog Tie/Hash/NamedCapture Time/HiRes Time/Piece Unicode/Collate XS/APItest XS/Typemap arybase attributes mro re threads threads/shared Archive/Tar Attribute/Handlers AutoLoader B/Debug CPAN CPAN/Meta CPAN/Meta/Requirements CPAN/Meta/YAML Carp Config/Perl/V Devel/SelfStubber Digest Dumpvalue Env Errno Exporter ExtUtils/CBuilder ExtUtils/Command ExtUtils/Constant ExtUtils/Install ExtUtils/MakeMaker ExtUtils/Manifest ExtUtils/Miniperl ExtUtils/ParseXS File/Fetch File/Find File/Path File/Temp FileCache Filter/Simple Getopt/Long HTTP/Tiny I18N/Collate I18N/LangTags IO/Compress IO/Socket/IP IO/Zlib IPC/Cmd IPC/Open3 JSON/PP Locale/Codes Locale/Maketext Locale/Maketext/Simple Math/BigInt Math/BigRat Math/Complex Memoize Module/CoreList Module/Load Module/Load/Conditional Module/Loaded Module/Metadata NEXT Net/Ping Params/Check Parse/CPAN/Meta Perl/OSType PerlIO/via/QuotedPrint Pod/Checker Pod/Escapes Pod/Functions Pod/Html Pod/Parser Pod/Perldoc Pod/Simple Pod/Usage Safe Search/Dict SelfLoader Term/ANSIColor Term/Cap Term/Complete Term/ReadLine Test Test/Harness Test/Simple Text/Abbrev Text/Balanced Text/ParseWords Text/Tabs Thread/Queue Thread/Semaphore Tie/File Tie/Memoize Tie/RefHash Time/Local XSLoader autodie autouse base bignum constant encoding/warnings experimental if lib libnet parent perlfaq podlators Unicode/Normalize version'
-nonxs_ext='Archive/Tar Attribute/Handlers AutoLoader B/Debug CPAN CPAN/Meta CPAN/Meta/Requirements CPAN/Meta/YAML Carp Config/Perl/V Devel/SelfStubber Digest Dumpvalue Env Errno Exporter ExtUtils/CBuilder ExtUtils/Command ExtUtils/Constant ExtUtils/Install ExtUtils/MakeMaker ExtUtils/Manifest ExtUtils/Miniperl ExtUtils/ParseXS File/Fetch File/Find File/Path File/Temp FileCache Filter/Simple Getopt/Long HTTP/Tiny I18N/Collate I18N/LangTags IO/Compress IO/Socket/IP IO/Zlib IPC/Cmd IPC/Open3 JSON/PP Locale/Codes Locale/Maketext Locale/Maketext/Simple Math/BigInt Math/BigRat Math/Complex Memoize Module/CoreList Module/Load Module/Load/Conditional Module/Loaded Module/Metadata NEXT Net/Ping Params/Check Parse/CPAN/Meta Perl/OSType PerlIO/via/QuotedPrint Pod/Checker Pod/Escapes Pod/Functions Pod/Html Pod/Parser Pod/Perldoc Pod/Simple Pod/Usage Safe Search/Dict SelfLoader Term/ANSIColor Term/Cap Term/Complete Term/ReadLine Test Test/Harness Test/Simple Text/Abbrev Text/Balanced Text/ParseWords Text/Tabs Thread/Queue Thread/Semaphore Tie/File Tie/Memoize Tie/RefHash Time/Local XSLoader autodie autouse base bignum constant encoding/warnings experimental if lib libnet parent perlfaq podlators Unicode/Normalize version'
-dynamic_ext='B Compress/Raw/Bzip2 Compress/Raw/Zlib Cwd DB_File Data/Dumper Devel/PPPort Devel/Peek Digest/MD5 Digest/SHA Encode Fcntl File/DosGlob File/Glob Filter/Util/Call GDBM_File Hash/Util Hash/Util/FieldHash I18N/Langinfo IO IPC/SysV List/Util MIME/Base64 Math/BigInt/FastCalc Opcode POSIX PerlIO/encoding PerlIO/mmap PerlIO/scalar PerlIO/via SDBM_File Socket Storable Sys/Hostname Sys/Syslog Tie/Hash/NamedCapture Time/HiRes Time/Piece Unicode/Collate XS/APItest XS/Typemap arybase attributes mro re threads threads/shared'
+dynamic_ext='attributes B Compress/Raw/Bzip2 Compress/Raw/Zlib Cwd Data/Dumper DB_File Devel/Peek Devel/PPPort Digest/MD5 Digest/SHA Encode Fcntl File/DosGlob File/Glob Filter/Util/Call GDBM_File Hash/Util Hash/Util/FieldHash I18N/Langinfo IO IPC/SysV List/Util Math/BigInt/FastCalc MIME/Base64 mro Opcode PerlIO/encoding PerlIO/mmap PerlIO/scalar PerlIO/via POSIX re SDBM_File Socket Storable Sys/Hostname Sys/Syslog threads threads/shared Time/HiRes Time/Piece Unicode/Collate Unicode/Normalize XS/APItest XS/Typemap'
+extensions='attributes B Compress/Raw/Bzip2 Compress/Raw/Zlib Cwd Data/Dumper DB_File Devel/Peek Devel/PPPort Digest/MD5 Digest/SHA Encode Fcntl File/DosGlob File/Glob Filter/Util/Call Hash/Util Hash/Util/FieldHash I18N/Langinfo IO IPC/SysV List/Util Math/BigInt/FastCalc MIME/Base64 mro Opcode PerlIO/encoding PerlIO/mmap PerlIO/scalar PerlIO/via POSIX re SDBM_File Socket Storable Sys/Hostname Sys/Syslog threads threads/shared Time/HiRes Time/Piece Unicode/Collate Unicode/Normalize XS/APItest XS/Typemap Archive/Tar Attribute/Handlers autodie AutoLoader autouse base bignum Carp Config/Perl/V constant CPAN CPAN/Meta CPAN/Meta/Requirements CPAN/Meta/YAML Devel/SelfStubber Digest Dumpvalue encoding/warnings Env Errno experimental Exporter ExtUtils/CBuilder ExtUtils/Constant ExtUtils/Install ExtUtils/MakeMaker ExtUtils/Manifest ExtUtils/Miniperl ExtUtils/ParseXS ExtUtils/PL2Bat FileCache File/Fetch File/Find File/Path File/Temp Filter/Simple FindBin GDBM_File Getopt/Long HTTP/Tiny I18N/Collate I18N/LangTags if IO/Compress IO/Socket/IP IO/Zlib IPC/Cmd IPC/Open3 JSON/PP lib libnet Locale/Maketext Locale/Maketext/Simple Math/BigInt Math/BigRat Math/Complex Memoize Module/CoreList Module/Load Module/Load/Conditional Module/Loaded Module/Metadata Net/Ping NEXT Params/Check parent perlfaq PerlIO/via/QuotedPrint Perl/OSType Pod/Checker Pod/Escapes Pod/Functions Pod/Html podlators Pod/Perldoc Pod/Simple Pod/Usage Safe Search/Dict SelfLoader Term/ANSIColor Term/Cap Term/Complete Term/ReadLine Test Test/Harness Test/Simple Text/Abbrev Text/Balanced Text/ParseWords Text/Tabs Thread/Queue Thread/Semaphore Tie/File Tie/Hash/NamedCapture Tie/Memoize Tie/RefHash Time/Local version XSLoader'
+known_extensions='Amiga/ARexx Amiga/Exec Archive/Tar Attribute/Handlers attributes autodie AutoLoader autouse B base bignum Carp Compress/Raw/Bzip2 Compress/Raw/Zlib Config/Perl/V constant CPAN CPAN/Meta CPAN/Meta/Requirements CPAN/Meta/YAML Cwd Data/Dumper DB_File Devel/Peek Devel/PPPort Devel/SelfStubber Digest Digest/MD5 Digest/SHA Dumpvalue Encode encoding/warnings Env Errno experimental Exporter ExtUtils/CBuilder ExtUtils/Constant ExtUtils/Install ExtUtils/MakeMaker ExtUtils/Manifest ExtUtils/Miniperl ExtUtils/ParseXS ExtUtils/PL2Bat Fcntl FileCache File/DosGlob File/Fetch File/Find File/Glob File/Path File/Temp Filter/Simple Filter/Util/Call FindBin GDBM_File Getopt/Long Hash/Util Hash/Util/FieldHash HTTP/Tiny I18N/Collate I18N/Langinfo I18N/LangTags if IO IO/Compress IO/Socket/IP IO/Zlib IPC/Cmd IPC/Open3 IPC/SysV JSON/PP lib libnet List/Util Locale/Maketext Locale/Maketext/Simple Math/BigInt Math/BigInt/FastCalc Math/BigRat Math/Complex Memoize MIME/Base64 Module/CoreList Module/Load Module/Load/Conditional Module/Loaded Module/Metadata mro NDBM_File Net/Ping NEXT ODBM_File Opcode Params/Check parent perlfaq PerlIO/encoding PerlIO/mmap PerlIO/scalar PerlIO/via PerlIO/via/QuotedPrint Perl/OSType Pod/Checker Pod/Escapes Pod/Functions Pod/Html podlators Pod/Perldoc Pod/Simple Pod/Usage POSIX re Safe SDBM_File Search/Dict SelfLoader Socket Storable Sys/Hostname Sys/Syslog Term/ANSIColor Term/Cap Term/Complete Term/ReadLine Test Test/Harness Test/Simple Text/Abbrev Text/Balanced Text/ParseWords Text/Tabs Thread/Queue threads Thread/Semaphore threads/shared Tie/File Tie/Hash/NamedCapture Tie/Memoize Tie/RefHash Time/HiRes Time/Local Time/Piece Unicode/Collate Unicode/Normalize version VMS/DCLsym VMS/Filespec VMS/Stdio Win32 Win32API/File Win32CORE XS/APItest XSLoader XS/Typemap'
+nonxs_ext='Archive/Tar Attribute/Handlers autodie AutoLoader autouse base bignum Carp Config/Perl/V constant CPAN CPAN/Meta CPAN/Meta/Requirements CPAN/Meta/YAML Devel/SelfStubber Digest Dumpvalue encoding/warnings Env Errno experimental Exporter ExtUtils/CBuilder ExtUtils/Constant ExtUtils/Install ExtUtils/MakeMaker ExtUtils/Manifest ExtUtils/Miniperl ExtUtils/ParseXS ExtUtils/PL2Bat FileCache File/Fetch File/Find File/Path File/Temp Filter/Simple FindBin Getopt/Long HTTP/Tiny I18N/Collate I18N/LangTags if IO/Compress IO/Socket/IP IO/Zlib IPC/Cmd IPC/Open3 JSON/PP lib libnet Locale/Maketext Locale/Maketext/Simple Math/BigInt Math/BigRat Math/Complex Memoize Module/CoreList Module/Load Module/Load/Conditional Module/Loaded Module/Metadata Net/Ping NEXT Params/Check parent perlfaq PerlIO/via/QuotedPrint Perl/OSType Pod/Checker Pod/Escapes Pod/Functions Pod/Html podlators Pod/Perldoc Pod/Simple Pod/Usage Safe Search/Dict SelfLoader Term/ANSIColor Term/Cap Term/Complete Term/ReadLine Test Test/Harness Test/Simple Text/Abbrev Text/Balanced Text/ParseWords Text/Tabs Thread/Queue Thread/Semaphore Tie/File Tie/Hash/NamedCapture Tie/Memoize Tie/RefHash Time/Local version XSLoader'
# No need to change anything from here on
owrt:perllibpath="/usr/lib/perl5/$PERL_REVISION.$PERL_VERSION"
+++ /dev/null
---- a/hints/darwin.sh
-+++ b/hints/darwin.sh
-@@ -301,7 +301,7 @@ case "$osvers" in # Note: osvers is the
- # We now use MACOSX_DEPLOYMENT_TARGET, if set, as an override by
- # capturing its value and adding it to the flags.
- case "$MACOSX_DEPLOYMENT_TARGET" in
-- 10.*)
-+ [1-9][0-9].*)
- add_macosx_version_min ccflags $MACOSX_DEPLOYMENT_TARGET
- add_macosx_version_min ldflags $MACOSX_DEPLOYMENT_TARGET
- ;;
-@@ -313,7 +313,7 @@ case "$osvers" in # Note: osvers is the
-
- *** Unexpected MACOSX_DEPLOYMENT_TARGET=$MACOSX_DEPLOYMENT_TARGET
- ***
--*** Please either set it to 10.something, or to empty.
-+*** Please either set it to a valid macOS version number (e.g., 10.15) or to empty.
-
- EOM
- exit 1
-@@ -327,7 +327,7 @@ EOM
- # "ProductVersion: 10.11" "10.11"
- prodvers=`sw_vers|awk '/^ProductVersion:/{print $2}'|awk -F. '{print $1"."$2}'`
- case "$prodvers" in
-- 10.*)
-+ [1-9][0-9].*)
- add_macosx_version_min ccflags $prodvers
- add_macosx_version_min ldflags $prodvers
- ;;
+++ /dev/null
-From 15f67d146cf1f32504e8a11de3faa2abc0f467cd Mon Sep 17 00:00:00 2001
-From: Tony Cook <tony@develop-help.com>
-Date: Mon, 25 Mar 2019 16:48:40 +1100
-Subject: [PATCH] (perl #133951) add Internals::getcwd
-
----
- MANIFEST | 1 +
- t/io/getcwd.t | 22 ++++++++++++++++++++++
- universal.c | 22 ++++++++++++++++++++++
- 3 files changed, 45 insertions(+)
- create mode 100644 t/io/getcwd.t
-
---- a/MANIFEST
-+++ b/MANIFEST
-@@ -5456,6 +5456,7 @@ t/io/errno.t See if $! is correctly se
- t/io/errnosig.t Test case for restoration $! when leaving signal handlers
- t/io/fflush.t See if auto-flush on fork/exec/system/qx works
- t/io/fs.t See if directory manipulations work
-+t/io/getcwd.t See if Internals::getcwd is sane
- t/io/inplace.t See if inplace editing works
- t/io/iofile.t See if we can load IO::File on demand
- t/io/iprefix.t See if inplace editing works with prefixes
---- /dev/null
-+++ b/t/io/getcwd.t
-@@ -0,0 +1,22 @@
-+#!./perl -w
-+
-+BEGIN {
-+ chdir 't' if -d 't';
-+ require "./test.pl";
-+ set_up_inc('../lib');
-+}
-+
-+use Config;
-+
-+$Config{d_getcwd}
-+ or plan skip_all => "no getcwd";
-+
-+my $cwd = Internals::getcwd();
-+ok(!defined $cwd || $cwd ne "",
-+ "Internals::getcwd() returned a reasonable result");
-+
-+if (defined $cwd) {
-+ ok(-d $cwd, "check a success result is a directory");
-+}
-+
-+done_testing();
---- a/universal.c
-+++ b/universal.c
-@@ -986,6 +986,25 @@ XS(XS_re_regexp_pattern)
- NOT_REACHED; /* NOTREACHED */
- }
-
-+#ifdef HAS_GETCWD
-+
-+XS(XS_Internals_getcwd)
-+{
-+ dXSARGS;
-+ SV *sv = sv_newmortal();
-+
-+ if (items != 0)
-+ croak_xs_usage(cv, "");
-+
-+ (void)getcwd_sv(sv);
-+
-+ SvTAINTED_on(sv);
-+ PUSHs(sv);
-+ XSRETURN(1);
-+}
-+
-+#endif
-+
- #include "vutil.h"
- #include "vxs.inc"
-
-@@ -1020,6 +1039,9 @@ static const struct xsub_details details
- {"re::regnames", XS_re_regnames, ";$"},
- {"re::regnames_count", XS_re_regnames_count, ""},
- {"re::regexp_pattern", XS_re_regexp_pattern, "$"},
-+#ifdef HAS_GETCWD
-+ {"Internals::getcwd", XS_Internals_getcwd, ""},
-+#endif
- };
-
- STATIC OP*
+++ /dev/null
---- a/dist/PathTools/Cwd.pm
-+++ b/dist/PathTools/Cwd.pm
-@@ -659,6 +659,10 @@ if (exists $METHOD_MAP{$^O}) {
- }
- }
-
-+# built-in from 5.30
-+*getcwd = \&Internals::getcwd
-+ if !defined &getcwd && defined &Internals::getcwd;
-+
- # In case the XS version doesn't load.
- *abs_path = \&_perl_abs_path unless defined &abs_path;
- *getcwd = \&_perl_getcwd unless defined &getcwd;
---- a/dist/PathTools/t/cwd.t
-+++ b/dist/PathTools/t/cwd.t
-@@ -10,6 +10,7 @@ chdir 't';
- use Config;
- use File::Spec;
- use File::Path;
-+use Errno qw(EACCES);
-
- use lib File::Spec->catdir('t', 'lib');
- use Test::More;
-@@ -208,7 +209,15 @@ SKIP: {
-
- like($abs_path, qr|$want$|i, "Cwd::abs_path produced $abs_path");
- like($fast_abs_path, qr|$want$|i, "Cwd::fast_abs_path produced $fast_abs_path");
-- like($pas, qr|$want$|i, "Cwd::_perl_abs_path produced $pas") if $EXTRA_ABSPATH_TESTS;
-+ if ($EXTRA_ABSPATH_TESTS) {
-+ # _perl_abs_path() can fail if some ancestor directory isn't readable
-+ if (defined $pas) {
-+ like($pas, qr|$want$|i, "Cwd::_perl_abs_path produced $pas");
-+ }
-+ else {
-+ is($!+0, EACCES, "check we got the expected error on failure");
-+ }
-+ }
-
- rmtree($test_dirs[0], 0, 0);
- 1 while unlink $file;
--- a/perl.c
+++ b/perl.c
-@@ -303,7 +303,7 @@ perl_construct(pTHXx)
+@@ -317,7 +317,7 @@ perl_construct(pTHXx)
PL_localpatches = local_patches; /* For possible -v */
#endif
+++ /dev/null
-From 682a4acb98783a7f9b5c286b308f12863599fec3 Mon Sep 17 00:00:00 2001
-From: Tony Cook <tony@develop-help.com>
-Date: Mon, 30 Jul 2018 21:00:52 +1000
-Subject: (perl #133411) don't try to load Storable with -Dusecrosscompile
-
----
- dist/Storable/Makefile.PL | 9 ++++++++-
- dist/Storable/stacksize | 10 +++++++---
- 2 files changed, 15 insertions(+), 4 deletions(-)
-
---- a/dist/Storable/Makefile.PL
-+++ b/dist/Storable/Makefile.PL
-@@ -90,12 +90,19 @@ sub depend {
- # blib.pm needs arch/lib
- $extra_deps = ' Storable.pm';
- }
-+ my $whichperl;
-+ if ($Config::Config{usecrosscompile}) {
-+ $whichperl = '$(PERLRUN)';
-+ }
-+ else {
-+ $whichperl = '$(FULLPERLRUNINST)';
-+ }
- my $linktype = uc($_[0]->{LINKTYPE});
- my $limit_pm = File::Spec->catfile('lib', 'Storable', 'Limit.pm');
- "
- $limit_pm : stacksize \$(INST_$linktype)$extra_deps
- \$(MKPATH) \$(INST_LIB)
-- \$(FULLPERLRUNINST) stacksize $options
-+ $whichperl stacksize $options
-
- release : dist
- git tag \$(VERSION)
---- a/dist/Storable/stacksize
-+++ b/dist/Storable/stacksize
-@@ -7,6 +7,9 @@ use Cwd;
- use File::Spec;
- use strict;
-
-+-d "lib" or mkdir "lib";
-+-d "lib/Storable" or mkdir "lib/Storable";
-+
- my $fn = "lib/Storable/Limit.pm";
- my $ptrsize = $Config{ptrsize};
- my ($bad1, $bad2) = (65001, 25000);
-@@ -29,6 +32,10 @@ sub is_miniperl {
- }
-
- if (is_miniperl()) {
-+ if ($Config{usecrosscompile}) {
-+ write_limits(500, 265);
-+ exit;
-+ }
- die "Should not run during miniperl\n";
- }
- my $prefix = "";
-@@ -68,9 +75,6 @@ if ($ENV{PERL_CORE}) {
- }
- }
-
---d "lib" or mkdir "lib";
---d "lib/Storable" or mkdir "lib/Storable";
--
- if ($^O eq "MSWin32") {
- require Win32;
- my ($str, $major, $minor) = Win32::GetOSVersion();
--- a/Makefile.SH
+++ b/Makefile.SH
-@@ -339,22 +339,11 @@ MANIFEST_SRT = MANIFEST.srt
-
- !GROK!THIS!
+@@ -360,22 +360,11 @@ PERL_EXE_LDFLAGS=$exeldflags
+ ;;
+ esac
-case "$usecrosscompile$perl" in
-define?*)
--- a/perl.c
+++ b/perl.c
-@@ -1987,16 +1987,6 @@ S_Internals_V(pTHX_ CV *cv)
+@@ -2098,16 +2098,6 @@ S_Internals_V(pTHX_ CV *cv)
PUSHs(Perl_newSVpvn_flags(aTHX_ non_bincompat_options,
- sizeof(non_bincompat_options) - 1, SVs_TEMP));
+ sizeof(non_bincompat_options) - 1, SVs_TEMP));
-#ifndef PERL_BUILD_DATE
-# ifdef __DATE__
-
#ifdef PERL_BUILD_DATE
PUSHs(Perl_newSVpvn_flags(aTHX_
- STR_WITH_LEN("Compiled at " PERL_BUILD_DATE),
+ STR_WITH_LEN("Compiled at " PERL_BUILD_DATE),
+++ /dev/null
---- a/cpan/ExtUtils-MakeMaker/lib/ExtUtils/MM_Unix.pm
-+++ b/cpan/ExtUtils-MakeMaker/lib/ExtUtils/MM_Unix.pm
-@@ -2738,14 +2738,14 @@ sub _find_static_libs {
-
- Called by a utility method of makeaperl. Checks whether a given file
- is an XS library by seeing whether it defines any symbols starting
--with C<boot_>.
-+with C<boot_> (with an optional leading underscore – needed on MacOS).
-
- =cut
-
- sub xs_static_lib_is_xs {
- my ($self, $libfile) = @_;
- my $devnull = File::Spec->devnull;
-- return `nm $libfile 2>$devnull` =~ /\bboot_/;
-+ return `nm $libfile 2>$devnull` =~ /\b_?boot_/;
- }
-
- =item makefile (o)
--- a/cpan/podlators/Makefile.PL
+++ b/cpan/podlators/Makefile.PL
-@@ -18,6 +18,19 @@ use Config;
- use ExtUtils::MakeMaker;
- use File::Spec;
+@@ -39,6 +39,19 @@ sub dist_version {
+ die "$0: cannot find version in lib/Pod/Man.pm\n";
+ }
+foreach (glob('scripts/pod*.PL')) {
+ # The various pod*.PL extractors change directory. Doing that with relative
# Generate full paths for scripts distributed in the bin directory. Appends
# the .com extension to scripts on VMS, unless they already have the .PL
# extension.
-@@ -28,7 +41,7 @@ use File::Spec;
+@@ -49,7 +62,7 @@ sub dist_version {
# (Scalar) Space-separated relative paths from top of distribution
sub scripts {
my (@scripts) = @_;
if ($^O eq 'VMS') {
@paths = map { m{ [.] PL \z }xms ? $_ : $_ . '.com' } @paths;
}
-@@ -77,8 +90,8 @@ my %metadata = (
+@@ -101,8 +114,8 @@ my %metadata = (
# Override the files that generate section 1 man pages.
MAN1PODS => {
--- a/Makefile.SH
+++ b/Makefile.SH
-@@ -275,6 +275,7 @@ LNS = $lns
+@@ -289,6 +289,7 @@ LNS = $lns
# NOTE: some systems don't grok "cp -f". XXX Configure test needed?
CPS = $cp
RMS = rm -f
+RMS_R = rm -rf
ranlib = $ranlib
+ ECHO = $echo
- # The following are mentioned only to make metaconfig include the
-@@ -736,7 +737,7 @@ bitcount.h: generate_uudmap$(HOST_EXE_EX
+@@ -786,7 +787,7 @@ bitcount.h: generate_uudmap$(HOST_EXE_EX
./generate_uudmap$(HOST_EXE_EXT) $(generated_headers)
generate_uudmap$(HOST_EXE_EXT): generate_uudmap$(OBJ_EXT)
$(LNS) $(HOST_GENERATE) generate_uudmap$(HOST_EXE_EXT)
!NO!SUBS!
-@@ -876,26 +877,26 @@ mydtrace.h: $(DTRACE_H)
+@@ -891,26 +892,26 @@ mydtrace.h: $(DTRACE_H)
define)
$spitshell >>$Makefile <<'!NO!SUBS!'
$(DTRACE_MINI_O): perldtrace.d $(miniperl_objs_nodt)
!NO!SUBS!
;;
-@@ -906,13 +907,13 @@ $(LIBPERL): $& $(perllib_dep) $(DYNALOAD
+@@ -921,13 +922,13 @@ $(LIBPERL): $& $(perllib_dep) $(DYNALOAD
case "$useshrplib" in
true)
$spitshell >>$Makefile <<'!NO!SUBS!'
mv $@ libperl$(OBJ_EXT)
$(AR) qv $(LIBPERL) libperl$(OBJ_EXT)
!NO!SUBS!
-@@ -921,7 +922,7 @@ $(LIBPERL): $& $(perllib_dep) $(DYNALOAD
+@@ -936,7 +937,7 @@ $(LIBPERL): $& $(perllib_dep) $(DYNALOAD
;;
*)
$spitshell >>$Makefile <<'!NO!SUBS!'
$(AR) rc $(LIBPERL) $(perllib_objs) $(DYNALOADER)
@$(ranlib) $(LIBPERL)
!NO!SUBS!
-@@ -954,7 +955,7 @@ $(MINIPERL_EXE): lib/buildcustomize.pl
+@@ -970,7 +971,7 @@ $(MINIPERL_EXE): lib/buildcustomize.pl
amigaos*)
$spitshell >>$Makefile <<'!NO!SUBS!'
lib/buildcustomize.pl: $& $(miniperl_objs) write_buildcustomize.pl
+ @$(RMS) miniperl.xok
!NO!SUBS!
- case $osname in
-@@ -1119,8 +1120,8 @@ pod/perl5281delta.pod: pod/perldelta.pod
- $(LNS) perldelta.pod pod/perl5281delta.pod
+ case "$osname" in
+@@ -1133,8 +1134,8 @@ pod/perl5380delta.pod: pod/perldelta.pod
+ $(LNS) perldelta.pod pod/perl5380delta.pod
extra.pods: $(MINIPERL_EXE)
- -@test ! -f extra.pods || rm -f `cat extra.pods`
-@for x in `grep -l '^=[a-z]' README.* | grep -v README.vms` ; do \
nx=`echo $$x | sed -e "s/README\.//"`; \
$(LNS) ../$$x "pod/perl"$$nx".pod" ; \
-@@ -1340,11 +1341,11 @@ realclean: _realcleaner _mopup
+@@ -1334,11 +1335,11 @@ realclean: _realcleaner _mopup
@echo "Note that '$(MAKE) realclean' does not delete config.sh or Policy.sh"
_clobber:
clobber: _realcleaner _mopup _clobber
-@@ -1352,23 +1353,23 @@ distclean: clobber
+@@ -1346,24 +1347,24 @@ distclean: clobber
# Like distclean but also removes emacs backups and *.orig.
veryclean: _verycleaner _mopup _clobber
# Do not 'make _mopup' directly.
_mopup:
-- rm -f *$(OBJ_EXT) *$(LIB_EXT) all perlmain.c opmini.c perlmini.c generate_uudmap$(EXE_EXT) $(generated_headers)
-+ $(RMS) *$(OBJ_EXT) *$(LIB_EXT) all perlmain.c opmini.c perlmini.c generate_uudmap$(EXE_EXT) $(generated_headers)
+- rm -f *$(OBJ_EXT) *$(LIB_EXT) all perlmain.c $(mini_only_src) generate_uudmap$(EXE_EXT) $(generated_headers)
++ $(RMS) *$(OBJ_EXT) *$(LIB_EXT) all perlmain.c $(mini_only_src) generate_uudmap$(EXE_EXT) $(generated_headers)
-rmdir .depending
+- -rm *.depends makedepend_file
- -@test -f extra.pods && rm -f `cat extra.pods`
- -@test -f vms/README_vms.pod && rm -f vms/README_vms.pod
-- -rm -f perl.exp ext.libs $(generated_pods) uni.data opmini.o perlmini.o pod/roffitall
+- -rm -f perl.exp ext.libs $(generated_pods) uni.data $(mini_only_objs) pod/roffitall
- -rm -f perl.export perl.dll perl.libexp perl.map perl.def
- -rm -f *perl.xok
- -rm -f cygwin.c libperl*.def libperl*.dll cygperl*.dll *.exe.stackdump
- -rm -f $(PERL_EXE) $(MINIPERL_EXE) $(LIBPERL) libperl.* microperl
- -rm -f config.arch config.over $(DTRACE_H)
++ $(RMS) *.depends makedepend_file
+ -@test -f extra.pods && $(RMS) `cat extra.pods`
+ -@test -f vms/README_vms.pod && $(RMS) vms/README_vms.pod
-+ $(RMS) perl.exp ext.libs $(generated_pods) uni.data opmini.o perlmini.o pod/roffitall
++ $(RMS) perl.exp ext.libs $(generated_pods) uni.data $(mini_only_objs) pod/roffitall
+ $(RMS) perl.export perl.dll perl.libexp perl.map perl.def
+ $(RMS) *perl.xok
+ $(RMS) cygwin.c libperl*.def libperl*.dll cygperl*.dll *.exe.stackdump
-cd pod; $(LDLIBPTH) $(MAKE) $(CLEAN)
-cd utils; $(LDLIBPTH) $(MAKE) $(CLEAN)
-@if test -f $(MINIPERL_EXE) ; then \
-@@ -1378,31 +1379,31 @@ _cleaner1:
+@@ -1373,8 +1374,8 @@ _cleaner1:
else \
sh $(CLEAN).sh ; \
fi
+ $(RMS) `grep -v ^# mkppport.lst | grep . | sed -e 's/$$/\/ppport.h/'`
# Dear POSIX, thanks for making the default to xargs to be
- # run once if nothhing is passed in. It is such a great help.
-
- # Some systems do not support "?", so keep these files separate.
+ # run once if nothing is passed in. It is such a great help.
+@@ -1389,24 +1390,24 @@ _cleaner1:
+ # Add new rules before that line - the next line (rm -f so_locations ...) is
+ # used as a placeholder by a regen script.
_cleaner2:
- -rm -f core.*perl.*.? t/core.perl.*.? .?*.c
- rm -f core *perl.core t/core t/*perl.core core.* t/core.*
+ $(RMS) pod2htmd.tmp
+ $(RMS_R) pod/perlfunc pod/perlipc
-rmdir ext/B/lib
-- rm -f so_locations $(LIBPERL_NONSHR) $(MINIPERL_NONSHR)
-+ $(RMS) so_locations $(LIBPERL_NONSHR) $(MINIPERL_NONSHR)
+- -rm -f dist/Time-HiRes/xdefine
+- rm -f so_locations $(LIBPERL_NONSHR)
++ $(RMS) dist/Time-HiRes/xdefine
++ $(RMS) so_locations $(LIBPERL_NONSHR)
-rmdir lib/version lib/threads lib/inc/ExtUtils lib/inc lib/encoding
-rmdir lib/autodie/exception lib/autodie/Scope lib/autodie lib/XS
-rmdir lib/Win32API lib/VMS lib/Unicode/Collate/Locale
-@@ -1452,11 +1453,11 @@ _realcleaner:
+@@ -1457,11 +1458,11 @@ _realcleaner:
_verycleaner:
@$(LDLIBPTH) $(MAKE) _cleaner1 CLEAN=veryclean
@$(LDLIBPTH) $(MAKE) _cleaner2
lint $(lintflags) -DPERL_CORE -D_REENTRANT -DDEBUGGING -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 $(c)
cscopeflags = -Rb # Recursive, build-only.
-@@ -1514,7 +1515,7 @@ case "$targethost" in
+@@ -1522,7 +1523,7 @@ case "$targethost" in
'') $spitshell >>$Makefile <<'!NO!SUBS!'
test_prep test-prep: test_prep_pre $(MINIPERL_EXE) $(unidatafiles) $(PERL_EXE) \
$(dynamic_ext) $(TEST_PERL_DLL) runtests $(generated_pods) common_build
!NO!SUBS!
;;
-@@ -1564,7 +1565,7 @@ test_prep test-prep: test_prep_pre \$(MI
+@@ -1572,7 +1573,7 @@ test_prep test-prep: test_prep_pre \$(MI
$to config.sh
# --- For lib/diagnostics.t with -Duseshrplib
$to \$(PERL_EXE)
$to t/\$(PERL_EXE)
!GROK!THIS!
-@@ -1574,7 +1575,7 @@ esac
+@@ -1582,7 +1583,7 @@ esac
$spitshell >>$Makefile <<'!NO!SUBS!'
test_prep_reonly: $(MINIPERL_EXE) $(PERL_EXE) $(dynamic_ext_re) $(TEST_PERL_DLL)
$(MINIPERL) make_ext.pl $(dynamic_ext_re) MAKE="$(MAKE)" LIBPERL_A=$(LIBPERL) LINKTYPE=dynamic
!NO!SUBS!
case "$targethost" in
-@@ -1629,7 +1630,7 @@ minitest_prep:
+@@ -1637,7 +1638,7 @@ minitest_prep: $(MINIPERL_EXE)
@echo "You may see some irrelevant test failures if you have been unable"
@echo "to build lib/Config.pm, or the Unicode data files."
@echo " "
-- - cd t && (rm -f $(PERL_EXE); $(LNS) ../$(MINIPERL_EXE) $(PERL_EXE))
-+ - cd t && ($(RMS) $(PERL_EXE); $(LNS) ../$(MINIPERL_EXE) $(PERL_EXE))
+- cd t && (rm -f $(PERL_EXE); $(LNS) ../$(MINIPERL_EXE) $(PERL_EXE))
++ cd t && ($(RMS) $(PERL_EXE); $(LNS) ../$(MINIPERL_EXE) $(PERL_EXE))
MINITEST_TESTS = base/*.t comp/*.t cmd/*.t run/*.t io/*.t re/*.t opbasic/*.t op/*.t uni/*.t perf/*.t
--- a/Makefile.SH
+++ b/Makefile.SH
-@@ -333,7 +333,7 @@ PATH_SEP = $p_
+@@ -346,7 +346,7 @@ OBJ_EXT = $_o
# Macros to invoke a copy of miniperl during the build. Targets which
# are built using these macros should depend on \$(MINIPERL_EXE)
MINIPERL_EXE = miniperl\$(EXE_EXT)
+++ /dev/null
-commit d36adde059ed1c4f7af210b4f9fc3a7bd2d7d343
-Author: Karl Williamson <khw@cpan.org>
-Date: Wed May 23 15:32:47 2018 -0600
-
- Fix to compile under -DNO_LOCALE
-
- Several problems with this compile option were not caught before 5.28
- was frozen.
-
---- a/embed.fnc
-+++ b/embed.fnc
-@@ -2793,9 +2793,11 @@ s |bool |isa_lookup |NN HV *stash|NN con
- #endif
-
- #if defined(PERL_IN_LOCALE_C)
-+# ifdef USE_LOCALE
- sn |const char*|category_name |const int category
- s |const char*|switch_category_locale_to_template|const int switch_category|const int template_category|NULLOK const char * template_locale
- s |void |restore_switched_locale|const int category|NULLOK const char * const original_locale
-+# endif
- # ifdef HAS_NL_LANGINFO
- sn |const char*|my_nl_langinfo|const nl_item item|bool toggle
- # else
---- a/embed.h
-+++ b/embed.h
-@@ -1796,16 +1796,16 @@
- #define unshare_hek_or_pvn(a,b,c,d) S_unshare_hek_or_pvn(aTHX_ a,b,c,d)
- # endif
- # if defined(PERL_IN_LOCALE_C)
--#define category_name S_category_name
--#define restore_switched_locale(a,b) S_restore_switched_locale(aTHX_ a,b)
- #define save_to_buffer S_save_to_buffer
--#define switch_category_locale_to_template(a,b,c) S_switch_category_locale_to_template(aTHX_ a,b,c)
- # if defined(USE_LOCALE)
-+#define category_name S_category_name
- #define new_collate(a) S_new_collate(aTHX_ a)
- #define new_ctype(a) S_new_ctype(aTHX_ a)
- #define new_numeric(a) S_new_numeric(aTHX_ a)
-+#define restore_switched_locale(a,b) S_restore_switched_locale(aTHX_ a,b)
- #define set_numeric_radix(a) S_set_numeric_radix(aTHX_ a)
- #define stdize_locale(a) S_stdize_locale(aTHX_ a)
-+#define switch_category_locale_to_template(a,b,c) S_switch_category_locale_to_template(aTHX_ a,b,c)
- # if defined(USE_POSIX_2008_LOCALE)
- #define emulate_setlocale S_emulate_setlocale
- # endif
---- a/locale.c
-+++ b/locale.c
-@@ -1264,6 +1264,7 @@ S_locking_setlocale(pTHX_
- }
-
- #endif
-+#ifdef USE_LOCALE
-
- STATIC void
- S_set_numeric_radix(pTHX_ const bool use_locale)
-@@ -1299,6 +1300,10 @@ S_set_numeric_radix(pTHX_ const bool use
- }
-
- # endif
-+#else
-+
-+ PERL_UNUSED_ARG(use_locale);
-+
- #endif /* USE_LOCALE_NUMERIC and can find the radix char */
-
- }
-@@ -1481,7 +1486,6 @@ S_new_ctype(pTHX_ const char *newctype)
-
- #ifndef USE_LOCALE_CTYPE
-
-- PERL_ARGS_ASSERT_NEW_CTYPE;
- PERL_UNUSED_ARG(newctype);
- PERL_UNUSED_CONTEXT;
-
-@@ -1994,6 +1998,8 @@ S_new_collate(pTHX_ const char *newcoll)
-
- }
-
-+#endif
-+
- #ifdef WIN32
-
- STATIC char *
-@@ -2139,11 +2145,20 @@ Perl_setlocale(const int category, const
- {
- /* This wraps POSIX::setlocale() */
-
-+#ifdef NO_LOCALE
-+
-+ PERL_UNUSED_ARG(category);
-+ PERL_UNUSED_ARG(locale);
-+
-+ return "C";
-+
-+#else
-+
- const char * retval;
- const char * newlocale;
- dSAVEDERRNO;
-- DECLARATION_FOR_LC_NUMERIC_MANIPULATION;
- dTHX;
-+ DECLARATION_FOR_LC_NUMERIC_MANIPULATION;
-
- #ifdef USE_LOCALE_NUMERIC
-
-@@ -2262,6 +2277,8 @@ Perl_setlocale(const int category, const
-
- return retval;
-
-+#endif
-+
- }
-
- PERL_STATIC_INLINE const char *
-@@ -2414,13 +2431,16 @@ S_my_nl_langinfo(const int item, bool to
- dTHX;
- const char * retval;
-
-+#ifdef USE_LOCALE_NUMERIC
-+
- /* We only need to toggle into the underlying LC_NUMERIC locale for these
- * two items, and only if not already there */
- if (toggle && (( item != RADIXCHAR && item != THOUSEP)
- || PL_numeric_underlying))
-- {
-+
-+#endif /* No toggling needed if not using LC_NUMERIC */
-+
- toggle = FALSE;
-- }
-
- #if defined(HAS_NL_LANGINFO) /* nl_langinfo() is available. */
- # if ! defined(HAS_THREAD_SAFE_NL_LANGINFO_L) \
-@@ -2468,6 +2488,8 @@ S_my_nl_langinfo(const int item, bool to
- do_free = TRUE;
- }
-
-+# ifdef USE_LOCALE_NUMERIC
-+
- if (toggle) {
- if (PL_underlying_numeric_obj) {
- cur = PL_underlying_numeric_obj;
-@@ -2478,6 +2500,8 @@ S_my_nl_langinfo(const int item, bool to
- }
- }
-
-+# endif
-+
- /* We have to save it to a buffer, because the freelocale() just below
- * can invalidate the internal one */
- retval = save_to_buffer(nl_langinfo_l(item, cur),
-@@ -5169,9 +5193,7 @@ Perl_my_strerror(pTHX_ const int errnum)
- LOCALE_UNLOCK;
-
- # endif /* End of doesn't have strerror_l */
--#endif /* End of does have locale messages */
--
--#ifdef DEBUGGING
-+# ifdef DEBUGGING
-
- if (DEBUG_Lv_TEST) {
- PerlIO_printf(Perl_debug_log, "Strerror returned; saving a copy: '");
-@@ -5179,7 +5201,8 @@ Perl_my_strerror(pTHX_ const int errnum)
- PerlIO_printf(Perl_debug_log, "'\n");
- }
-
--#endif
-+# endif
-+#endif /* End of does have locale messages */
-
- SAVEFREEPV(errstr);
- return errstr;
-@@ -5301,10 +5324,17 @@ L<C<Perl_switch_to_global_locale>|perlap
- bool
- Perl_sync_locale()
- {
-+
-+#ifndef USE_LOCALE
-+
-+ return TRUE;
-+
-+#else
-+
- const char * newlocale;
- dTHX;
-
--#ifdef USE_POSIX_2008_LOCALE
-+# ifdef USE_POSIX_2008_LOCALE
-
- bool was_in_global_locale = FALSE;
- locale_t cur_obj = uselocale((locale_t) 0);
-@@ -5316,11 +5346,11 @@ Perl_sync_locale()
- * will affect the */
- if (cur_obj == LC_GLOBAL_LOCALE) {
-
--# ifdef HAS_QUERY_LOCALE
-+# ifdef HAS_QUERY_LOCALE
-
- do_setlocale_c(LC_ALL, setlocale(LC_ALL, NULL));
-
--# else
-+# else
-
- unsigned int i;
-
-@@ -5330,17 +5360,17 @@ Perl_sync_locale()
- do_setlocale_r(categories[i], setlocale(categories[i], NULL));
- }
-
--# endif
-+# endif
-
- was_in_global_locale = TRUE;
- }
-
--#else
-+# else
-
- bool was_in_global_locale = TRUE;
-
--#endif
--#ifdef USE_LOCALE_CTYPE
-+# endif
-+# ifdef USE_LOCALE_CTYPE
-
- newlocale = savepv(do_setlocale_c(LC_CTYPE, NULL));
- DEBUG_Lv(PerlIO_printf(Perl_debug_log,
-@@ -5349,8 +5379,8 @@ Perl_sync_locale()
- new_ctype(newlocale);
- Safefree(newlocale);
-
--#endif /* USE_LOCALE_CTYPE */
--#ifdef USE_LOCALE_COLLATE
-+# endif /* USE_LOCALE_CTYPE */
-+# ifdef USE_LOCALE_COLLATE
-
- newlocale = savepv(do_setlocale_c(LC_COLLATE, NULL));
- DEBUG_Lv(PerlIO_printf(Perl_debug_log,
-@@ -5359,8 +5389,8 @@ Perl_sync_locale()
- new_collate(newlocale);
- Safefree(newlocale);
-
--#endif
--#ifdef USE_LOCALE_NUMERIC
-+# endif
-+# ifdef USE_LOCALE_NUMERIC
-
- newlocale = savepv(do_setlocale_c(LC_NUMERIC, NULL));
- DEBUG_Lv(PerlIO_printf(Perl_debug_log,
-@@ -5369,9 +5399,12 @@ Perl_sync_locale()
- new_numeric(newlocale);
- Safefree(newlocale);
-
--#endif /* USE_LOCALE_NUMERIC */
-+# endif /* USE_LOCALE_NUMERIC */
-
- return was_in_global_locale;
-+
-+#endif
-+
- }
-
- #if defined(DEBUGGING) && defined(USE_LOCALE)
---- a/makedef.pl
-+++ b/makedef.pl
-@@ -574,6 +574,9 @@ unless ($define{USE_LOCALE_COLLATE}) {
- PL_collxfrm_mult
- Perl_sv_collxfrm
- Perl_sv_collxfrm_flags
-+ PL_strxfrm_NUL_replacement
-+ PL_strxfrm_is_behaved
-+ PL_strxfrm_max_cp
- );
- }
-
-@@ -583,6 +586,9 @@ unless ($define{USE_LOCALE_NUMERIC}) {
- PL_numeric_name
- PL_numeric_radix_sv
- PL_numeric_standard
-+ PL_numeric_underlying
-+ PL_numeric_underlying_is_standard
-+ PL_underlying_numeric_obj
- );
- }
-
---- a/perl.h
-+++ b/perl.h
-@@ -5656,6 +5656,9 @@ typedef struct am_table_short AMTS;
- # define IN_LC_COMPILETIME(category) 0
- # define IN_LC_RUNTIME(category) 0
- # define IN_LC(category) 0
-+# define _CHECK_AND_WARN_PROBLEMATIC_LOCALE
-+# define _CHECK_AND_OUTPUT_WIDE_LOCALE_UTF8_MSG(s, send)
-+# define _CHECK_AND_OUTPUT_WIDE_LOCALE_CP_MSG(c)
- #endif
-
-
---- a/proto.h
-+++ b/proto.h
-@@ -4886,8 +4886,6 @@ PERL_CALLCONV SV* Perl_hfree_next_entry(
- assert(hv); assert(indexp)
- #endif
- #if defined(PERL_IN_LOCALE_C)
--STATIC const char* S_category_name(const int category);
--STATIC void S_restore_switched_locale(pTHX_ const int category, const char * const original_locale);
- #ifndef PERL_NO_INLINE_FUNCTIONS
- PERL_STATIC_INLINE const char * S_save_to_buffer(const char * string, char **buf, Size_t *buf_size, const Size_t offset)
- __attribute__warn_unused_result__;
-@@ -4895,17 +4893,19 @@ PERL_STATIC_INLINE const char * S_save_t
- assert(buf_size)
- #endif
-
--STATIC const char* S_switch_category_locale_to_template(pTHX_ const int switch_category, const int template_category, const char * template_locale);
- # if defined(USE_LOCALE)
-+STATIC const char* S_category_name(const int category);
- STATIC void S_new_collate(pTHX_ const char* newcoll);
- STATIC void S_new_ctype(pTHX_ const char* newctype);
- #define PERL_ARGS_ASSERT_NEW_CTYPE \
- assert(newctype)
- STATIC void S_new_numeric(pTHX_ const char* newnum);
-+STATIC void S_restore_switched_locale(pTHX_ const int category, const char * const original_locale);
- STATIC void S_set_numeric_radix(pTHX_ const bool use_locale);
- STATIC char* S_stdize_locale(pTHX_ char* locs);
- #define PERL_ARGS_ASSERT_STDIZE_LOCALE \
- assert(locs)
-+STATIC const char* S_switch_category_locale_to_template(pTHX_ const int switch_category, const int template_category, const char * template_locale);
- # if defined(USE_POSIX_2008_LOCALE)
- STATIC const char* S_emulate_setlocale(const int category, const char* locale, unsigned int index, const bool is_index_valid);
- # endif
---- a/sv.c
-+++ b/sv.c
-@@ -13330,10 +13330,15 @@ Perl_sv_vcatpvfn_flags(pTHX_ SV *const s
-
- SvTAINT(sv);
-
-+#ifdef USE_LOCALE_NUMERIC
-+
- if (lc_numeric_set) {
- RESTORE_LC_NUMERIC(); /* Done outside loop, so don't have to
- save/restore each iteration. */
- }
-+
-+#endif
-+
- }
-
- /* =========================================================================
---- a/t/lib/warnings/regexec
-+++ b/t/lib/warnings/regexec
-@@ -215,6 +215,10 @@ Use of \b{} or \B{} for non-UTF-8 locale
- Use of \b{} or \B{} for non-UTF-8 locale is wrong. Assuming a UTF-8 locale at - line 17.
- ########
- # NAME (?[ ]) in non-UTF-8 locale
-+require '../loc_tools.pl';
-+unless (locales_enabled()) {
-+ print("SKIPPED\n# locales not available\n"),exit;
-+}
- eval { require POSIX; POSIX->import("locale_h") };
- if ($@) {
- print("SKIPPED\n# no POSIX\n"),exit;
-@@ -229,14 +233,14 @@ setlocale(&POSIX::LC_CTYPE, "C");
- ":" =~ /(?[ \: ])/;
- no warnings 'locale';
- EXPECT
--Use of (?[ ]) for non-UTF-8 locale is wrong. Assuming a UTF-8 locale at - line 9.
--Use of (?[ ]) for non-UTF-8 locale is wrong. Assuming a UTF-8 locale at - line 9.
--Use of (?[ ]) for non-UTF-8 locale is wrong. Assuming a UTF-8 locale at - line 10.
--Use of (?[ ]) for non-UTF-8 locale is wrong. Assuming a UTF-8 locale at - line 10.
--Use of (?[ ]) for non-UTF-8 locale is wrong. Assuming a UTF-8 locale at - line 11.
--Use of (?[ ]) for non-UTF-8 locale is wrong. Assuming a UTF-8 locale at - line 11.
--Use of (?[ ]) for non-UTF-8 locale is wrong. Assuming a UTF-8 locale at - line 12.
--Use of (?[ ]) for non-UTF-8 locale is wrong. Assuming a UTF-8 locale at - line 12.
-+Use of (?[ ]) for non-UTF-8 locale is wrong. Assuming a UTF-8 locale at - line 13.
-+Use of (?[ ]) for non-UTF-8 locale is wrong. Assuming a UTF-8 locale at - line 13.
-+Use of (?[ ]) for non-UTF-8 locale is wrong. Assuming a UTF-8 locale at - line 14.
-+Use of (?[ ]) for non-UTF-8 locale is wrong. Assuming a UTF-8 locale at - line 14.
-+Use of (?[ ]) for non-UTF-8 locale is wrong. Assuming a UTF-8 locale at - line 15.
-+Use of (?[ ]) for non-UTF-8 locale is wrong. Assuming a UTF-8 locale at - line 15.
-+Use of (?[ ]) for non-UTF-8 locale is wrong. Assuming a UTF-8 locale at - line 16.
-+Use of (?[ ]) for non-UTF-8 locale is wrong. Assuming a UTF-8 locale at - line 16.
- ########
- # NAME (?[ ]) in UTF-8 locale
- require '../loc_tools.pl';
--- a/ext/Errno/Errno_pm.PL
+++ b/ext/Errno/Errno_pm.PL
-@@ -133,7 +133,7 @@ sub get_files {
+@@ -115,7 +115,7 @@ sub get_files {
# Some Linuxes have weird errno.hs which generate
# no #file or #line directives
- my ($linux_errno_h) = grep { -e $_ } map { "$_/errno.h" }
+ ($linux_errno_h) = grep { -e $_ } map { "$_/errno.h" }
- "$sysroot/usr/include", "$sysroot/usr/local/include",
+ "$sysroot/usr/include", "$sysroot/usr/local/include", "$sysroot/include",
- split / / => $Config{locincpth} or
- die "Cannot find errno.h";
- $file{$linux_errno_h} = 1;
+ split / / => $Config{locincpth};
+ }
+
+++ /dev/null
-From 6bd6308fcea3541e505651bf8e8127a4a03d22cd Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Petr=20P=C3=ADsa=C5=99?= <ppisar@redhat.com>
-Date: Tue, 12 Nov 2019 09:19:18 +0100
-Subject: [PATCH] Adapt Configure to GCC version 10
-
-I got a notice from Jeff Law <law@redhat.com>:
-
- Your particular package fails its testsuite. This was ultimately
- tracked down to a Configure problem. The perl configure script treated
- gcc-10 as gcc-1 and turned on -fpcc-struct-return. This is an ABI
- changing flag and caused Perl to not be able to interact properly with
- the dbm libraries on the system leading to a segfault.
-
-His proposed patch corrected only this one instance of the version
-mismatch. Reading the Configure script revealed more issues. This
-patch fixes all of them I found.
-
----
- Configure | 14 +++++++-------
- cflags.SH | 2 +-
- 2 files changed, 8 insertions(+), 8 deletions(-)
-
---- a/Configure
-+++ b/Configure
-@@ -4689,7 +4689,7 @@ else
- fi
- $rm -f try try.*
- case "$gccversion" in
--1*) cpp=`./loc gcc-cpp $cpp $pth` ;;
-+1.*) cpp=`./loc gcc-cpp $cpp $pth` ;;
- esac
- case "$gccversion" in
- '') gccosandvers='' ;;
-@@ -4729,7 +4729,7 @@ esac
- # gcc 3.* complain about adding -Idirectories that they already know about,
- # so we will take those off from locincpth.
- case "$gccversion" in
--3*)
-+3.*)
- echo "main(){}">try.c
- for incdir in $locincpth; do
- warn=`$cc $ccflags -I$incdir -c try.c 2>&1 | \
-@@ -5455,13 +5455,13 @@ fi
- case "$hint" in
- default|recommended)
- case "$gccversion" in
-- 1*) dflt="$dflt -fpcc-struct-return" ;;
-+ 1.*) dflt="$dflt -fpcc-struct-return" ;;
- esac
- case "$optimize:$DEBUGGING" in
- *-g*:old) dflt="$dflt -DDEBUGGING";;
- esac
- case "$gccversion" in
-- 2*) if $test -d /etc/conf/kconfig.d &&
-+ 2.*) if $test -d /etc/conf/kconfig.d &&
- $contains _POSIX_VERSION $usrinc/sys/unistd.h >/dev/null 2>&1
- then
- # Interactive Systems (ISC) POSIX mode.
-@@ -5470,7 +5470,7 @@ default|recommended)
- ;;
- esac
- case "$gccversion" in
-- 1*) ;;
-+ 1.*) ;;
- 2.[0-8]*) ;;
- ?*) set strict-aliasing -fno-strict-aliasing
- eval $checkccflag
-@@ -5588,7 +5588,7 @@ case "$cppflags" in
- ;;
- esac
- case "$gccversion" in
--1*) cppflags="$cppflags -D__GNUC__"
-+1.*) cppflags="$cppflags -D__GNUC__"
- esac
- case "$mips_type" in
- '');;
-@@ -22957,7 +22957,7 @@ fi
-
- : add -D_FORTIFY_SOURCE if feasible and not already there
- case "$gccversion" in
--[4567].*) case "$optimize$ccflags" in
-+[456789].*|[1-9][0-9]*) case "$optimize$ccflags" in
- *-O*) case "$ccflags$cppsymbols" in
- *_FORTIFY_SOURCE=*) # Don't add it again.
- echo "You seem to have -D_FORTIFY_SOURCE already, not adding it." >&4
---- a/cflags.SH
-+++ b/cflags.SH
-@@ -156,7 +156,7 @@ esac
-
- case "$gccversion" in
- '') ;;
--[12]*) ;; # gcc versions 1 (gasp!) and 2 are not good for this.
-+[12].*) ;; # gcc versions 1 (gasp!) and 2 are not good for this.
- Intel*) ;; # # Is that you, Intel C++?
- #
- # NOTE 1: the -std=c89 without -pedantic is a bit pointless.
--- /dev/null
+From ba6e2c38aafc23cf114f3ba0d0ff3baead34328b Mon Sep 17 00:00:00 2001
+From: Yves Orton <demerphq@gmail.com>
+Date: Tue, 1 Aug 2023 23:12:46 +0200
+Subject: [PATCH] regcomp*.c, regexec.c - fixup regex engine build under
+ -Uusedl
+
+The regex engine is built a bit different from most of the perl
+codebase. It is compiled as part of the main libperl.so and it is
+also compiled (with DEBUGGING enabled) as part of the re extension.
+When perl itself is compiled with DEBUGGING enabled then the code
+in the re.so extension and the code in libperl.so is the same.
+
+This all works fine and dandy until you have a static build where the
+re.so is linked into libperl.so, which results in duplicate symbols
+being defined. These symbols come in two flaviours: "auxiliary" and
+"debugging" related symbols.
+
+We have basically three cases:
+
+1. USE_DYNAMIC_LOADING is defined. In this case we are doing a dynamic
+ build and re.so will be separate from libperl.so, so it even if this
+ is a DEBUGGING enabled build debug and auxiliary functions can be
+ compiled into *both* re.so and libperl.so. This is basically the
+ "standard build".
+
+2. USE_DYNAMIC_LOADING is not defined, and DEBUGGING is not defined
+ either. In this case auxiliary functions should only be compiled in
+ libperl.so, and the debug functions should only be compiled into
+ re.so
+
+3. USE_DYNAMIC_LOADING is not defined, and DEBUGGING *is* defined. In
+ this case auxiliary functions AND debug functions should only be
+ compiled into libperl.so
+
+It is possible to detect the different build options by looking at the
+defines 'USE_DYNAMIC_LOADING', 'PERL_EXT_RE_DEBUG' and
+'DEBUGGING_RE_ONLY'. 'USE_DYNAMIC_LOADING' is NOT defined when we are
+building a static perl. 'PERL_EXT_RE_DEBUG' is defined only when we are
+building re.so, and 'DEBUGGING_RE_ONLY' is defined only when we are
+building re.so in a perl that is not itself already a DEBUGGING enabled
+perl. The file ext/re/re_top.h responsible for setting up
+DEBUGGING_RE_ONLY.
+
+This patch uses 'PERL_EXT_RE_DEBUG', 'DEBUGGING_RE_ONLY' and
+'USE_DYNAMIC_LOADING' to define in regcomp.h two further define flags
+'PERL_RE_BUILD_DEBUG' and 'PERL_RE_BUILD_AUX'.
+
+The 'PERL_RE_BUILD_DEBUG' flag determines if the debugging functions
+should be compiled into libperl.so or re.so or both. The
+'PERL_RE_BUILD_AUX' flag determines if the auxiliary functions should be
+compiled into just libperl.so or into it and re.so. We then use these
+flags to guard the different types of functions so that we can build in
+all three modes without duplicate symbols.
+---
+ regcomp.c | 13 +-
+ regcomp.h | 14 ++-
+ regcomp_debug.c | 308 +++++++++++++++++++++++-----------------------
+ regcomp_invlist.c | 3 +-
+ regexec.c | 3 +-
+ 5 files changed, 181 insertions(+), 160 deletions(-)
+
+--- a/regcomp.c
++++ b/regcomp.c
+@@ -290,6 +290,7 @@ S_edit_distance(const UV* src,
+ /* END of edit_distance() stuff
+ * ========================================================= */
+
++#ifdef PERL_RE_BUILD_AUX
+ /* add a data member to the struct reg_data attached to this regex, it should
+ * always return a non-zero return. the 's' argument is the type of the items
+ * being added and the n is the number of items. The length of 's' should match
+@@ -340,6 +341,7 @@ Perl_reg_add_data(RExC_state_t* const pR
+ assert(count>0);
+ return count;
+ }
++#endif /* PERL_RE_BUILD_AUX */
+
+ /*XXX: todo make this not included in a non debugging perl, but appears to be
+ * used anyway there, in 'use re' */
+@@ -7443,6 +7445,7 @@ S_regatom(pTHX_ RExC_state_t *pRExC_stat
+ }
+
+
++#ifdef PERL_RE_BUILD_AUX
+ void
+ Perl_populate_anyof_bitmap_from_invlist(pTHX_ regnode *node, SV** invlist_ptr)
+ {
+@@ -7502,6 +7505,7 @@ Perl_populate_anyof_bitmap_from_invlist(
+ }
+ }
+ }
++#endif /* PERL_RE_BUILD_AUX */
+
+ /* Parse POSIX character classes: [[:foo:]], [[=foo=]], [[.foo.]].
+ Character classes ([:foo:]) can also be negated ([:^foo:]).
+@@ -9095,6 +9099,7 @@ S_dump_regex_sets_structures(pTHX_ RExC_
+ #undef IS_OPERATOR
+ #undef IS_OPERAND
+
++#ifdef PERL_RE_BUILD_AUX
+ void
+ Perl_add_above_Latin1_folds(pTHX_ RExC_state_t *pRExC_state, const U8 cp, SV** invlist)
+ {
+@@ -9182,6 +9187,8 @@ Perl_add_above_Latin1_folds(pTHX_ RExC_s
+ }
+ }
+ }
++#endif /* PERL_RE_BUILD_AUX */
++
+
+ STATIC void
+ S_output_posix_warnings(pTHX_ RExC_state_t *pRExC_state, AV* posix_warnings)
+@@ -12105,6 +12112,7 @@ S_optimize_regclass(pTHX_
+
+ #undef HAS_NONLOCALE_RUNTIME_PROPERTY_DEFINITION
+
++#ifdef PERL_RE_BUILD_AUX
+ void
+ Perl_set_ANYOF_arg(pTHX_ RExC_state_t* const pRExC_state,
+ regnode* const node,
+@@ -12261,6 +12269,7 @@ Perl_set_ANYOF_arg(pTHX_ RExC_state_t* c
+ RExC_rxi->data->data[n] = (void*)rv;
+ ARG1u_SET(node, n);
+ }
++#endif /* PERL_RE_BUILD_AUX */
+
+ SV *
+
+@@ -12999,6 +13008,8 @@ S_regtail_study(pTHX_ RExC_state_t *pREx
+ }
+ #endif
+
++
++#ifdef PERL_RE_BUILD_AUX
+ SV*
+ Perl_get_ANYOFM_contents(pTHX_ const regnode * n) {
+
+@@ -13047,7 +13058,7 @@ Perl_get_ANYOFHbbm_contents(pTHX_ const
+ UTF_CONTINUATION_MARK | 0));
+ return cp_list;
+ }
+-
++#endif /* PERL_RE_BUILD_AUX */
+
+
+ SV *
+--- a/regcomp.h
++++ b/regcomp.h
+@@ -1554,7 +1554,19 @@ typedef enum {
+ #define EVAL_OPTIMISTIC_FLAG 128
+ #define EVAL_FLAGS_MASK (EVAL_OPTIMISTIC_FLAG-1)
+
+-
++/* We define PERL_RE_BUILD_DEBUG if we are NOT compiling the re extension and
++ * we are under DEBUGGING, or if we are ARE compiling the re extension
++ * and this is not a DEBUGGING enabled build (identified by
++ * DEBUGGING_RE_ONLY being defined)
++ */
++#if ( defined(USE_DYNAMIC_LOADING) && defined(DEBUGGING)) || \
++ ( defined(PERL_EXT_RE_BUILD) && defined(DEBUGGING_RE_ONLY)) || \
++ (!defined(PERL_EXT_RE_BUILD) && defined(DEBUGGING))
++#define PERL_RE_BUILD_DEBUG
++#endif
++#if ( defined(USE_DYNAMIC_LOADING) || !defined(PERL_EXT_RE_BUILD) )
++#define PERL_RE_BUILD_AUX
++#endif
+
+ #endif /* PERL_REGCOMP_H_ */
+
+--- a/regcomp_debug.c
++++ b/regcomp_debug.c
+@@ -18,8 +18,7 @@
+ #include "unicode_constants.h"
+ #include "regcomp_internal.h"
+
+-#ifdef DEBUGGING
+-
++#ifdef PERL_RE_BUILD_DEBUG
+ int
+ Perl_re_printf(pTHX_ const char *fmt, ...)
+ {
+@@ -159,13 +158,160 @@ Perl_debug_peep(pTHX_ const char *str, c
+ });
+ }
+
+-#endif /* DEBUGGING */
++const regnode *
++Perl_dumpuntil(pTHX_ const regexp *r, const regnode *start, const regnode *node,
++ const regnode *last, const regnode *plast,
++ SV* sv, I32 indent, U32 depth)
++{
++ const regnode *next;
++ const regnode *optstart= NULL;
++
++ RXi_GET_DECL(r, ri);
++ DECLARE_AND_GET_RE_DEBUG_FLAGS;
++
++ PERL_ARGS_ASSERT_DUMPUNTIL;
++
++#ifdef DEBUG_DUMPUNTIL
++ Perl_re_printf( aTHX_ "--- %d : %d - %d - %d\n", indent, node-start,
++ last ? last-start : 0, plast ? plast-start : 0);
++#endif
++
++ if (plast && plast < last)
++ last= plast;
++
++ while (node && (!last || node < last)) {
++ const U8 op = OP(node);
++
++ if (op == CLOSE || op == SRCLOSE || op == WHILEM)
++ indent--;
++ next = regnext((regnode *)node);
++ const regnode *after = regnode_after((regnode *)node,0);
++
++ /* Where, what. */
++ if (op == OPTIMIZED) {
++ if (!optstart && RE_DEBUG_FLAG(RE_DEBUG_COMPILE_OPTIMISE))
++ optstart = node;
++ else
++ goto after_print;
++ } else
++ CLEAR_OPTSTART;
++
++ regprop(r, sv, node, NULL, NULL);
++ Perl_re_printf( aTHX_ "%4" IVdf ":%*s%s", (IV)(node - start),
++ (int)(2*indent + 1), "", SvPVX_const(sv));
++
++ if (op != OPTIMIZED) {
++ if (next == NULL) /* Next ptr. */
++ Perl_re_printf( aTHX_ " (0)");
++ else if (REGNODE_TYPE(op) == BRANCH
++ && REGNODE_TYPE(OP(next)) != BRANCH )
++ Perl_re_printf( aTHX_ " (FAIL)");
++ else
++ Perl_re_printf( aTHX_ " (%" IVdf ")", (IV)(next - start));
++ Perl_re_printf( aTHX_ "\n");
++ }
++
++ after_print:
++ if (REGNODE_TYPE(op) == BRANCHJ) {
++ assert(next);
++ const regnode *nnode = (OP(next) == LONGJMP
++ ? regnext((regnode *)next)
++ : next);
++ if (last && nnode > last)
++ nnode = last;
++ DUMPUNTIL(after, nnode);
++ }
++ else if (REGNODE_TYPE(op) == BRANCH) {
++ assert(next);
++ DUMPUNTIL(after, next);
++ }
++ else if ( REGNODE_TYPE(op) == TRIE ) {
++ const regnode *this_trie = node;
++ const U32 n = ARG1u(node);
++ const reg_ac_data * const ac = op>=AHOCORASICK ?
++ (reg_ac_data *)ri->data->data[n] :
++ NULL;
++ const reg_trie_data * const trie =
++ (reg_trie_data*)ri->data->data[op<AHOCORASICK ? n : ac->trie];
++#ifdef DEBUGGING
++ AV *const trie_words
++ = MUTABLE_AV(ri->data->data[n + TRIE_WORDS_OFFSET]);
++#endif
++ const regnode *nextbranch= NULL;
++ I32 word_idx;
++ SvPVCLEAR(sv);
++ for (word_idx= 0; word_idx < (I32)trie->wordcount; word_idx++) {
++ SV ** const elem_ptr = av_fetch_simple(trie_words, word_idx, 0);
++
++ Perl_re_indentf( aTHX_ "%s ",
++ indent+3,
++ elem_ptr
++ ? pv_pretty(sv, SvPV_nolen_const(*elem_ptr),
++ SvCUR(*elem_ptr), PL_dump_re_max_len,
++ PL_colors[0], PL_colors[1],
++ (SvUTF8(*elem_ptr)
++ ? PERL_PV_ESCAPE_UNI
++ : 0)
++ | PERL_PV_PRETTY_ELLIPSES
++ | PERL_PV_PRETTY_LTGT
++ )
++ : "???"
++ );
++ if (trie->jump) {
++ U16 dist= trie->jump[word_idx+1];
++ Perl_re_printf( aTHX_ "(%" UVuf ")\n",
++ (UV)((dist ? this_trie + dist : next) - start));
++ if (dist) {
++ if (!nextbranch)
++ nextbranch= this_trie + trie->jump[0];
++ DUMPUNTIL(this_trie + dist, nextbranch);
++ }
++ if (nextbranch && REGNODE_TYPE(OP(nextbranch))==BRANCH)
++ nextbranch= regnext((regnode *)nextbranch);
++ } else {
++ Perl_re_printf( aTHX_ "\n");
++ }
++ }
++ if (last && next > last)
++ node= last;
++ else
++ node= next;
++ }
++ else if ( op == CURLY ) { /* "next" might be very big: optimizer */
++ DUMPUNTIL(after, after + 1); /* +1 is NOT a REGNODE_AFTER */
++ }
++ else if (REGNODE_TYPE(op) == CURLY && op != CURLYX) {
++ assert(next);
++ DUMPUNTIL(after, next);
++ }
++ else if ( op == PLUS || op == STAR) {
++ DUMPUNTIL(after, after + 1); /* +1 NOT a REGNODE_AFTER */
++ }
++ else if (REGNODE_TYPE(op) == EXACT || op == ANYOFHs) {
++ /* Literal string, where present. */
++ node = (const regnode *)REGNODE_AFTER_varies(node);
++ }
++ else {
++ node = REGNODE_AFTER_opcode(node,op);
++ }
++ if (op == CURLYX || op == OPEN || op == SROPEN)
++ indent++;
++ if (REGNODE_TYPE(op) == END)
++ break;
++ }
++ CLEAR_OPTSTART;
++#ifdef DEBUG_DUMPUNTIL
++ Perl_re_printf( aTHX_ "--- %d\n", (int)indent);
++#endif
++ return node;
++}
++
++#endif /* PERL_RE_BUILD_DEBUG */
+
+ /*
+ - regdump - dump a regexp onto Perl_debug_log in vaguely comprehensible form
+ */
+ #ifdef DEBUGGING
+-
+ static void
+ S_regdump_intflags(pTHX_ const char *lead, const U32 flags)
+ {
+@@ -907,8 +1053,8 @@ Perl_regprop(pTHX_ const regexp *prog, S
+ #endif /* DEBUGGING */
+ }
+
+-#ifdef DEBUGGING
+
++#ifdef DEBUGGING
+ STATIC void
+ S_put_code_point(pTHX_ SV *sv, UV c)
+ {
+@@ -1517,154 +1663,4 @@ S_put_charclass_bitmap_innards(pTHX_ SV
+
+ return did_output_something;
+ }
+-
+-
+-const regnode *
+-Perl_dumpuntil(pTHX_ const regexp *r, const regnode *start, const regnode *node,
+- const regnode *last, const regnode *plast,
+- SV* sv, I32 indent, U32 depth)
+-{
+- const regnode *next;
+- const regnode *optstart= NULL;
+-
+- RXi_GET_DECL(r, ri);
+- DECLARE_AND_GET_RE_DEBUG_FLAGS;
+-
+- PERL_ARGS_ASSERT_DUMPUNTIL;
+-
+-#ifdef DEBUG_DUMPUNTIL
+- Perl_re_printf( aTHX_ "--- %d : %d - %d - %d\n", indent, node-start,
+- last ? last-start : 0, plast ? plast-start : 0);
+-#endif
+-
+- if (plast && plast < last)
+- last= plast;
+-
+- while (node && (!last || node < last)) {
+- const U8 op = OP(node);
+-
+- if (op == CLOSE || op == SRCLOSE || op == WHILEM)
+- indent--;
+- next = regnext((regnode *)node);
+- const regnode *after = regnode_after((regnode *)node,0);
+-
+- /* Where, what. */
+- if (op == OPTIMIZED) {
+- if (!optstart && RE_DEBUG_FLAG(RE_DEBUG_COMPILE_OPTIMISE))
+- optstart = node;
+- else
+- goto after_print;
+- } else
+- CLEAR_OPTSTART;
+-
+- regprop(r, sv, node, NULL, NULL);
+- Perl_re_printf( aTHX_ "%4" IVdf ":%*s%s", (IV)(node - start),
+- (int)(2*indent + 1), "", SvPVX_const(sv));
+-
+- if (op != OPTIMIZED) {
+- if (next == NULL) /* Next ptr. */
+- Perl_re_printf( aTHX_ " (0)");
+- else if (REGNODE_TYPE(op) == BRANCH
+- && REGNODE_TYPE(OP(next)) != BRANCH )
+- Perl_re_printf( aTHX_ " (FAIL)");
+- else
+- Perl_re_printf( aTHX_ " (%" IVdf ")", (IV)(next - start));
+- Perl_re_printf( aTHX_ "\n");
+- }
+-
+- after_print:
+- if (REGNODE_TYPE(op) == BRANCHJ) {
+- assert(next);
+- const regnode *nnode = (OP(next) == LONGJMP
+- ? regnext((regnode *)next)
+- : next);
+- if (last && nnode > last)
+- nnode = last;
+- DUMPUNTIL(after, nnode);
+- }
+- else if (REGNODE_TYPE(op) == BRANCH) {
+- assert(next);
+- DUMPUNTIL(after, next);
+- }
+- else if ( REGNODE_TYPE(op) == TRIE ) {
+- const regnode *this_trie = node;
+- const U32 n = ARG1u(node);
+- const reg_ac_data * const ac = op>=AHOCORASICK ?
+- (reg_ac_data *)ri->data->data[n] :
+- NULL;
+- const reg_trie_data * const trie =
+- (reg_trie_data*)ri->data->data[op<AHOCORASICK ? n : ac->trie];
+-#ifdef DEBUGGING
+- AV *const trie_words
+- = MUTABLE_AV(ri->data->data[n + TRIE_WORDS_OFFSET]);
+-#endif
+- const regnode *nextbranch= NULL;
+- I32 word_idx;
+- SvPVCLEAR(sv);
+- for (word_idx= 0; word_idx < (I32)trie->wordcount; word_idx++) {
+- SV ** const elem_ptr = av_fetch_simple(trie_words, word_idx, 0);
+-
+- Perl_re_indentf( aTHX_ "%s ",
+- indent+3,
+- elem_ptr
+- ? pv_pretty(sv, SvPV_nolen_const(*elem_ptr),
+- SvCUR(*elem_ptr), PL_dump_re_max_len,
+- PL_colors[0], PL_colors[1],
+- (SvUTF8(*elem_ptr)
+- ? PERL_PV_ESCAPE_UNI
+- : 0)
+- | PERL_PV_PRETTY_ELLIPSES
+- | PERL_PV_PRETTY_LTGT
+- )
+- : "???"
+- );
+- if (trie->jump) {
+- U16 dist= trie->jump[word_idx+1];
+- Perl_re_printf( aTHX_ "(%" UVuf ")\n",
+- (UV)((dist ? this_trie + dist : next) - start));
+- if (dist) {
+- if (!nextbranch)
+- nextbranch= this_trie + trie->jump[0];
+- DUMPUNTIL(this_trie + dist, nextbranch);
+- }
+- if (nextbranch && REGNODE_TYPE(OP(nextbranch))==BRANCH)
+- nextbranch= regnext((regnode *)nextbranch);
+- } else {
+- Perl_re_printf( aTHX_ "\n");
+- }
+- }
+- if (last && next > last)
+- node= last;
+- else
+- node= next;
+- }
+- else if ( op == CURLY ) { /* "next" might be very big: optimizer */
+- DUMPUNTIL(after, after + 1); /* +1 is NOT a REGNODE_AFTER */
+- }
+- else if (REGNODE_TYPE(op) == CURLY && op != CURLYX) {
+- assert(next);
+- DUMPUNTIL(after, next);
+- }
+- else if ( op == PLUS || op == STAR) {
+- DUMPUNTIL(after, after + 1); /* +1 NOT a REGNODE_AFTER */
+- }
+- else if (REGNODE_TYPE(op) == EXACT || op == ANYOFHs) {
+- /* Literal string, where present. */
+- node = (const regnode *)REGNODE_AFTER_varies(node);
+- }
+- else {
+- node = REGNODE_AFTER_opcode(node,op);
+- }
+- if (op == CURLYX || op == OPEN || op == SROPEN)
+- indent++;
+- if (REGNODE_TYPE(op) == END)
+- break;
+- }
+- CLEAR_OPTSTART;
+-#ifdef DEBUG_DUMPUNTIL
+- Perl_re_printf( aTHX_ "--- %d\n", (int)indent);
+-#endif
+- return node;
+-}
+-
+-#endif /* DEBUGGING */
++#endif /* DEBUGGING */
+--- a/regcomp_invlist.c
++++ b/regcomp_invlist.c
+@@ -18,7 +18,7 @@
+ #include "unicode_constants.h"
+ #include "regcomp_internal.h"
+
+-
++#ifdef PERL_RE_BUILD_AUX
+ void
+ Perl_populate_bitmap_from_invlist(pTHX_ SV * invlist, const UV offset, const U8 * bitmap, const Size_t len)
+ {
+@@ -70,6 +70,7 @@ Perl_populate_invlist_from_bitmap(pTHX_
+ }
+ }
+ }
++#endif /* PERL_RE_BUILD_AUX */
+
+ /* This section of code defines the inversion list object and its methods. The
+ * interfaces are highly subject to change, so as much as possible is static to
+--- a/regexec.c
++++ b/regexec.c
+@@ -4421,7 +4421,8 @@ S_regtry(pTHX_ regmatch_info *reginfo, c
+ */
+ #define REPORT_CODE_OFF 29
+ #define INDENT_CHARS(depth) ((int)(depth) % 20)
+-#ifdef DEBUGGING
++
++#ifdef PERL_RE_BUILD_DEBUG
+ int
+ Perl_re_exec_indentf(pTHX_ const char *fmt, U32 depth, ...)
+ {
$(eval $(call BuildPackage,perlbase-archive))
-define Package/perlbase-arybase
-$(call Package/perlbase-template)
-TITLE:=arybase perl module
-DEPENDS+=+perlbase-xsloader
-endef
-
-define Package/perlbase-arybase/install
-$(call perlmod/Install,$(1),arybase.pm auto/arybase,)
-$(call perlmod/InstallBaseTests,$(1),ext/arybase/t)
-endef
-
-$(eval $(call BuildPackage,perlbase-arybase))
-
-
define Package/perlbase-attribute
$(call Package/perlbase-template)
TITLE:=Attribute perl module
define Package/perlbase-findbin/install
$(call perlmod/Install,$(1),FindBin.pm,)
-$(call perlmod/InstallBaseTests,$(1),lib/FindBin.t)
+$(call perlmod/InstallBaseTests,$(1),dist/FindBin/t)
endef
$(eval $(call BuildPackage,perlbase-findbin))
endef
define Package/perlbase-tie/install
-$(call perlmod/Install,$(1),Tie auto/Tie,)
+$(call perlmod/Install,$(1),Tie,)
$(call perlmod/InstallBaseTests,$(1),cpan/Tie-RefHash/t dist/Tie-File/t ext/Tie-Hash-NamedCapture/t ext/Tie-Memoize/lib/Tie/Memoize.pm ext/Tie-Memoize/t lib/Tie/Array/push.t lib/Tie/Array/splice.t lib/Tie/Array/std.t lib/Tie/Array/stdpush.t lib/Tie/ExtraHash.t lib/Tie/Handle/stdhandle.t lib/Tie/Handle/stdhandle_from_handle.t lib/Tie/Hash.t lib/Tie/Scalar.t lib/Tie/SubstrHash.t)
endef
endef
define Package/perlbase-utf8/install
-$(call perlmod/Install,$(1),utf8.pm utf8_heavy.pl,)
+$(call perlmod/Install,$(1),utf8.pm,)
$(call perlmod/InstallBaseTests,$(1),lib/utf8.t)
endef
-PERL_VERSION:=5.28.1
+PERL_VERSION:=5.38.0
PERL_EXPLODE:=$(subst ., ,$(PERL_VERSION))
--- /dev/null
+#
+# Copyright (C) 2023 Jeffery To
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=pipx
+PKG_VERSION:=1.2.1
+PKG_RELEASE:=1
+
+PYPI_NAME:=pipx
+PKG_HASH:=698777c05a97cca81df4dc6a71d9ca4ece2184c6f91dc7a0e4802ac51d86d32a
+
+PKG_LICENSE:=MIT
+PKG_LICENSE_FILES:=LICENSE
+PKG_MAINTAINER:=Jeffery To <jeffery.to@gmail.com>
+
+PKG_BUILD_DEPENDS:=python-hatchling/host
+
+include ../pypi.mk
+include $(INCLUDE_DIR)/package.mk
+include ../python3-package.mk
+
+define Package/pipx
+ SECTION:=lang
+ CATEGORY:=Languages
+ SUBMENU:=Python
+ TITLE:=Install/Run Python Applications in Isolated Environments
+ URL:=https://github.com/pypa/pipx
+ DEPENDS:= \
+ +python3-light \
+ +python3-logging \
+ +python3-urllib \
+ +python3-venv \
+ +python3-argcomplete \
+ +python3-packaging \
+ +python3-userpath
+endef
+
+define Package/pipx/description
+pipx is a tool to help you install and run end-user applications written
+in Python. It's roughly similar to macOS's brew, JavaScript's npx, and
+Linux's apt.
+
+It's closely related to pip. In fact, it uses pip, but is focused on
+installing and managing Python packages that can be run from the command
+line directly as applications.
+endef
+
+$(eval $(call Py3Package,pipx))
+$(eval $(call BuildPackage,pipx))
+$(eval $(call BuildPackage,pipx-src))
--- /dev/null
+#!/bin/sh
+
+[ "$1" = pipx ] || exit 0
+
+pipx --version | grep -Fx "$PKG_VERSION"
--- /dev/null
+#
+# Copyright (C) 2023 Jeffery To
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=python-argcomplete
+PKG_VERSION:=3.1.6
+PKG_RELEASE:=1
+
+PYPI_NAME:=argcomplete
+PKG_HASH:=3b1f07d133332547a53c79437527c00be48cca3807b1d4ca5cab1b26313386a6
+
+PKG_LICENSE:=Apache-2.0
+PKG_LICENSE_FILES:=LICENSE.rst
+PKG_MAINTAINER:=Jeffery To <jeffery.to@gmail.com>
+
+PKG_BUILD_DEPENDS:=python-setuptools-scm/host
+
+include ../pypi.mk
+include $(INCLUDE_DIR)/package.mk
+include ../python3-package.mk
+
+define Package/python3-argcomplete
+ SECTION:=lang
+ CATEGORY:=Languages
+ SUBMENU:=Python
+ TITLE:=Bash tab completion for argparse
+ URL:=https://github.com/kislyuk/argcomplete
+ DEPENDS:=+python3-light
+endef
+
+define Package/python3-argcomplete/description
+Argcomplete provides easy, extensible command line tab completion of
+arguments for your Python application.
+endef
+
+$(eval $(call Py3Package,python3-argcomplete))
+$(eval $(call BuildPackage,python3-argcomplete))
+$(eval $(call BuildPackage,python3-argcomplete-src))
--- /dev/null
+--- a/pyproject.toml
++++ b/pyproject.toml
+@@ -1,5 +1,5 @@
+ [build-system]
+-requires = ["setuptools>=67.7.2", "setuptools_scm[toml]>=6.2"]
++requires = ["setuptools", "setuptools_scm[toml]>=6.2"]
+ build-backend = "setuptools.build_meta"
+
+ [project]
--- /dev/null
+#!/bin/sh
+
+[ "$1" = python3-argcomplete ] || exit 0
+
+python3 -c 'import argcomplete'
--- /dev/null
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=python-fnv-hash-fast
+PKG_VERSION:=0.5.0
+PKG_RELEASE:=1
+
+PYPI_NAME:=fnv-hash-fast
+PYPI_SOURCE_NAME:=fnv_hash_fast
+PKG_HASH:=a84d658952776a186418f4158fc8e55ff3c576ac32cc9ef7f8077efdf2d0b89f
+
+PKG_MAINTAINER:=Timothy Ace <openwrt@timothyace.com>
+PKG_LICENSE:=MIT
+PKG_LICENSE_FILES:=LICENSE
+
+PKG_BUILD_DEPENDS:=python-cython/host python-poetry-core/host
+
+include ../pypi.mk
+include $(INCLUDE_DIR)/package.mk
+include ../python3-package.mk
+
+define Package/python3-fnv-hash-fast
+ SECTION:=lang
+ CATEGORY:=Languages
+ SUBMENU:=Python
+ TITLE:=A fast version of fnv1a
+ URL:=https://github.com/bdraco/fnv-hash-fast
+ DEPENDS:=+libstdcpp +python3-light +python3-fnvhash
+endef
+
+define Package/python3-fnv-hash-fast/description
+A fast version of fnv1a. This library will use a CPP implementation of fnv1a
+(32) if cython is available, and will fallback to pure python from the fnvhash
+package if it is not.
+endef
+
+$(eval $(call Py3Package,python3-fnv-hash-fast))
+$(eval $(call BuildPackage,python3-fnv-hash-fast))
+$(eval $(call BuildPackage,python3-fnv-hash-fast-src))
--- /dev/null
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=python-fnvhash
+PKG_VERSION:=0.1.0
+PKG_RELEASE:=1
+
+PYPI_NAME:=fnvhash
+PKG_HASH:=3e82d505054f9f3987b2b5b649f7e7b6f48349f6af8a1b8e4d66779699c85a8e
+
+PKG_MAINTAINER:=Timothy Ace <openwrt@timothyace.com>
+PKG_LICENSE:=MIT
+PKG_LICENSE_FILES:=LICENSE
+
+include ../pypi.mk
+include $(INCLUDE_DIR)/package.mk
+include ../python3-package.mk
+
+define Package/python3-fnvhash
+ SECTION:=lang
+ CATEGORY:=Languages
+ SUBMENU:=Python
+ TITLE:=Pure Python FNV hash implementation
+ URL:=https://github.com/znerol/py-fnvhash
+ DEPENDS:=+python3-light
+endef
+
+define Package/python3-fnvhash/description
+Pure Python implementation of the FNV hash family with 100% test coverage.
+endef
+
+$(eval $(call Py3Package,python3-fnvhash))
+$(eval $(call BuildPackage,python3-fnvhash))
+$(eval $(call BuildPackage,python3-fnvhash-src))
include $(TOPDIR)/rules.mk
PKG_NAME:=python-hatch-vcs
-PKG_VERSION:=0.3.0
+PKG_VERSION:=0.4.0
PKG_RELEASE:=1
PYPI_NAME:=hatch-vcs
PYPI_SOURCE_NAME:=hatch_vcs
-PKG_HASH:=cec5107cfce482c67f8bc96f18bbc320c9aa0d068180e14ad317bbee5a153fee
+PKG_HASH:=093810748fe01db0d451fabcf2c1ac2688caefd232d4ede967090b1c1b07d9f7
PKG_LICENSE:=MIT
PKG_LICENSE_FILES:=LICENSE.txt
include $(TOPDIR)/rules.mk
PKG_NAME:=python-idna
-PKG_VERSION:=3.4
+PKG_VERSION:=3.6
PKG_RELEASE:=1
PYPI_NAME:=idna
-PKG_HASH:=814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4
+PKG_HASH:=9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca
PKG_LICENSE:=BSD-3-Clause
-PKG_LICENSE_FILES:=LICENSE.rst
+PKG_LICENSE_FILES:=LICENSE.md
PKG_MAINTAINER:=Jeffery To <jeffery.to@gmail.com>
PKG_BUILD_DEPENDS:=python-flit-core/host
SUBMENU:=Python
TITLE:=IDNA library
URL:=https://github.com/kjd/idna
- DEPENDS:= \
- +python3-light \
- +python3-codecs
+ DEPENDS:=+python3-light +python3-codecs
endef
define Package/python3-idna/description
--- /dev/null
+#!/bin/sh
+
+[ "$1" = python3-idna ] || exit 0
+
+python3 - << 'EOF'
+
+import idna
+import idna.codec
+
+assert idna.encode('ドメイン.テスト') == b'xn--eckwd4c7c.xn--zckzah'
+assert idna.decode('xn--eckwd4c7c.xn--zckzah') == 'ドメイン.テスト'
+
+assert 'домен.испытание'.encode('idna2008') == b'xn--d1acufc.xn--80akhbyknj4f'
+assert b'xn--d1acufc.xn--80akhbyknj4f'.decode('idna2008') == 'домен.испытание'
+
+assert idna.alabel('测试') == b'xn--0zwm56d'
+
+assert idna.encode('Königsgäßchen', uts46=True) == b'xn--knigsgchen-b4a3dun'
+assert idna.decode('xn--knigsgchen-b4a3dun') == 'königsgäßchen'
+
+assert idna.encode('Königsgäßchen', uts46=True, transitional=True) == b'xn--knigsgsschen-lcb0w'
+
+EOF
--- /dev/null
+#
+# Copyright (C) 2023 Jeffery To
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=python-jsonschema-specifications
+PKG_VERSION:=2023.7.1
+PKG_RELEASE:=1
+
+PYPI_NAME:=jsonschema-specifications
+PYPI_SOURCE_NAME:=jsonschema_specifications
+PKG_HASH:=c91a50404e88a1f6ba40636778e2ee08f6e24c5613fe4c53ac24578a5a7f72bb
+
+PKG_LICENSE:=MIT
+PKG_LICENSE_FILES:=COPYING
+PKG_MAINTAINER:=Jeffery To <jeffery.to@gmail.com>
+
+PKG_BUILD_DEPENDS:=python-hatchling/host python-hatch-vcs/host
+
+include ../pypi.mk
+include $(INCLUDE_DIR)/package.mk
+include ../python3-package.mk
+
+define Package/python3-jsonschema-specifications
+ SECTION:=lang
+ CATEGORY:=Languages
+ SUBMENU:=Python
+ TITLE:=JSON Schema meta-schemas and vocabularies
+ URL:=https://github.com/python-jsonschema/jsonschema-specifications
+ DEPENDS:=+python3-light +python3-referencing
+endef
+
+define Package/python3-jsonschema-specifications/description
+JSON support files from the JSON Schema Specifications (metaschemas,
+vocabularies, etc.), packaged for runtime access from Python as a
+referencing-based Schema Registry.
+endef
+
+$(eval $(call Py3Package,python3-jsonschema-specifications))
+$(eval $(call BuildPackage,python3-jsonschema-specifications))
+$(eval $(call BuildPackage,python3-jsonschema-specifications-src))
--- /dev/null
+#!/bin/sh
+
+[ "$1" = python3-jsonschema-specifications ] || exit 0
+
+python3 - << 'EOF'
+
+from jsonschema_specifications import REGISTRY as SPECIFICATIONS
+
+DRAFT202012_DIALECT_URI = "https://json-schema.org/draft/2020-12/schema"
+assert SPECIFICATIONS.contents(DRAFT202012_DIALECT_URI) != ""
+
+EOF
include $(TOPDIR)/rules.mk
PKG_NAME:=python-jsonschema
-PKG_VERSION:=4.17.3
-PKG_RELEASE:=3
+PKG_VERSION:=4.19.1
+PKG_RELEASE:=1
PYPI_NAME:=jsonschema
-PKG_HASH:=0f864437ab8b6076ba6707453ef8f98a6a0d512a80e93f8abdb676f737ecb60d
+PKG_HASH:=ec84cc37cfa703ef7cd4928db24f9cb31428a5d0fa77747b8b51a847458e0bbf
PKG_MAINTAINER:=Javier Marcet <javier@marcet.info>
PKG_LICENSE:=MIT
CATEGORY:=Languages
SUBMENU:=Python
TITLE:=An implementation of JSON Schema validation
- URL:=https://github.com/Julian/jsonschema
- DEPENDS:=+python3-light +python3-attrs +python3-urllib \
- +python3-six +python3-pyrsistent +python3-setuptools
+ URL:=https://github.com/python-jsonschema/jsonschema
+ DEPENDS:= \
+ +python3-light \
+ +python3-decimal \
+ +python3-urllib \
+ +python3-uuid \
+ +python3-attrs \
+ +python3-jsonschema-specifications \
+ +python3-referencing \
+ +python3-rpds-py
endef
define Package/python3-jsonschema/description
--- /dev/null
+#!/bin/sh
+
+[ "$1" = python3-jsonschema ] || exit 0
+
+python3 - << 'EOF'
+
+from jsonschema import validate
+
+# A sample schema, like what we'd get from json.load()
+schema = {
+ "type" : "object",
+ "properties" : {
+ "price" : {"type" : "number"},
+ "name" : {"type" : "string"},
+ },
+}
+
+# If no exception is raised by validate(), the instance is valid.
+validate(instance={"name" : "Eggs", "price" : 34.99}, schema=schema)
+
+EOF
--- /dev/null
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=python-lru-dict
+PKG_VERSION:=1.3.0
+PKG_RELEASE:=1
+
+PYPI_NAME:=lru-dict
+PKG_HASH:=54fd1966d6bd1fcde781596cb86068214edeebff1db13a2cea11079e3fd07b6b
+
+PKG_MAINTAINER:=Timothy Ace <openwrt@timothyace.com>
+PKG_LICENSE:=MIT
+PKG_LICENSE_FILES:=LICENSE
+
+include ../pypi.mk
+include $(INCLUDE_DIR)/package.mk
+include ../python3-package.mk
+
+define Package/python3-lru-dict
+ SECTION:=lang
+ CATEGORY:=Languages
+ SUBMENU:=Python
+ TITLE:=An Dict like LRU container
+ URL:=https://github.com/amitdev/lru-dict
+ DEPENDS:=+python3-light
+endef
+
+define Package/python3-lru-dict/description
+A fixed size dict like container which evicts Least Recently Used (LRU) items
+once size limit is exceeded. There are many python implementations available
+which does similar things. This is a fast and efficient C implementation. LRU
+maximum capacity can be modified at run-time. If you are looking for pure
+python version, look elsewhere.
+endef
+
+$(eval $(call Py3Package,python3-lru-dict))
+$(eval $(call BuildPackage,python3-lru-dict))
+$(eval $(call BuildPackage,python3-lru-dict-src))
include $(TOPDIR)/rules.mk
PKG_NAME:=python-mako
-PKG_VERSION:=1.2.4
+PKG_VERSION:=1.3.0
PKG_RELEASE:=1
PYPI_NAME:=Mako
-PKG_HASH:=d60a3903dc3bb01a18ad6a89cdbe2e4eadc69c0bc8ef1e3773ba53d44c3f7a34
+PKG_HASH:=e3a9d388fd00e87043edbe8792f45880ac0114e9c4adc69f6e9bfb2c55e3b11b
PKG_MAINTAINER:=Jeffery To <jeffery.to@gmail.com>
PKG_LICENSE:=MIT
--- /dev/null
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=python-orjson
+PKG_VERSION:=3.9.10
+PKG_RELEASE:=1
+
+PYPI_NAME:=orjson
+PKG_HASH:=9ebbdbd6a046c304b1845e96fbcc5559cd296b4dfd3ad2509e33c4d9ce07d6a1
+
+PKG_MAINTAINER:=Timothy Ace <openwrt@timothyace.com>
+PKG_LICENSE:=Apache-2.0 MIT
+PKG_LICENSE_FILES:=LICENSE-APACHE LICENSE-MIT
+
+PKG_BUILD_DEPENDS:=python-maturin/host
+
+include ../pypi.mk
+include $(INCLUDE_DIR)/package.mk
+include ../python3-package.mk
+
+define Package/python3-orjson
+ SECTION:=lang
+ CATEGORY:=Languages
+ SUBMENU:=Python
+ TITLE:=Fast, correct Python JSON library
+ URL:=https://github.com/ijl/orjson
+ DEPENDS:= \
+ +python3-light \
+ $(RUST_ARCH_DEPENDS)
+endef
+
+define Package/python3-orjson/description
+Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy
+endef
+
+$(eval $(call Py3Package,python3-orjson))
+$(eval $(call BuildPackage,python3-orjson))
+$(eval $(call BuildPackage,python3-orjson-src))
include $(TOPDIR)/rules.mk
PKG_NAME:=python-poetry-core
-PKG_VERSION:=1.7.0
+PKG_VERSION:=1.8.1
PKG_RELEASE:=1
PYPI_NAME:=poetry-core
PYPI_SOURCE_NAME:=poetry_core
-PKG_HASH:=8f679b83bd9c820082637beca1204124d5d2a786e4818da47ec8acefd0353b74
+PKG_HASH:=67a76c671da2a70e55047cddda83566035b701f7e463b32a2abfeac6e2a16376
PKG_LICENSE:=MIT
PKG_LICENSE_FILES:=LICENSE
include $(TOPDIR)/rules.mk
PKG_NAME:=python-pyasn1
-PKG_VERSION:=0.5.0
+PKG_VERSION:=0.5.1
PKG_RELEASE:=1
PYPI_NAME:=pyasn1
-PKG_HASH:=97b7290ca68e62a832558ec3976f15cbf911bf5d7c7039d8b861c2a0ece69fde
+PKG_HASH:=6d391a96e59b23130a5cfa74d6fd7f388dbbe26cc8f1edf39fdddf08d9d6676c
PKG_LICENSE:=BSD-2-Clause
PKG_LICENSE_FILES:=LICENSE.rst
--- /dev/null
+#!/bin/sh
+
+[ "$1" = python3-pyasn1 ] || exit 0
+
+python3 - << 'EOF'
+
+from collections import OrderedDict
+
+from pyasn1.type import namedtype
+from pyasn1.type import tag
+from pyasn1.type import univ
+from pyasn1.codec.der.encoder import encode as derEncode
+from pyasn1.codec.der.decoder import decode as derDecode
+from pyasn1.codec.native.encoder import encode as nativeEncode
+from pyasn1.codec.native.decoder import decode as nativeDecode
+
+class Record(univ.Sequence):
+ componentType = namedtype.NamedTypes(
+ namedtype.NamedType('id', univ.Integer()),
+ namedtype.OptionalNamedType(
+ 'room', univ.Integer().subtype(
+ implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0)
+ )
+ ),
+ namedtype.DefaultedNamedType(
+ 'house', univ.Integer(0).subtype(
+ implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1)
+ )
+ )
+ )
+
+# encoding modifies the object (https://github.com/pyasn1/pyasn1/issues/53)
+# so test decoding before encoding
+
+record = Record()
+record['id'] = 123
+record['room'] = 321
+assert str(record) == 'Record:\n id=123\n room=321\n'
+
+substrate = b'0\x07\x02\x01{\x80\x02\x01A'
+
+received_record, _ = derDecode(substrate, asn1Spec=Record())
+assert received_record == record
+
+dict_record = nativeDecode({'id': 123, 'room': 321}, asn1Spec=Record())
+assert dict_record == record
+
+assert derEncode(record) == substrate
+assert nativeEncode(record) == OrderedDict([('id', 123), ('room', 321), ('house', 0)])
+
+EOF
--- /dev/null
+#
+# Copyright (C) 2023 Jeffery To
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=python-referencing
+PKG_VERSION:=0.30.2
+PKG_RELEASE:=1
+
+PYPI_NAME:=referencing
+PKG_HASH:=794ad8003c65938edcdbc027f1933215e0d0ccc0291e3ce20a4d87432b59efc0
+
+PKG_LICENSE:=MIT
+PKG_LICENSE_FILES:=COPYING
+PKG_MAINTAINER:=Jeffery To <jeffery.to@gmail.com>
+
+PKG_BUILD_DEPENDS:=python-hatchling/host python-hatch-vcs/host
+
+include ../pypi.mk
+include $(INCLUDE_DIR)/package.mk
+include ../python3-package.mk
+
+define Package/python3-referencing
+ SECTION:=lang
+ CATEGORY:=Languages
+ SUBMENU:=Python
+ TITLE:=JSON Referencing + Python
+ URL:=https://github.com/python-jsonschema/referencing
+ DEPENDS:= \
+ +python3-light \
+ +python3-email \
+ +python3-urllib \
+ +python3-attrs \
+ +python3-rpds-py
+endef
+
+define Package/python3-referencing/description
+An implementation-agnostic implementation of JSON reference resolution.
+endef
+
+$(eval $(call Py3Package,python3-referencing))
+$(eval $(call BuildPackage,python3-referencing))
+$(eval $(call BuildPackage,python3-referencing-src))
--- /dev/null
+#!/bin/sh
+
+[ "$1" = python3-referencing ] || exit 0
+
+python3 - << 'EOF'
+
+from referencing import Registry, Resource
+import referencing.jsonschema
+
+schema = Resource.from_contents( # Parse some contents into a 2020-12 JSON Schema
+ {
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "urn:example:a-202012-schema",
+ "$defs": {
+ "nonNegativeInteger": {
+ "$anchor": "nonNegativeInteger",
+ "type": "integer",
+ "minimum": 0,
+ },
+ },
+ }
+)
+registry = schema @ Registry() # Add the resource to a new registry
+
+# From here forward, this would usually be done within a library wrapping this one,
+# like a JSON Schema implementation
+resolver = registry.resolver()
+resolved = resolver.lookup("urn:example:a-202012-schema#nonNegativeInteger")
+assert resolved.contents == {
+ "$anchor": "nonNegativeInteger",
+ "type": "integer",
+ "minimum": 0,
+}
+
+EOF
--- /dev/null
+#
+# Copyright (C) 2023 Jeffery To
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=python-rpds-py
+PKG_VERSION:=0.10.6
+PKG_RELEASE:=1
+
+PYPI_NAME:=rpds-py
+PYPI_SOURCE_NAME:=rpds_py
+PKG_HASH:=4ce5a708d65a8dbf3748d2474b580d606b1b9f91b5c6ab2a316e0b0cf7a4ba50
+
+PKG_LICENSE:=MIT
+PKG_LICENSE_FILES:=LICENSE
+PKG_MAINTAINER:=Jeffery To <jeffery.to@gmail.com>
+
+PKG_BUILD_DEPENDS:=python-maturin/host
+
+include ../pypi.mk
+include $(INCLUDE_DIR)/package.mk
+include ../python3-package.mk
+
+define Package/python3-rpds-py
+ SECTION:=lang
+ CATEGORY:=Languages
+ SUBMENU:=Python
+ TITLE:=Bindings to Rust's persistent data structures
+ URL:=https://github.com/crate-py/rpds
+ DEPENDS:=+python3-light $(RUST_ARCH_DEPENDS)
+endef
+
+define Package/python3-rpds-py/description
+Python bindings to the Rust rpds crate for persistent data structures.
+endef
+
+$(eval $(call Py3Package,python3-rpds-py))
+$(eval $(call BuildPackage,python3-rpds-py))
+$(eval $(call BuildPackage,python3-rpds-py-src))
--- /dev/null
+#!/bin/sh
+
+[ "$1" = python3-rpds-py ] || exit 0
+
+python3 - << 'EOF'
+
+from rpds import HashTrieMap, HashTrieSet, List
+
+m = HashTrieMap({"foo": "bar", "baz": "quux"})
+assert m.insert("spam", 37) == HashTrieMap({"foo": "bar", "baz": "quux", "spam": 37})
+assert m.remove("foo") == HashTrieMap({"baz": "quux"})
+
+s = HashTrieSet({"foo", "bar", "baz", "quux"})
+assert s.insert("spam") == HashTrieSet({"foo", "bar", "baz", "quux", "spam"})
+assert s.remove("foo") == HashTrieSet({"bar", "baz", "quux"})
+
+L = List([1, 3, 5])
+assert L.push_front(-1) == List([-1, 1, 3, 5])
+assert L.rest == List([3, 5])
+
+EOF
include $(TOPDIR)/rules.mk
PKG_NAME:=python-setuptools
-PKG_VERSION:=68.2.2
+PKG_VERSION:=69.0.2
PKG_RELEASE:=1
PYPI_NAME:=setuptools
-PKG_HASH:=4ac1475276d2f1c48684874089fefcd83bd7162ddaafb81fac866ba0db282a87
+PKG_HASH:=735896e78a4742605974de002ac60562d286fa8051a7e2299445e8e8fbb01aa6
PKG_LICENSE:=MIT
PKG_LICENSE_FILES:=LICENSE
include $(TOPDIR)/rules.mk
PKG_NAME:=python-trove-classifiers
-PKG_VERSION:=2023.10.18
+PKG_VERSION:=2023.11.14
PKG_RELEASE:=1
PYPI_NAME:=trove-classifiers
-PKG_HASH:=2cdfcc7f31f7ffdd57666a9957296089ac72daad4d11ab5005060e5cd7e29939
+PKG_HASH:=64b5e78305a5de347f2cd7ec8c12d704a3ef0cb85cc10c0ca5f73488d1c201f8
PKG_LICENSE:=Apache-2.0
PKG_LICENSE_FILES:=LICENSE
include $(TOPDIR)/rules.mk
PKG_NAME:=python-twisted
-PKG_VERSION:=23.8.0
+PKG_VERSION:=23.10.0
PKG_RELEASE:=1
PYPI_NAME:=Twisted
PYPI_SOURCE_NAME:=twisted
-PKG_HASH:=3c73360add17336a622c0d811c2a2ce29866b6e59b1125fd6509b17252098a24
+PKG_HASH:=987847a0790a2c597197613686e2784fd54167df3a55d0fb17c8412305d76ce5
PKG_BUILD_DEPENDS:=libtirpc
--- a/pyproject.toml
+++ b/pyproject.toml
-@@ -150,7 +150,6 @@ ckeygen = "twisted.conch.scripts.ckeygen
+@@ -138,7 +138,6 @@ ckeygen = "twisted.conch.scripts.ckeygen
conch = "twisted.conch.scripts.conch:run"
mailmail = "twisted.mail.scripts.mailmail:run"
pyhtmlizer = "twisted.scripts.htmlizer:run"
--- a/pyproject.toml
+++ b/pyproject.toml
-@@ -194,6 +194,7 @@ exclude = [
+@@ -182,6 +182,7 @@ exclude = [
"*.pxi",
"*.pyx",
"build.bat",
--- /dev/null
+#
+# Copyright (C) 2023 Jeffery To
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=python-userpath
+PKG_VERSION:=1.9.1
+PKG_RELEASE:=1
+
+PYPI_NAME:=userpath
+PKG_HASH:=ce8176728d98c914b6401781bf3b23fccd968d1647539c8788c7010375e02796
+
+PKG_LICENSE:=MIT
+PKG_LICENSE_FILES:=LICENSE.txt
+PKG_MAINTAINER:=Jeffery To <jeffery.to@gmail.com>
+
+PKG_BUILD_DEPENDS:=python-hatchling/host
+
+include ../pypi.mk
+include $(INCLUDE_DIR)/package.mk
+include ../python3-package.mk
+
+define Package/python3-userpath
+ SECTION:=lang
+ CATEGORY:=Languages
+ SUBMENU:=Python
+ TITLE:=Cross-platform tool for modifying a user's PATH
+ URL:=https://github.com/ofek/userpath
+ DEPENDS:=+python3-light +python3-click +python3-psutil
+endef
+
+define Package/python3-userpath/description
+This is a tool for modifying a user's PATH.
+endef
+
+$(eval $(call Py3Package,python3-userpath))
+$(eval $(call BuildPackage,python3-userpath))
+$(eval $(call BuildPackage,python3-userpath-src))
--- /dev/null
+From 9175a0a97c7bc2eeb995e53d50a07be6a7e834f0 Mon Sep 17 00:00:00 2001
+From: Jeffery To <jeffery.to@gmail.com>
+Date: Thu, 9 Nov 2023 14:20:58 +0800
+Subject: [PATCH] Handle OSErrors when running show path commands
+
+Bash may not always be installed, for example on OpenWrt, and attempting
+to call the show path commands for Bash will cause a FileNotFoundError
+to be raised.
+
+This wraps the subprocess call with a try statement and returns the
+empty string in the case of an OSError.
+---
+ userpath/utils.py | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+--- a/userpath/utils.py
++++ b/userpath/utils.py
+@@ -30,8 +30,11 @@ def ensure_parent_dir_exists(path):
+
+
+ def get_flat_output(command, sep=os.pathsep, **kwargs):
+- process = subprocess.Popen(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kwargs)
+- output = process.communicate()[0].decode(locale.getpreferredencoding(False)).strip()
++ try:
++ process = subprocess.Popen(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kwargs)
++ output = process.communicate()[0].decode(locale.getpreferredencoding(False)).strip()
++ except OSError:
++ return ''
+
+ # We do this because the output may contain new lines.
+ lines = [line.strip() for line in output.splitlines()]
--- /dev/null
+From dffcc1c5823bcce10b420467db41e42ec41f4702 Mon Sep 17 00:00:00 2001
+From: Jeffery To <jeffery.to@gmail.com>
+Date: Thu, 9 Nov 2023 17:48:50 +0800
+Subject: [PATCH 1/2] Use Sh as base class for Bash and Zsh
+
+---
+ userpath/shells.py | 41 ++++++++++++++++++++++++++---------------
+ 1 file changed, 26 insertions(+), 15 deletions(-)
+
+--- a/userpath/shells.py
++++ b/userpath/shells.py
+@@ -12,24 +12,36 @@ class Shell(object):
+
+
+ class Sh(Shell):
+- def config(self, location, front=True):
++ name = 'sh'
++
++ def _config_contents(self, location, front=True):
+ head, tail = (location, '$PATH') if front else ('$PATH', location)
+ new_path = '{}{}{}'.format(head, pathsep, tail)
++ return 'export PATH="{}"'.format(new_path)
++
++ def config(self, location, front=True):
++ contents = self._config_contents(location, front=front)
++ return {path.join(self.home, '.profile'): contents}
+
+- return {path.join(self.home, '.profile'): 'PATH="{}"'.format(new_path)}
++ @classmethod
++ def _interactive_show_path_command(cls):
++ return [cls.name, '-i', '-c', 'echo $PATH']
++
++ @classmethod
++ def _interactive_login_show_path_command(cls):
++ return [cls.name, '-i', '-l', '-c', 'echo $PATH']
+
+ @classmethod
+ def show_path_commands(cls):
+ # TODO: Find out what file influences non-login shells. The issue may simply be our Docker setup.
+- return [['sh', '-i', '-l', '-c', 'echo $PATH']]
++ return [cls._interactive_login_show_path_command()]
+
+
+-class Bash(Shell):
+- def config(self, location, front=True):
+- head, tail = (location, '$PATH') if front else ('$PATH', location)
+- new_path = '{}{}{}'.format(head, pathsep, tail)
+- contents = 'export PATH="{}"'.format(new_path)
++class Bash(Sh):
++ name = 'bash'
+
++ def config(self, location, front=True):
++ contents = self._config_contents(location, front=front)
+ configs = {path.join(self.home, '.bashrc'): contents}
+
+ # https://github.com/ofek/userpath/issues/3#issuecomment-492491977
+@@ -50,7 +62,7 @@ class Bash(Shell):
+
+ @classmethod
+ def show_path_commands(cls):
+- return [['bash', '-i', '-c', 'echo $PATH'], ['bash', '-i', '-l', '-c', 'echo $PATH']]
++ return [cls._interactive_show_path_command(), cls._interactive_login_show_path_command()]
+
+
+ class Fish(Shell):
+@@ -88,18 +100,17 @@ class Xonsh(Shell):
+ return [['xonsh', '-i', '-c', command], ['xonsh', '-i', '--login', '-c', command]]
+
+
+-class Zsh(Shell):
+- def config(self, location, front=True):
+- head, tail = (location, '$PATH') if front else ('$PATH', location)
+- new_path = '{}{}{}'.format(head, pathsep, tail)
+- contents = 'export PATH="{}"'.format(new_path)
++class Zsh(Sh):
++ name = 'zsh'
+
++ def config(self, location, front=True):
++ contents = self._config_contents(location, front=front)
+ zdotdir = environ.get('ZDOTDIR', self.home)
+ return {path.join(zdotdir, '.zshrc'): contents, path.join(zdotdir, '.zprofile'): contents}
+
+ @classmethod
+ def show_path_commands(cls):
+- return [['zsh', '-i', '-c', 'echo $PATH'], ['zsh', '-i', '-l', '-c', 'echo $PATH']]
++ return [cls._interactive_show_path_command(), cls._interactive_login_show_path_command()]
+
+
+ SHELLS = {
--- /dev/null
+From 7823b9b39c486aedf830783329abdc3bd9664ba4 Mon Sep 17 00:00:00 2001
+From: Jeffery To <jeffery.to@gmail.com>
+Date: Thu, 9 Nov 2023 17:51:21 +0800
+Subject: [PATCH 2/2] Add support for ash (Almquist shell)
+
+---
+ tests/docker/debian | 2 +-
+ tests/test_ash.py | 65 +++++++++++++++++++++++++++++++++++++++++++++
+ userpath/shells.py | 5 ++++
+ 3 files changed, 71 insertions(+), 1 deletion(-)
+ create mode 100644 tests/test_ash.py
+
+--- a/tests/docker/debian
++++ b/tests/docker/debian
+@@ -2,7 +2,7 @@ ARG PYTHON_VERSION
+ FROM python:${PYTHON_VERSION}
+
+ RUN apt-get update \
+- && apt-get --no-install-recommends -y install fish zsh
++ && apt-get --no-install-recommends -y install ash fish zsh
+
+ COPY requirements.txt /
+ RUN pip install -r requirements.txt
+--- /dev/null
++++ b/tests/test_ash.py
+@@ -0,0 +1,65 @@
++import pytest
++import userpath
++
++from .utils import SKIP_WINDOWS_CI, get_random_path
++
++SHELL_NAME = 'ash'
++
++pytestmark = [SKIP_WINDOWS_CI, pytest.mark.ash]
++
++
++@pytest.mark.usefixtures('shell_test')
++class TestDebian(object):
++ DOCKERFILE = 'debian'
++
++ def test_prepend(self, request, shell_test):
++ if shell_test is None:
++ location = get_random_path()
++ assert not userpath.in_current_path(location)
++ assert userpath.prepend(location, check=True)
++ assert userpath.in_new_path(location)
++ assert userpath.need_shell_restart(location)
++ else:
++ process = shell_test(request.node.name)
++ stdout, stderr = process.communicate()
++
++ assert process.returncode == 0, (stdout + stderr).decode('utf-8')
++
++ def test_prepend_multiple(self, request, shell_test):
++ if shell_test is None:
++ locations = [get_random_path(), get_random_path()]
++ assert not userpath.in_current_path(locations)
++ assert userpath.prepend(locations, check=True)
++ assert userpath.in_new_path(locations)
++ assert userpath.need_shell_restart(locations)
++ else:
++ process = shell_test(request.node.name)
++ stdout, stderr = process.communicate()
++
++ assert process.returncode == 0, (stdout + stderr).decode('utf-8')
++
++ def test_append(self, request, shell_test):
++ if shell_test is None:
++ location = get_random_path()
++ assert not userpath.in_current_path(location)
++ assert userpath.append(location, check=True)
++ assert userpath.in_new_path(location)
++ assert userpath.need_shell_restart(location)
++ else:
++ process = shell_test(request.node.name)
++ stdout, stderr = process.communicate()
++
++ assert process.returncode == 0, (stdout + stderr).decode('utf-8')
++
++ def test_append_multiple(self, request, shell_test):
++ if shell_test is None:
++ locations = [get_random_path(), get_random_path()]
++ assert not userpath.in_current_path(locations)
++ assert userpath.append(locations, check=True)
++ assert userpath.in_new_path(locations)
++ assert userpath.need_shell_restart(locations)
++ else:
++ process = shell_test(request.node.name)
++ stdout, stderr = process.communicate()
++
++ assert process.returncode == 0, (stdout + stderr).decode('utf-8')
+--- a/userpath/shells.py
++++ b/userpath/shells.py
+@@ -37,6 +37,10 @@ class Sh(Shell):
+ return [cls._interactive_login_show_path_command()]
+
+
++class Ash(Sh):
++ name = 'ash'
++
++
+ class Bash(Sh):
+ name = 'bash'
+
+@@ -114,6 +118,7 @@ class Zsh(Sh):
+
+
+ SHELLS = {
++ 'ash': Ash,
+ 'bash': Bash,
+ 'fish': Fish,
+ 'sh': Sh,
--- /dev/null
+#!/bin/sh
+
+[ "$1" = python3-userpath ] || exit 0
+
+userpath --version | grep -Fx "userpath, version $PKG_VERSION"
include $(TOPDIR)/rules.mk
PKG_NAME:=python-wheel
-PKG_VERSION:=0.41.2
+PKG_VERSION:=0.42.0
PKG_RELEASE:=1
PYPI_NAME:=wheel
-PKG_HASH:=0c5ac5ff2afb79ac23ab82bab027a0be7b5dbcf2e54dc50efe4bf507de1f7985
+PKG_HASH:=c45be39f7882c9d34243236f2d63cbd58039e360f85d0913425fbd7ceea617a8
PKG_LICENSE:=MIT
PKG_LICENSE_FILES:=LICENSE.txt
include $(TOPDIR)/rules.mk
PKG_NAME:=rust
-PKG_VERSION:=1.73.0
-PKG_RELEASE:=2
+PKG_VERSION:=1.74.0
+PKG_RELEASE:=1
PKG_SOURCE:=rustc-$(PKG_VERSION)-src.tar.gz
PKG_SOURCE_URL:=https://static.rust-lang.org/dist/
-PKG_HASH:=96d62e6d1f2d21df7ac8acb3b9882411f9e7c7036173f7f2ede9e1f1f6b1bb3a
+PKG_HASH:=882b584bc321c5dcfe77cdaa69f277906b936255ef7808fcd5c7492925cf1049
HOST_BUILD_DIR:=$(BUILD_DIR)/host/rustc-$(PKG_VERSION)-src
PKG_MAINTAINER:=Luca Barbato <lu_zero@luminem.org>
--- a/src/bootstrap/Cargo.lock
+++ b/src/bootstrap/Cargo.lock
-@@ -434,9 +434,9 @@ dependencies = [
+@@ -424,9 +424,9 @@ dependencies = [
[[package]]
name = "lzma-sys"
dependencies = [
"cc",
"libc",
-@@ -903,9 +903,9 @@ dependencies = [
+@@ -871,9 +871,9 @@ dependencies = [
[[package]]
name = "xz2"
--- a/src/bootstrap/bootstrap.py
+++ b/src/bootstrap/bootstrap.py
-@@ -546,7 +546,7 @@ class RustBuild(object):
+@@ -557,7 +557,7 @@ class RustBuild(object):
shutil.rmtree(bin_root)
key = self.stage0_compiler.date
os.makedirs(rustc_cache)
--- a/src/bootstrap/download.rs
+++ b/src/bootstrap/download.rs
-@@ -202,7 +202,13 @@ impl Config {
+@@ -211,7 +211,13 @@ impl Config {
Some(other) => panic!("unsupported protocol {other} in {url}"),
None => panic!("no protocol in {url}"),
}
}
fn download_http_with_retries(&self, tempfile: &Path, url: &str, help_on_error: &str) {
-@@ -520,7 +526,10 @@ impl Config {
+@@ -529,7 +535,10 @@ impl Config {
key: &str,
destination: &str,
) {
let cache_dir = cache_dst.join(key);
if !cache_dir.exists() {
t!(fs::create_dir_all(&cache_dir));
-@@ -647,7 +656,10 @@ download-rustc = false
+@@ -656,7 +665,10 @@ download-rustc = false
let llvm_assertions = self.llvm_assertions;
let cache_prefix = format!("llvm-{llvm_sha}-{llvm_assertions}");
-This patch bumps all libc dependencies and checksums to 0.2.146, which includes the fix for musl 1.2.4.
+This patch bumps all libc dependencies and checksums to 0.2.147, which includes the fix for musl 1.2.4.
---- a/vendor/addr2line-0.20.0/Cargo.lock
-+++ b/vendor/addr2line-0.20.0/Cargo.lock
-@@ -246,9 +246,9 @@ checksum = "e2abad23fbc42b3700f2f279844d
+--- a/vendor/addr2line-0.19.0/Cargo.lock
++++ b/vendor/addr2line-0.19.0/Cargo.lock
+@@ -235,9 +235,9 @@ checksum = "e2abad23fbc42b3700f2f279844d
[[package]]
name = "libc"
--version = "0.2.141"
-+version = "0.2.146"
+-version = "0.2.126"
++version = "0.2.147"
source = "registry+https://github.com/rust-lang/crates.io-index"
--checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5"
-+checksum = "f92be4933c13fd498862a9e02a3055f8a8d9c039ce33db97306fd5a6caa7f29b"
+-checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836"
++checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
[[package]]
- name = "libtest-mimic"
+ name = "memchr"
--- a/vendor/backtrace-0.3.67/Cargo.lock
+++ b/vendor/backtrace-0.3.67/Cargo.lock
@@ -64,9 +64,9 @@ checksum = "dec7af912d60cdbd3677c1af9352
[[package]]
name = "libc"
-version = "0.2.138"
-+version = "0.2.146"
++version = "0.2.147"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8"
-+checksum = "f92be4933c13fd498862a9e02a3055f8a8d9c039ce33db97306fd5a6caa7f29b"
++checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
[[package]]
name = "libloading"
---- a/vendor/bstr/Cargo.lock
-+++ b/vendor/bstr/Cargo.lock
-@@ -34,9 +34,9 @@ dependencies = [
-
- [[package]]
- name = "libc"
--version = "0.2.138"
-+version = "0.2.146"
- source = "registry+https://github.com/rust-lang/crates.io-index"
--checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8"
-+checksum = "f92be4933c13fd498862a9e02a3055f8a8d9c039ce33db97306fd5a6caa7f29b"
-
- [[package]]
- name = "memchr"
--- a/vendor/cranelift-jit/Cargo.lock
+++ b/vendor/cranelift-jit/Cargo.lock
@@ -224,9 +224,9 @@ dependencies = [
[[package]]
name = "libc"
-version = "0.2.141"
-+version = "0.2.146"
++version = "0.2.147"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5"
-+checksum = "f92be4933c13fd498862a9e02a3055f8a8d9c039ce33db97306fd5a6caa7f29b"
++checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
[[package]]
name = "log"
[[package]]
name = "libc"
-version = "0.2.141"
-+version = "0.2.146"
++version = "0.2.147"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5"
-+checksum = "f92be4933c13fd498862a9e02a3055f8a8d9c039ce33db97306fd5a6caa7f29b"
++checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
[[package]]
name = "num_cpus"
[[package]]
name = "libc"
-version = "0.2.140"
-+version = "0.2.146"
++version = "0.2.147"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c"
-+checksum = "f92be4933c13fd498862a9e02a3055f8a8d9c039ce33db97306fd5a6caa7f29b"
++checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
[[package]]
name = "lindera"
[[package]]
name = "libc"
-version = "0.2.140"
-+version = "0.2.146"
++version = "0.2.147"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c"
-+checksum = "f92be4933c13fd498862a9e02a3055f8a8d9c039ce33db97306fd5a6caa7f29b"
++checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
[[package]]
name = "lock_api"
[[package]]
name = "libc"
-version = "0.2.141"
-+version = "0.2.146"
++version = "0.2.147"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5"
-+checksum = "f92be4933c13fd498862a9e02a3055f8a8d9c039ce33db97306fd5a6caa7f29b"
++checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
[[package]]
name = "litemap"
[[package]]
name = "libc"
-version = "0.2.140"
-+version = "0.2.146"
++version = "0.2.147"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c"
-+checksum = "f92be4933c13fd498862a9e02a3055f8a8d9c039ce33db97306fd5a6caa7f29b"
++checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
[[package]]
name = "libffi"
---- a/vendor/terminal_size/Cargo.lock
-+++ b/vendor/terminal_size/Cargo.lock
-@@ -47,9 +47,9 @@ dependencies = [
-
- [[package]]
- name = "libc"
--version = "0.2.140"
-+version = "0.2.146"
- source = "registry+https://github.com/rust-lang/crates.io-index"
--checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c"
-+checksum = "f92be4933c13fd498862a9e02a3055f8a8d9c039ce33db97306fd5a6caa7f29b"
-
- [[package]]
- name = "linux-raw-sys"
--- a/vendor/tracing-tree/Cargo.lock
+++ b/vendor/tracing-tree/Cargo.lock
-@@ -100,9 +100,9 @@ checksum = "e2abad23fbc42b3700f2f279844d
+@@ -296,9 +296,9 @@ checksum = "e2abad23fbc42b3700f2f279844d
[[package]]
name = "libc"
-version = "0.2.141"
-+version = "0.2.146"
++version = "0.2.147"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5"
-+checksum = "f92be4933c13fd498862a9e02a3055f8a8d9c039ce33db97306fd5a6caa7f29b"
++checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
[[package]]
- name = "log"
+ name = "linux-raw-sys"
For more information please see the avahi documentation.
endef
-define Package/libavahi-compat-libdnssd
- $(call Package/avahi/Default)
- SECTION:=libs
- CATEGORY:=Libraries
- VARIANT:=dbus
- DEPENDS:=+libavahi-client
- TITLE+= (libdnssd)
-endef
-
-define Package/libavahi-compat-libdnssd/description
-$(call Package/avahi/Default/description)
- .
- This packages adds the libavahi-compat-libdnssd library.
- It also automatically adds the required libavahi-client package.
- For more information please see the avahi documentation.
-endef
-
define Package/avahi-utils
$(call Package/avahi/Default)
SUBMENU:=IP Addresses and Names
--with-autoipd-group=nogroup
ifeq ($(BUILD_VARIANT),dbus)
-ifneq ($(CONFIG_PACKAGE_libavahi-compat-libdnssd),)
-CONFIGURE_ARGS += \
- --enable-compat-libdns_sd
-endif
CONFIGURE_ARGS += \
--enable-dbus
else
$(CP) $(PKG_INSTALL_DIR)/usr/include/* $(1)/usr/include/
$(INSTALL_DIR) $(1)/usr/lib
$(CP) $(PKG_INSTALL_DIR)/usr/lib/libavahi-* $(1)/usr/lib/
-ifneq ($(CONFIG_PACKAGE_libavahi-compat-libdnssd),)
-ifeq ($(BUILD_VARIANT),dbus)
- $(CP) $(PKG_INSTALL_DIR)/usr/lib/libdns_sd* $(1)/usr/lib/
-endif
-endif
$(INSTALL_DIR) $(1)/usr/lib/pkgconfig
$(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/* $(1)/usr/lib/pkgconfig/
endef
$(CP) $(PKG_INSTALL_DIR)/usr/lib/libavahi-client.so.* $(1)/usr/lib/
endef
-define Package/libavahi-compat-libdnssd/install
- $(INSTALL_DIR) $(1)/usr/lib
- $(CP) $(PKG_INSTALL_DIR)/usr/lib/libdns_sd.so* $(1)/usr/lib/
-endef
-
define Package/avahi-utils/install
$(INSTALL_DIR) $(1)/usr/bin
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/* $(1)/usr/bin/
endef
$(eval $(call BuildPackage,libavahi-client))
-$(eval $(call BuildPackage,libavahi-compat-libdnssd))
$(eval $(call BuildPackage,avahi-utils))
$(eval $(call BuildPackage,libavahi-dbus-support))
$(eval $(call BuildPackage,libavahi-nodbus-support))
PKG_LICENSE:=BSD-3-Clause
PKG_LICENSE_FILES:=LICENSE.md
PKG_VERSION:=0.9.7
-PKG_RELEASE:=4
+PKG_RELEASE:=5
# Use this for official releasees
PKG_HASH:=12b7b046004db29317b7b937dc794abf719c400ba3115af8d41849127b562681
--- /dev/null
+From 19fe46ecb796c0d30d66dd7e7038fd7f2d6f9bf4 Mon Sep 17 00:00:00 2001
+From: Florian Lindner <florian.lindner@student.tuwien.ac.at>
+Date: Thu, 8 Jun 2023 16:55:34 +0200
+Subject: [PATCH] bindings: include <cstdint> in key.hpp for uint8_t
+
+---
+ src/bindings/cpp/include/key.hpp | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/src/bindings/cpp/include/key.hpp
++++ b/src/bindings/cpp/include/key.hpp
+@@ -10,6 +10,7 @@
+ #define ELEKTRA_KEY_HPP
+
+ #include <cstdarg>
++#include <cstdint>
+ #include <cstring>
+ #include <functional>
+ #include <locale>
include $(TOPDIR)/rules.mk
PKG_NAME:=icu4c
-MAJOR_VERSION:=73
-MINOR_VERSION:=2
+MAJOR_VERSION:=74
+MINOR_VERSION:=1
PKG_VERSION:=$(MAJOR_VERSION).$(MINOR_VERSION)
PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-$(MAJOR_VERSION)_$(MINOR_VERSION)-src.tgz
PKG_SOURCE_URL:=https://github.com/unicode-org/icu/releases/download/release-$(MAJOR_VERSION)-$(MINOR_VERSION)
-PKG_HASH:=818a80712ed3caacd9b652305e01afc7fa167e6f2e94996da44b90c2ab604ce1
+PKG_HASH:=86ce8e60681972e60e4dcb2490c697463fcec60dd400a5f9bffba26d0b52b8d0
PKG_LICENSE:=ICU
PKG_LICENSE_FILES:=LICENSE
include $(TOPDIR)/rules.mk
PKG_NAME:=libdaq3
-PKG_VERSION:=3.0.12
+PKG_VERSION:=3.0.13
PKG_RELEASE:=1
PKG_MAINTAINER:=W. Michael Petullo <mike@flyn.org>
PKG_SOURCE:=libdaq-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://codeload.github.com/snort3/libdaq/tar.gz/v$(PKG_VERSION)?
-PKG_HASH:=dedfdb88de151d61009bdb365322853687b1add4adec248952d2a93b70f584af
+PKG_HASH:=3a48b934bc45a1fe44b3887185d33a76a042c1d10aa177e3e7c417d83da67213
PKG_BUILD_DIR:=$(BUILD_DIR)/libdaq-$(PKG_VERSION)
PKG_FIXUP:=autoreconf
include $(TOPDIR)/rules.mk
PKG_NAME:=libnpupnp
-PKG_VERSION:=5.0.0
-PKG_RELEASE:=2
+PKG_VERSION:=5.1.2
+PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://www.lesbonscomptes.com/upmpdcli/downloads
-PKG_HASH:=2e5648cf180a425ef57b8c9c0d9dbd77f0314487ea0e0a85ebc6c3ef87cab05b
+PKG_HASH:=c1be8b2f654ef520791fbfaf13006fdd84522e6480a3126006e40caceea23552
PKG_MAINTAINER:=
PKG_LICENSE:=LGPL-2.1-or-later
PKG_LICENSE_FILES:=COPYING
-PKG_INSTALL:=1
-PKG_BUILD_PARALLEL:=1
PKG_BUILD_DEPENDS:=libmicrohttpd
-PKG_BUILD_FLAGS:=lto
include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/meson.mk
define Package/libnpupnp
SECTION:=libs
branch (around 1.6.25).
endef
+MESON_OPTIONS += \
+ -Db_lto=true
+
define Build/InstallDev
$(INSTALL_DIR) $(1)/usr/include/npupnp
$(CP) $(PKG_INSTALL_DIR)/usr/include/npupnp/* $(1)/usr/include/npupnp/
include $(TOPDIR)/rules.mk
PKG_NAME:=libupnpp
-PKG_VERSION:=0.22.2
+PKG_VERSION:=0.24.1
PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://www.lesbonscomptes.com/upmpdcli/downloads
-PKG_HASH:=90338c19383333fd4eeec8a866a8c4add1754ef9a6a720ddd9af97e6754ff849
+PKG_HASH:=f09d5162f237bcb971ef4bbd45de9e93a073d96555cd691374eb1a3f338b2d0b
PKG_MAINTAINER:=
PKG_LICENSE:=LGPL-2.1-or-later
include $(TOPDIR)/rules.mk
PKG_NAME:=liburing
-PKG_VERSION:=2.4
+PKG_VERSION:=2.5
PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
PKG_SOURCE_URL:=https://git.kernel.dk/cgit/liburing/snapshot
-PKG_HASH:=ca260e7a5820c2d0e737ec1e9b999f10776dbe84a169a02a0eff10c8eeaf3394
+PKG_HASH:=319ff9096a5655362a9741c5145b45494db810e38679a1de82e2f440c17181a6
PKG_MAINTAINER:=Christian Lachner <gladiac@gmail.com>
PKG_LICENSE:=MIT
include $(TOPDIR)/rules.mk
PKG_NAME:=libzip
-PKG_VERSION:=1.9.2
+PKG_VERSION:=1.10.1
PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
PKG_SOURCE_URL:=https://libzip.org/download/
-PKG_HASH:=c93e9852b7b2dc931197831438fee5295976ee0ba24f8524a8907be5c2ba5937
+PKG_HASH:=dc3c8d5b4c8bbd09626864f6bcf93de701540f761d76b85d7c7d710f4bd90318
PKG_MAINTAINER:=Michael Heimpold <mhei@heimpold.de>
+++ /dev/null
---- a/lib/zipint.h
-+++ b/lib/zipint.h
-@@ -180,8 +180,10 @@ zip_source_t *zip_source_pkware_decode(z
- zip_source_t *zip_source_pkware_encode(zip_t *, zip_source_t *, zip_uint16_t, int, const char *);
- int zip_source_remove(zip_source_t *);
- zip_int64_t zip_source_supports(zip_source_t *src);
-+#ifdef HAVE_CRYPTO
- zip_source_t *zip_source_winzip_aes_decode(zip_t *, zip_source_t *, zip_uint16_t, int, const char *);
- zip_source_t *zip_source_winzip_aes_encode(zip_t *, zip_source_t *, zip_uint16_t, int, const char *);
-+#endif
- zip_source_t *zip_source_buffer_with_attributes(zip_t *za, const void *data, zip_uint64_t len, int freep, zip_file_attributes_t *attributes);
- zip_source_t *zip_source_buffer_with_attributes_create(const void *data, zip_uint64_t len, int freep, zip_file_attributes_t *attributes, zip_error_t *error);
-
+++ /dev/null
-#
-# Copyright (C) 2016 Ben Rosser <rosser.bjr@gmail.com>
-#
-# This is free software, licensed under the GNU General Public License v2.
-# See /LICENSE for more information.
-#
-
-include $(TOPDIR)/rules.mk
-
-PKG_NAME:=quasselc
-PKG_SOURCE_DATE:=2017-01-11
-PKG_SOURCE_VERSION:=a0a1e6bd87d3eac68b5369972d1c2035cfe47e94
-PKG_RELEASE:=4
-
-PKG_SOURCE:=$(PKG_NAME)-$(PKG_SOURCE_DATE).tar.gz
-PKG_SOURCE_URL:=https://codeload.github.com/phhusson/QuasselC/tar.gz/$(PKG_SOURCE_VERSION)?
-PKG_HASH:=fe7b48a13c0e6dad81cdae18069d4f5607af64d73a3201f42d79548170dde510
-PKG_BUILD_DIR:=$(BUILD_DIR)/QuasselC-$(PKG_SOURCE_VERSION)
-
-PKG_MAINTAINER:=Ben Rosser <rosser.bjr@gmail.com>
-PKG_LICENSE:=LGPL-3.0
-PKG_LICENSE_FILES:=COPYING.LESSER
-
-PKG_BUILD_PARALLEL:=1
-PKG_INSTALL:=1
-
-include $(INCLUDE_DIR)/package.mk
-include $(INCLUDE_DIR)/nls.mk
-
-MAKE_FLAGS += prefix=$(STAGING_DIR)/usr libdir=$(STAGING_DIR)/usr/lib includedir=$(STAGING_DIR)/usr/include
-MAKE_INSTALL_FLAGS += prefix=/usr libdir=/usr/lib includedir=/usr/include
-
-define Package/quasselc
- SECTION:=libs
- CATEGORY:=Libraries
- DEPENDS:=+glib2
- SUBMENU:=Instant Messaging
- URL:=https://github.com/phhusson/QuasselC
- TITLE:=API to access a Quassel Core in pure C
-endef
-
-define Package/quasselc/description
- An implementation of the Quassel protocol in pure C.
-endef
-
-define Build/InstallDev
- $(INSTALL_DIR) $(1)/usr/include/quasselc
- $(CP) $(PKG_INSTALL_DIR)/usr/include/quasselc/* $(1)/usr/include/quasselc/
-
- $(INSTALL_DIR) $(1)/usr/lib
- $(CP) $(PKG_INSTALL_DIR)/usr/lib/libquasselc.so* $(1)/usr/lib/
- $(LN) libquasselc.so.0 $(1)/usr/lib/libquasselc.so
-
- $(INSTALL_DIR) $(1)/usr/lib/pkgconfig
- $(CP) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/quasselc.pc $(1)/usr/lib/pkgconfig/
-endef
-
-define Package/quasselc/install
- $(INSTALL_DIR) $(1)/usr/lib
- $(CP) $(PKG_INSTALL_DIR)/usr/lib/libquasselc.so* $(1)/usr/lib/
-endef
-
-$(eval $(call BuildPackage,quasselc))
+++ /dev/null
---- a/Makefile
-+++ b/Makefile
-@@ -2,11 +2,11 @@ prefix ?= /usr/local
- libdir ?= $(prefix)/lib
- includedir ?= $(prefix)/include
-
--CFLAGS:=-Wall -g -Wextra $(shell pkg-config glib-2.0 --cflags) -Wswitch-enum -std=gnu11 -O2 -fPIC
-+CFLAGS+=-Wall -g -Wextra $(shell pkg-config glib-2.0 --cflags) -Wswitch-enum -std=gnu11 -fPIC
- SO_VERSION = 0
- VERSION = 0
- INSTALL = install
--LDLIBS:=$(shell pkg-config glib-2.0 --libs) -lz
-+LDFLAGS+=$(shell pkg-config glib-2.0 --libs) -lz
-
- BOTLIBS := -Wl,-rpath,.
-
-@@ -15,10 +15,10 @@ lib_objects=setters.o getters.o main.o c
- all: bot libquasselc.so.$(VERSION) quasselc.pc
-
- libquasselc.so.$(VERSION): $(lib_objects)
-- $(CC) -shared -o $@ -Wl,-soname,libquasselc.so.$(SO_VERSION) $^ $(LDLIBS)
-+ $(CC) -shared -o $@ -Wl,-soname,libquasselc.so.$(SO_VERSION) $^ $(LDFLAGS)
-
- bot: bot.o display.o libquasselc.so.$(VERSION)
-- $(CC) -o $@ $^ $(LDLIBS) $(BOTLIBS)
-+ $(CC) -o $@ $^ $(LDFLAGS) $(BOTLIBS)
-
- clean:
- rm -f *.o bot libquasselc.so.$(VERSION) quasselc.pc
include $(TOPDIR)/rules.mk
PKG_NAME:=yt-dlp
-PKG_VERSION:=2023.3.4
-PKG_RELEASE:=2
+PKG_VERSION:=2023.11.16
+PKG_RELEASE:=1
PYPI_NAME:=yt-dlp
-PKG_HASH:=265d5da97a76c15d7d9a4088a67b78acd5dcf6f8cfd8257c52f581ff996ff515
+PKG_HASH:=f0ccdaf12e08b15902601a4671c7ab12906d7b11de3ae75fa6506811c24ec5da
PKG_MAINTAINER:=Michal Vasilek <michal.vasilek@nic.cz>
PKG_LICENSE:=Unlicense
include $(TOPDIR)/rules.mk
PKG_NAME:=acme-acmesh
-PKG_VERSION:=3.0.6
+PKG_VERSION:=3.0.7
PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://codeload.github.com/acmesh-official/acme.sh/tar.gz/$(PKG_VERSION)?
-PKG_HASH:=4a8e44c27e2a8f01a978e8d15add8e9908b83f9b1555670e49a9b769421f5fa6
+PKG_HASH:=abd446d6bd45d0b44dca1dcbd931348797a3f82d1ed6fb171472eaf851a8d849
PKG_BUILD_DIR:=$(BUILD_DIR)/acme.sh-$(PKG_VERSION)
PKG_MAINTAINER:=Toke Høiland-Jørgensen <toke@toke.dk>
-# Copyright 2023 Stan Grishin (stangri@melmac.ca)
+# Copyright 2023 MOSSDeF, Stan Grishin (stangri@melmac.ca)
# TLD optimization written by Dirk Brenken (dev@brenken.org)
# This is free software, licensed under the GNU General Public License v3.
include $(TOPDIR)/rules.mk
PKG_NAME:=adblock-fast
-PKG_VERSION:=1.0.0
-PKG_RELEASE:=7
+PKG_VERSION:=1.0.1
+PKG_RELEASE:=6
PKG_MAINTAINER:=Stan Grishin <stangri@melmac.ca>
PKG_LICENSE:=GPL-3.0-or-later
option parallel_downloads '1'
option pause_timeout '20'
option procd_trigger_wan6 '0'
+ option procd_boot_delay '0'
option procd_boot_wan_timeout '60'
option verbosity '2'
#!/bin/sh /etc/rc.common
# Copyright 2023 MOSSDeF, Stan Grishin (stangri@melmac.ca)
-# shellcheck disable=SC1091,SC2015,SC2016,SC3037,SC3043,SC3045,SC3057,SC3060
+# shellcheck disable=SC3043
# shellcheck disable=SC2034
START=94
USE_PROCD=1
LC_ALL=C
-if type extra_command 1>/dev/null 2>&1; then
- extra_command 'allow' 'Allows domain in current block-list and config'
- extra_command 'check' 'Checks if specified domain is found in current block-list'
- extra_command 'dl' 'Force-downloads all enabled block-list'
- extra_command 'killcache' 'Delete all cached files'
- extra_command 'pause' 'Pauses AdBlocking for specified number of seconds (default: 60)'
- extra_command 'sizes' 'Displays the file-sizes of enabled block-lists'
- extra_command 'version' 'Show version information'
-else
-# shellcheck disable=SC2034
- EXTRA_COMMANDS='allow check dl killcache pause sizes status_service version'
-# shellcheck disable=SC2034
- EXTRA_HELP=' allow Allows domain(s) in current block-list and config
- check Checks if specified domain is found in current block-list
- dl Force-downloads all enabled block-list
- pause Pauses AdBlocking for specified number of seconds (default: 60)
- sizes Displays the file-sizes of enabled block-lists'
-fi
-
readonly PKG_VERSION='dev-test'
readonly packageName='adblock-fast'
readonly serviceName="$packageName $PKG_VERSION"
readonly dnsmasqFileFilter='\|^server=/[[:alnum:]_.-].*/|!d;s|server=/||;s|/.*$||'
readonly dnsmasq2FileFilter='\|^local=/[[:alnum:]_.-].*/|!d;s|local=/||;s|/.*$||'
readonly dnsmasq3FileFilter='\|^address=/[[:alnum:]_.-].*/|!d;s|address=/||;s|/.*$||'
+readonly _ERROR_='\033[0;31mERROR\033[0m'
readonly _OK_='\033[0;32m\xe2\x9c\x93\033[0m'
readonly _FAIL_='\033[0;31m\xe2\x9c\x97\033[0m'
readonly __OK__='\033[0;32m[\xe2\x9c\x93]\033[0m'
readonly __FAIL__='\033[0;31m[\xe2\x9c\x97]\033[0m'
-readonly _ERROR_='\033[0;31mERROR\033[0m'
readonly _WARNING_='\033[0;33mWARNING\033[0m'
# shellcheck disable=SC2155
readonly ipset="$(command -v ipset)"
allowed_url=
blocked_url=
+# shellcheck disable=SC1091
+. /lib/functions.sh
+# shellcheck disable=SC1091
+. /lib/functions/network.sh
+# shellcheck disable=SC1091
+. /usr/share/libubox/jshn.sh
+
+append_newline() { is_newline_ending "$1" || echo '' >> "$1"; }
+check_ipset() { { command -v ipset && /usr/sbin/ipset help hash:net; } >/dev/null 2>&1; }
+check_nft() { command -v nft >/dev/null 2>&1; }
+check_dnsmasq() { command -v dnsmasq >/dev/null 2>&1; }
+check_dnsmasq_ipset() {
+ local o;
+ check_dnsmasq || return 1
+ o="$(dnsmasq -v 2>/dev/null)"
+ check_ipset && ! echo "$o" | grep -q 'no-ipset' && echo "$o" | grep -q 'ipset'
+}
+check_dnsmasq_nftset() {
+ local o;
+ check_dnsmasq || return 1
+ o="$(dnsmasq -v 2>/dev/null)"
+ check_nft && ! echo "$o" | grep -q 'no-nftset' && echo "$o" | grep -q 'nftset'
+}
+check_unbound() { command -v unbound >/dev/null 2>&1; }
debug() { local i j; for i in "$@"; do eval "j=\$$i"; echo "${i}: ${j} "; done; }
+dnsmasq_hup() { killall -q -s HUP dnsmasq; }
+dnsmasq_kill() { killall -q -s KILL dnsmasq; }
+dnsmasq_restart() { /etc/init.d/dnsmasq restart >/dev/null 2>&1; }
+is_enabled() { uci -q get "${1}.config.enabled"; }
+is_integer() {
+ case "$1" in
+ (*[!0123456789]*) return 1;;
+ ('') return 1;;
+ (*) return 0;;
+ esac
+}
+is_greater() { test "$(printf '%s\n' "$@" | sort -V | head -n 1)" != "$1"; }
+is_greater_or_equal() { test "$(printf '%s\n' "$@" | sort -V | head -n 1)" = "$2"; }
+# shellcheck disable=SC3057
+is_https_url() { [ "${1:0:8}" = "https://" ]; }
+is_newline_ending() { [ "$(tail -c1 "$1" | wc -l)" -ne '0' ]; }
+is_present() { command -v "$1" >/dev/null 2>&1; }
+is_running() {
+ local i j
+ i="$(json 'get' 'status')"
+ j="$(ubus_get_data 'status')"
+ if [ "$i" = 'statusStopped' ] || [ -z "${i}${j}" ]; then
+ return 1
+ else
+ return 0
+ fi
+}
+ipset() { "$ipset" "$@" >/dev/null 2>&1; }
+get_version() { grep -m1 -A2 -w "^Package: $1$" /usr/lib/opkg/status | sed -n 's/Version: //p'; }
+get_ram_free() { ubus call system info | jsonfilter -e '@.memory.free'; }
+get_ram_total() { ubus call system info | jsonfilter -e '@.memory.total'; }
+led_on(){ if [ -n "${1}" ] && [ -e "${1}/trigger" ]; then echo 'default-on' > "${1}/trigger" 2>&1; fi; }
+led_off(){ if [ -n "${1}" ] && [ -e "${1}/trigger" ]; then echo 'none' > "${1}/trigger" 2>&1; fi; }
+logger() { /usr/bin/logger -t "$packageName" "$@"; }
+nft() { "$nft" "$@" >/dev/null 2>&1; }
+output_ok() { output 1 "$_OK_"; output 2 "$__OK__\\n"; }
+output_okn() { output 1 "$_OK_\\n"; output 2 "$__OK__\\n"; }
+output_fail() { output 1 "$_FAIL_"; output 2 "$__FAIL__\\n"; }
+output_failn() { output 1 "$_FAIL_\\n"; output 2 "$__FAIL__\\n"; }
+print_json_bool() { json_init; json_add_boolean "$1" "$2"; json_dump; json_cleanup; }
+print_json_int() { json_init; json_add_int "$1" "$2"; json_dump; json_cleanup; }
+print_json_string() { json_init; json_add_string "$1" "$2"; json_dump; json_cleanup; }
+sanitize_dir() { [ -d "$(readlink -fn "$1")" ] && readlink -fn "$1"; }
+str_contains() { test "$1" != "$(str_replace "$1" "$2" '')"; }
+str_contains_word() { echo "$1" | grep -q -w "$2"; }
+# shellcheck disable=SC2018,SC2019
+str_to_lower() { echo "$1" | tr 'A-Z' 'a-z'; }
+# shellcheck disable=SC2018,SC2019
+str_to_upper() { echo "$1" | tr 'a-z' 'A-Z'; }
+str_replace() { printf "%b" "$1" | sed -e "s/$(printf "%b" "$2")/$(printf "%b" "$3")/g"; }
+ubus_get_data() { ubus call service list "{ 'name': '$packageName' }" | jsonfilter -e "@['${packageName}'].instances.main.data.${1}"; }
+ubus_get_ports() { ubus call service list "{ 'name': '$packageName' }" | jsonfilter -e "@['${packageName}'].instances.main.data.firewall.*.dest_port"; }
+unbound_restart() { /etc/init.d/unbound restart >/dev/null 2>&1; }
+
+json() {
+# shellcheck disable=SC2034
+ local action="$1" param="$2" value="$3"
+ shift 3
+# shellcheck disable=SC2124
+ local extras="$@" line
+ local status message error stats
+ local reload restart curReload curRestart ret i
+ if [ -s "$jsonFile" ]; then
+ json_load_file "$jsonFile" 2>/dev/null
+ json_select 'data' 2>/dev/null
+ for i in status message error stats reload restart; do
+ json_get_var "$i" "$i" 2>/dev/null
+ done
+ fi
+ case "$action" in
+ get)
+ case "$param" in
+ triggers)
+# shellcheck disable=SC2154
+ curReload="$parallel_downloads $debug $download_timeout \
+ $allowed_domain $blocked_domain $allowed_url $blocked_url $dns \
+ $config_update_enabled $config_update_url $dnsmasq_config_file_url \
+ $curl_additional_param $curl_max_file_size $curl_retry"
+# shellcheck disable=SC2154
+ curRestart="$compressed_cache $compressed_cache_dir $force_dns $led \
+ $force_dns_port"
+ if [ ! -s "$jsonFile" ]; then
+ ret='on_boot'
+ elif [ "$curReload" != "$reload" ]; then
+ ret='download'
+ elif [ "$curRestart" != "$restart" ]; then
+ ret='restart'
+ fi
+ printf "%b" "$ret"
+ return;;
+ *)
+ printf "%b" "$(eval echo "\$$param")"; return;;
+ esac
+ ;;
+ add)
+ line="$(eval echo "\$$param")"
+ eval "$param"='${line:+$line }${value}${extras:+|$extras}'
+ ;;
+ del)
+ case "$param" in
+ all)
+ unset status message error stats;;
+ triggers)
+ unset reload restart;;
+ *)
+ unset "$param";;
+ esac
+ ;;
+ set)
+ case "$param" in
+ triggers)
+ reload="$parallel_downloads $debug $download_timeout \
+ $allowed_domain $blocked_domain $allowed_url $blocked_url $dns \
+ $config_update_enabled $config_update_url $dnsmasq_config_file_url \
+ $curl_additional_param $curl_max_file_size $curl_retry"
+ restart="$compressed_cache $compressed_cache_dir $force_dns $led \
+ $force_dns_port"
+ ;;
+ *)
+ eval "$param"='${value}${extras:+|$extras}';;
+ esac
+ ;;
+ esac
+ json_init
+ json_add_object 'data'
+ json_add_string version "$PKG_VERSION"
+ json_add_string status "$status"
+ json_add_string message "$message"
+ json_add_string error "$error"
+ json_add_string stats "$stats"
+ json_add_string reload "$reload"
+ json_add_string restart "$restart"
+ json_close_object
+ mkdir -p "$(dirname "$jsonFile")"
+ json_dump > "$jsonFile"
+ sync
+}
+
+get_local_filesize() {
+ local file="$1" size
+ [ -f "$file" ] || return 0
+ if is_present stat; then
+ size="$(stat -c%s "$file")"
+ elif is_present wc; then
+ size="$(wc -c < "$file")"
+ fi
+# shellcheck disable=SC3037
+ echo -en "$size"
+}
+
+get_url_filesize() {
+ local url="$1" size size_command
+ [ -n "$url" ] || return 0
+ is_present 'curl' || return 0
+ size_command='curl --silent --insecure --fail --head --request GET'
+ size="$($size_command "$url" | grep -Po '^[cC]ontent-[lL]ength: \K\w+')"
+# shellcheck disable=SC3037
+ echo -en "$size"
+}
+
+output() {
+# Target verbosity level with the first parameter being an integer
+ is_integer() {
+ case "$1" in
+ (*[!0123456789]*) return 1;;
+ ('') return 1;;
+ (*) return 0;;
+ esac
+ }
+ local msg memmsg logmsg text
+ local sharedMemoryOutput="/dev/shm/$packageName-output"
+ if [ -z "$verbosity" ] && [ -n "$packageName" ]; then
+ verbosity="$(uci -q get "$packageName.config.verbosity")"
+ fi
+ verbosity="${verbosity:-2}"
+ if [ $# -ne 1 ] && is_integer "$1"; then
+ if [ $((verbosity & $1)) -gt 0 ] || [ "$verbosity" = "$1" ]; then shift; text="$*"; else return 0; fi
+ fi
+ text="${text:-$*}";
+ [ -t 1 ] && printf "%b" "$text"
+# shellcheck disable=SC3060
+ msg="${text//$serviceName /service }";
+ if [ "$(printf "%b" "$msg" | wc -l)" -gt 0 ]; then
+ [ -s "$sharedMemoryOutput" ] && memmsg="$(cat "$sharedMemoryOutput")"
+ logmsg="$(printf "%b" "${memmsg}${msg}" | sed 's/\x1b\[[0-9;]*m//g')"
+ logger -t "${packageName:-service} [$$]" "$(printf "%b" "$logmsg")"
+ rm -f "$sharedMemoryOutput"
+ else
+ printf "%b" "$msg" >> "$sharedMemoryOutput"
+ fi
+}
uci_add_list_if_new() {
local PACKAGE="$1"
done
uci_add_list "$PACKAGE" "$CONFIG" "$OPTION" "$VALUE"
}
+
uci_changes() {
local PACKAGE="$1"
local CONFIG="$2"
/sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} changes "$PACKAGE${CONFIG:+.$CONFIG}${OPTION:+.$OPTION}"
}
-ipset() { "$ipset" "$@" >/dev/null 2>&1; }
-nft() { "$nft" "$@" >/dev/null 2>&1; }
+if type extra_command 1>/dev/null 2>&1; then
+ extra_command 'allow' 'Allows domain in current block-list and config'
+ extra_command 'check' 'Checks if specified domain is found in current block-list'
+ extra_command 'check_lists' 'Checks if specified domain is found in enabled block-lists'
+ extra_command 'dl' 'Force-downloads all enabled block-list'
+ extra_command 'killcache' 'Delete all cached files'
+ extra_command 'pause' 'Pauses AdBlocking for specified number of seconds (default: 60)'
+ extra_command 'sizes' 'Displays the file-sizes of enabled block-lists'
+ extra_command 'version' 'Show version information'
+else
+# shellcheck disable=SC2034
+ EXTRA_COMMANDS='allow check dl killcache pause sizes status_service version'
+# shellcheck disable=SC2034
+ EXTRA_HELP=' allow Allows domain(s) in current block-list and config
+ check Checks if specified domain is found in current block-list
+ dl Force-downloads all enabled block-list
+ pause Pauses AdBlocking for specified number of seconds (default: 60)
+ sizes Displays the file-sizes of enabled block-lists'
+fi
get_text() {
local r
errorCreatingDirectory) r="failed to create output/cache/gzip file directory";;
errorDetectingFileType) r="failed to detect format";;
errorNothingToDo) r="no blocked list URLs nor blocked-domains enabled";;
+ errorTooLittleRam) r="free ram (%s) is not enough to process all enabled block-lists";;
statusNoInstall) r="$serviceName is not installed or not found";;
statusStopped) r="Stopped";;
statusForceReloading) r="Force Reloading";;
statusDownloading) r="Downloading";;
statusProcessing) r="Processing";;
- statusError) r="Error";;
- statusWarning) r="Warning";;
- statusFail) r="Fail";;
+ statusFail) r="failed to start";;
statusSuccess) r="Success";;
warningExternalDnsmasqConfig)
r="use of external dnsmasq config file detected, please set 'dns' option to 'dnsmasq.conf'";;
- warningMissingRecommendedPackages) r="Some recommended packages are missing";;
+ warningMissingRecommendedPackages) r="some recommended packages are missing";;
warningInvalidCompressedCacheDir) r="invalid compressed cache directory '%s'";;
+ warningFreeRamCheckFail) r="can't detect free RAM";;
esac
- echo "$r"
-}
-
-output_ok() { output 1 "$_OK_"; output 2 "$__OK__\\n"; }
-output_okn() { output 1 "$_OK_\\n"; output 2 "$__OK__\\n"; }
-output_fail() { output 1 "$_FAIL_"; output 2 "$__FAIL__\\n"; }
-output_failn() { output 1 "$_FAIL_\\n"; output 2 "$__FAIL__\\n"; }
-str_replace() { printf "%b" "$1" | sed -e "s/$(printf "%b" "$2")/$(printf "%b" "$3")/g"; }
-str_contains() { test "$1" != "$(str_replace "$1" "$2" '')"; }
-is_greater() { test "$(printf '%s\n' "$@" | sort -V | head -n 1)" != "$1"; }
-is_greater_or_equal() { test "$(printf '%s\n' "$@" | sort -V | head -n 1)" = "$2"; }
-is_chaos_calmer() { ubus -S call system board | grep -q 'Chaos Calmer'; }
-led_on(){ if [ -n "${1}" ] && [ -e "${1}/trigger" ]; then echo 'default-on' > "${1}/trigger" 2>&1; fi; }
-led_off(){ if [ -n "${1}" ] && [ -e "${1}/trigger" ]; then echo 'none' > "${1}/trigger" 2>&1; fi; }
-dnsmasq_hup() { killall -q -s HUP dnsmasq; }
-dnsmasq_kill() { killall -q -s KILL dnsmasq; }
-dnsmasq_restart() { /etc/init.d/dnsmasq restart >/dev/null 2>&1; }
-unbound_restart() { /etc/init.d/unbound restart >/dev/null 2>&1; }
-is_present() { command -v "$1" >/dev/null 2>&1; }
-sanitize_dir() { [ -d "$(readlink -fn "$1")" ] && readlink -fn "$1"; }
-
-output() {
-# Can take a single parameter (text) to be output at any verbosity
-# Or target verbosity level and text to be output at specifc verbosity
- local msg memmsg logmsg
- local sharedMemoryOutput="/dev/shm/$packageName-output"
- verbosity="${verbosity:-2}"
- if [ $# -ne 1 ]; then
- if [ $((verbosity & $1)) -gt 0 ] || [ "$verbosity" = "$1" ]; then shift; else return 0; fi
- fi
- [ -t 1 ] && printf "%b" "$1"
- msg="${1//$serviceName /service }";
- if [ "$(printf "%b" "$msg" | wc -l)" -gt 0 ]; then
- [ -s "$sharedMemoryOutput" ] && memmsg="$(cat "$sharedMemoryOutput")"
- logmsg="$(printf "%b" "${memmsg}${msg}" | sed 's/\x1b\[[0-9;]*m//g')"
- logger -t "${packageName:-service} [$$]" "$(printf "%b" "$logmsg")"
- rm -f "$sharedMemoryOutput"
- else
- printf "%b" "$msg" >> "$sharedMemoryOutput"
- fi
+ shift
+# shellcheck disable=SC2059
+ printf "$r" "$@"
}
load_network() {
output "Waiting to discover $wan_if gateway...\\n"
sleep 1
done
- json add error "errorNoWanGateway"
+ json add error 'errorNoWanGateway'
output "${_ERROR_}: $(get_text 'errorNoWanGateway')!\\n"; return 1;
}
append_url() {
local cfg="$1" var="$2"
local en action url
- config_get en "$cfg" enabled '1'
+ config_get_bool en "$cfg" enabled '1'
config_get action "$cfg" action 'block'
config_get url "$cfg" url
if [ "$en" = '1' ]; then
fi
}
- detect_file_type() {
- local file="$1"
- if [ "$(head -1 "$file")" = '[Adblock Plus]' ] || \
- grep -q '^||' "$file"; then
- echo 'adblockplus'
- elif grep -q '^server=' "$file"; then
- echo 'dnsmasq'
- elif grep -q '^local=' "$file"; then
- echo 'dnsmasq2'
- elif grep -q '^address=' "$file"; then
- echo 'dnsmasq3'
- elif grep -q '^0\.0\.0\.0' "$file" || grep -q '^127\.0\.0\.1' "$file"; then
- echo 'hosts'
- elif [ -n "$(sed "$domainsFilter" "$file" | head -1)" ]; then
- echo 'domains'
- fi
- }
-# detect_file_type() {
-# local file="$1"
-# if [ -n "$(sed "$adBlockPlusFilter" "$file" | head -1)" ]; then
-# echo 'adblockplus'
-# elif [ -n "$(sed "$dnsmasqFileFilter" "$file" | head -1)" ]; then
-# echo 'dnsmasq'
-# elif [ -n "$(sed "$dnsmasq2FileFilter" "$file" | head -1)" ]; then
-# echo 'dnsmasq2'
-# elif [ -n "$(sed "$hostsFilter" "$file" | head -1)" ]; then
-# echo 'hosts'
-# elif [ -n "$(sed "$domainsFilter" "$file" | head -1)" ]; then
-# echo 'domains'
-# fi
-# }
+detect_file_type() {
+ local file="$1"
+ if [ "$(head -1 "$file")" = '[Adblock Plus]' ] || \
+ grep -q '^||' "$file"; then
+ echo 'adblockplus'
+ elif grep -q '^server=' "$file"; then
+ echo 'dnsmasq'
+ elif grep -q '^local=' "$file"; then
+ echo 'dnsmasq2'
+ elif grep -q '^address=' "$file"; then
+ echo 'dnsmasq3'
+ elif grep -q '^0\.0\.0\.0' "$file" || grep -q '^127\.0\.0\.1' "$file"; then
+ echo 'hosts'
+ elif [ -n "$(sed "$domainsFilter" "$file" | head -1)" ]; then
+ echo 'domains'
+ fi
+}
load_environment() {
local i j
[ -z "$load_environment_flag" ] || return 0
if [ "$validation_result" != '0' ]; then
- json add error "errorConfigValidationFail"
+ json add error 'errorConfigValidationFail'
output "${_ERROR_}: $(get_text 'errorConfigValidationFail')!\\n"
output "Please check if the '$packageConfigFile' contains correct values for config options.\\n"
return 1
fi
if [ "$enabled" -eq 0 ]; then
- json add error "errorServiceDisabled"
+ json add error 'errorServiceDisabled'
output "${_ERROR_}: $(get_text 'errorServiceDisabled')!\\n"
output "Run the following commands before starting service again:\\n"
output "uci set ${packageName}.config.enabled='1'; uci commit $packageName;\\n"
dnsmasq.conf) :;;
*)
if [ "$param" != 'quiet' ]; then
- json add warning "warningExternalDnsmasqConfig"
+ json add warning 'warningExternalDnsmasqConfig'
output "${_WARNING_}: $(get_text 'warningExternalDnsmasqConfig')!\\n"
fi
;;
dnsmasq.ipset)
if dnsmasq -v 2>/dev/null | grep -q 'no-ipset' || ! dnsmasq -v 2>/dev/null | grep -q -w 'ipset'; then
if [ "$param" != 'quiet' ]; then
- json add error "errorNoDnsmasqIpset"
+ json add error 'errorNoDnsmasqIpset'
output "${_ERROR_}: $(get_text 'errorNoDnsmasqIpset')!\\n"
fi
dns='dnsmasq.servers'
fi
if ! ipset help hash:net; then
if [ "$param" != 'quiet' ]; then
- json add error "errorNoIpset"
+ json add error 'errorNoIpset'
output "${_ERROR_}: $(get_text 'errorNoIpset')!\\n"
fi
dns='dnsmasq.servers'
dnsmasq.nftset)
if dnsmasq -v 2>/dev/null | grep -q 'no-nftset' || ! dnsmasq -v 2>/dev/null | grep -q -w 'nftset'; then
if [ "$param" != 'quiet' ]; then
- json add error "errorNoDnsmasqNftset"
+ json add error 'errorNoDnsmasqNftset'
output "${_ERROR_}: $(get_text 'errorNoDnsmasqNftset')!\\n"
fi
dns='dnsmasq.servers'
fi
if [ -z "$nft" ]; then
if [ "$param" != 'quiet' ]; then
- json add error "errorNoNft"
+ json add error 'errorNoNft'
output "${_ERROR_}: $(get_text 'errorNoNft')!\\n"
fi
dns='dnsmasq.servers'
compressed_cache_dir="$(sanitize_dir "$compressed_cache_dir")"
else
json add warning 'warningInvalidCompressedCacheDir' "$compressed_cache_dir"
+ output "${_WARNING_}: $(get_text 'warningInvalidCompressedCacheDir' "$compressed_cache_dir")!\\n"
compressed_cache_dir="/etc"
fi
for i in "$jsonFile" "$outputFile" "$outputCache" "$outputGzip"; do
if ! mkdir -p "$(dirname "$i")"; then
if [ "$param" != 'quiet' ]; then
- json add error "errorOutputDirCreate" "$i"
+ json add error 'errorOutputDirCreate' "$i"
output "${_ERROR_}: $(get_text 'errorOutputDirCreate' "$i")!\\n"
fi
fi
is_present 'gawk' && awk='gawk'
if ! is_present '/usr/libexec/grep-gnu' || ! is_present '/usr/libexec/sed-gnu' || \
! is_present '/usr/libexec/sort-coreutils' || ! is_present 'gawk'; then
- local s="opkg update; opkg --force-overwrite install"
- is_present 'gawk' || s="$s gawk"
- is_present '/usr/libexec/grep-gnu' || s="$s grep"
- is_present '/usr/libexec/sed-gnu' || s="$s sed"
- is_present '/usr/libexec/sort-coreutils' || s="$s coreutils-sort"
+ local s
+ is_present 'gawk' || s="${s:+$s }gawk"
+ is_present '/usr/libexec/grep-gnu' || s="${s:+$s }grep"
+ is_present '/usr/libexec/sed-gnu' || s="${s:+$s }sed"
+ is_present '/usr/libexec/sort-coreutils' || s="${s:+$s }coreutils-sort"
if [ "$param" != 'quiet' ]; then
- json add warning "warningMissingRecommendedPackages" "${i}"
+ json add warning 'warningMissingRecommendedPackages' "$s"
output "${_WARNING_}: $(get_text 'warningMissingRecommendedPackages'), install them by running:\\n"
- output "$s;\\n"
+ output "opkg update; opkg --force-overwrite install $s;\\n"
fi
fi
# Prefer curl because it supports the file:// scheme.
fi
}
-get_url_filesize() {
- local url="$1" size size_command
- [ -n "$url" ] || return 0
- is_present 'curl' || return 0
- size_command='curl --silent --insecure --fail --head --request GET'
- size="$($size_command "$url" | grep -Po '^[cC]ontent-[lL]ength: \K\w+')"
- echo -en "$size"
-}
-
-get_local_filesize() {
- local file="$1" size
- [ -f "$file" ] || return 0
- if is_present stat; then
- size="$(stat -c%s "$file")"
- elif is_present wc; then
- size="$(wc -c < "$file")"
- fi
- echo -en "$size"
-}
-
-resolver_config() {
- local cfg="$1" param="$2"
- case "$param" in
- dnsmasq.addnhosts)
- if [ "$(uci_get 'dhcp' "$cfg" 'serversfile')" = "$dnsmasqServersFile" ]; then
- uci_remove 'dhcp' "$cfg" 'serversfile'
- fi
- uci_add_list_if_new 'dhcp' "$cfg" 'addnhosts' "$dnsmasqAddnhostsFile"
- ;;
- cleanup|dnsmasq.conf|dnsmasq.ipset|dnsmasq.nftset|unbound.adb_list)
- uci_remove_list 'dhcp' "$cfg" 'addnhosts' "$dnsmasqAddnhostsFile"
- if [ "$(uci_get 'dhcp' "$cfg" 'serversfile')" = "$dnsmasqServersFile" ]; then
- uci_remove 'dhcp' "$cfg" 'serversfile'
- fi
- ;;
- dnsmasq.servers)
- uci_remove_list 'dhcp' "$cfg" 'addnhosts' "$dnsmasqAddnhostsFile"
- if [ "$(uci_get 'dhcp' "$cfg" 'serversfile')" != "$dnsmasqServersFile" ]; then
- uci_set 'dhcp' "$cfg" 'serversfile' "$dnsmasqServersFile"
- fi
- ;;
- esac
-}
-
-dns() {
+resolver() {
+ _resolver_config() {
+ local cfg="$1" param="$2"
+ case "$param" in
+ dnsmasq.addnhosts)
+ if [ "$(uci_get 'dhcp' "$cfg" 'serversfile')" = "$dnsmasqServersFile" ]; then
+ uci_remove 'dhcp' "$cfg" 'serversfile'
+ fi
+ uci_add_list_if_new 'dhcp' "$cfg" 'addnhosts' "$dnsmasqAddnhostsFile"
+ ;;
+ cleanup|dnsmasq.conf|dnsmasq.ipset|dnsmasq.nftset|unbound.adb_list)
+ uci_remove_list 'dhcp' "$cfg" 'addnhosts' "$dnsmasqAddnhostsFile"
+ if [ "$(uci_get 'dhcp' "$cfg" 'serversfile')" = "$dnsmasqServersFile" ]; then
+ uci_remove 'dhcp' "$cfg" 'serversfile'
+ fi
+ ;;
+ dnsmasq.servers)
+ uci_remove_list 'dhcp' "$cfg" 'addnhosts' "$dnsmasqAddnhostsFile"
+ if [ "$(uci_get 'dhcp' "$cfg" 'serversfile')" != "$dnsmasqServersFile" ]; then
+ uci_set 'dhcp' "$cfg" 'serversfile' "$dnsmasqServersFile"
+ fi
+ ;;
+ esac
+ }
local param output_text i
case $1 in
+ cleanup)
+ rm -f "$dnsmasqAddnhostsFile" "$dnsmasqAddnhostsCache" "${compressed_cache_dir}/${dnsmasqAddnhostsGzip}"
+ rm -f "$dnsmasqConfFile" "$dnsmasqConfCache" "${compressed_cache_dir}/${dnsmasqConfGzip}"
+ rm -f "$dnsmasqIpsetFile" "$dnsmasqIpsetCache" "${compressed_cache_dir}/${dnsmasqIpsetGzip}"
+ rm -f "$dnsmasqNftsetFile" "$dnsmasqNftsetCache" "${compressed_cache_dir}/${dnsmasqNftsetGzip}"
+ rm -f "$dnsmasqServersFile" "$dnsmasqServersCache" "${compressed_cache_dir}/${dnsmasqServersGzip}"
+ rm -f "$unboundFile" "$unboundCache" "$unboundGzip"
+ config_load 'dhcp'
+ config_foreach _resolver_config 'dnsmasq' 'cleanup'
+ uci_commit 'dhcp'
+ ;;
on_start)
if [ ! -s "$outputFile" ]; then
- json set status "statusFail"
- json add error "errorOutputFileCreate"
+ json set status 'statusFail'
+ json add error 'errorOutputFileCreate'
output "${_ERROR_}: $(get_text 'errorOutputFileCreate')!\\n"
return 1
fi
config_load 'dhcp'
if [ "$dnsmasq_instance" = "*" ]; then
- config_foreach resolver_config 'dnsmasq' "$dns"
+ config_foreach _resolver_config 'dnsmasq' "$dns"
elif [ -n "$dnsmasq_instance" ]; then
for i in $dnsmasq_instance; do
- resolver_config "@dnsmasq[$i]" "$dns" || resolver_config "$i" "$dns"
+ _resolver_config "@dnsmasq[$i]" "$dns" || _resolver_config "$i" "$dns"
done
fi
output 2 "$output_text "
json set message "$output_text"
if eval "$param"; then
- json set status "statusSuccess"
+ json set status 'statusSuccess'
led_on "$led"
output_okn
else
output_fail
- json set status "statusFail"
- json add error "errorDNSReload"
+ json set status 'statusFail'
+ json add error 'errorDNSReload'
output "${_ERROR_}: $(get_text 'errorDNSReload')!\\n"
return 1
fi
eval "$param"
return $?
;;
- quiet)
+ quiet|quiet_restart)
case "$dns" in
dnsmasq.addnhosts|dnsmasq.conf|dnsmasq.ipset|dnsmasq.nftset|dnsmasq.servers)
param=dnsmasq_restart
esac
}
-json() {
-# shellcheck disable=SC2034
- local action="$1" param="$2" value="$3"
- shift 3
-# shellcheck disable=SC2124
- local extras="$@" line
- local status message error stats
- local reload restart curReload curRestart ret i
- if [ -s "$jsonFile" ]; then
- json_load_file "$jsonFile" 2>/dev/null
- json_select 'data' 2>/dev/null
- for i in status message error stats reload restart; do
- json_get_var "$i" "$i" 2>/dev/null
- done
- fi
- case "$action" in
- get)
- case "$param" in
- triggers)
- curReload="$parallel_downloads $debug $download_timeout \
- $allowed_domain $blocked_domain $allowed_url $blocked_url $dns \
- $config_update_enabled $config_update_url $dnsmasq_config_file_url \
- $curl_additional_param $curl_max_file_size $curl_retry"
- curRestart="$compressed_cache $compressed_cache_dir $force_dns $led \
- $force_dns_port"
- if [ ! -s "$jsonFile" ]; then
- ret='on_boot'
- elif [ "$curReload" != "$reload" ]; then
- ret='download'
- elif [ "$curRestart" != "$restart" ]; then
- ret='restart'
- fi
- printf "%b" "$ret"
- return;;
- *)
- printf "%b" "$(eval echo "\$$param")"; return;;
- esac
- ;;
- add)
- line="$(eval echo "\$$param")"
- eval "$param"='${line:+$line }${value}${extras:+|$extras}'
- ;;
- del)
- case "$param" in
- all)
- unset status message error stats;;
- triggers)
- unset reload restart;;
- *)
- unset "$param";;
- esac
- ;;
- set)
- case "$param" in
- triggers)
- reload="$parallel_downloads $debug $download_timeout \
- $allowed_domain $blocked_domain $allowed_url $blocked_url $dns \
- $config_update_enabled $config_update_url $dnsmasq_config_file_url \
- $curl_additional_param $curl_max_file_size $curl_retry"
- restart="$compressed_cache $compressed_cache_dir $force_dns $led \
- $force_dns_port"
- ;;
- *)
- eval "$param"='${value}${extras:+|$extras}';;
- esac
- ;;
- esac
- json_init
- json_add_object 'data'
- json_add_string version "$PKG_VERSION"
- json_add_string status "$status"
- json_add_string message "$message"
- json_add_string error "$error"
- json_add_string stats "$stats"
- json_add_string reload "$reload"
- json_add_string restart "$restart"
- json_close_object
- mkdir -p "$(dirname "$jsonFile")"
- json_dump > "$jsonFile"
- sync
-}
-
cache() {
local R_TMP
case "$1" in
esac
}
-_process_file_url() {
+process_file_url_wrapper() {
if [ "$2" != '0' ]; then
- json add error "errorConfigValidationFail"
+ json add error 'errorConfigValidationFail'
output "${_ERROR_}: $(get_text 'errorConfigValidationFail')!\\n"
output "Please check if the '$packageConfigFile' contains correct values for config options.\\n"
fi
file) type='File'; D_TMP="$B_TMP"
;;
esac
- if [ "${1:0:5}" = "https" ] && [ -z "$isSSLSupported" ]; then
+ if is_https_url "$url" && [ -z "$isSSLSupported" ]; then
output 1 "$_FAIL_"
output 2 "[DL] $type $label $__FAIL__\\n"
echo "errorNoSSLSupport|${1}" >> "$sharedMemoryError"
output 2 "[DL] $type $label $__FAIL__\\n"
echo "errorDownloadingList|${url}" >> "$sharedMemoryError"
else
+ append_newline "$R_TMP"
[ -n "$cfg" ] && new_size="$(get_local_filesize "$R_TMP")"
if [ -n "$new_size" ] && [ "$size" != "$new_size" ]; then
uci set "${packageName}.${cfg}.size=$size"
output 2 "[DL] $type $label ($format) $__FAIL__\\n"
echo "errorParsingList|${url}" >> "$sharedMemoryError"
else
+ append_newline "$R_TMP"
cat "${R_TMP}" >> "$D_TMP"
output 1 "$_OK_"
output 2 "[DL] $type $label ($format) $__OK__\\n"
download_dnsmasq_file() {
local hf allow_filter j=0 R_TMP
- json set message "$(get_text "statusDownloading")..."
- json set status "statusDownloading"
+ json set message "$(get_text 'statusDownloading')..."
+ json set status 'statusDownloading'
rm -f "$A_TMP" "$B_TMP" "$outputFile" "$outputCache" "$outputGzip"
- if [ "$($awk '/^MemFree/ {print int($2/1000)}' "/proc/meminfo")" -lt 32 ]; then
+ if [ "$(get_ram_free)" -lt 32 ]; then
output 3 'Low free memory, restarting resolver '
- if dns 'quiet'; then
+ if resolver 'quiet_restart'; then
output_okn
else
output_failn
output 2 "$__OK__\\n"
else
output 2 "$__FAIL__\\n"
- json add error "errorMovingDataFile"
+ json add error 'errorMovingDataFile'
fi
output 1 '\n'
}
download_lists() {
+ _ram_check() {
+ _config_calculate_sizes() {
+ local cfg="$1"
+ local en size url
+ config_get_bool en "$cfg" enabled '1'
+ config_get size "$cfg" size
+ config_get url "$cfg" url
+ [ "$en" = '0' ] && return 0
+ [ -n "$size" ] || size="$(get_url_filesize "$url")"
+ [ -n "$size" ] && total_sizes=$((total_sizes+size))
+ }
+ local i free_mem total_sizes
+ free_mem="$(get_ram_free)"
+ if [ -z "$free_mem" ]; then
+ json add warnning 'warningFreeRamCheckFail'
+ output "${_WARNING_}: $(get_text 'warningFreeRamCheckFail')!\\n"
+ return 0
+ fi
+ config_load "$packageName"
+ config_foreach _config_calculate_sizes 'file_url'
+ if [ $((free_mem)) -lt $((total_sizes * 2)) ]; then
+ json add error 'errorTooLittleRam' "$free_mem"
+ output "${_ERROR_}: $(get_text 'errorTooLittleRam' "$free_mem")!\\n"
+ return 1
+ else
+ return 0
+ fi
+ }
local hf allow_filter j=0 R_TMP
- json set message "$(get_text "statusDownloading")..."
- json set status "statusDownloading"
+ _ram_check || return 1
+
+ json set message "$(get_text 'statusDownloading')..."
+ json set status 'statusDownloading'
rm -f "$A_TMP" "$B_TMP" "$outputFile" "$outputCache" "$outputGzip"
- if [ "$($awk '/^MemFree/ {print int($2/1000)}' "/proc/meminfo")" -lt 32 ]; then
+ if [ "$(get_ram_total)" -lt 33554432 ]; then
output 3 'Low free memory, restarting resolver '
- if dns 'quiet'; then
+ if resolver 'quiet_restart'; then
output_okn
else
output_failn
output 1 'Downloading lists '
rm -f "$sharedMemoryError"
config_load "$packageName"
- config_foreach load_validate_file_url_section 'file_url' _process_file_url
+ config_foreach load_validate_file_url_section 'file_url' process_file_url_wrapper
wait
if [ -n "$(uci changes "$packageName")" ]; then
output 2 "Saving updated file size(s) "
- uci commit "$packageName" && output_okn || output_failn
+ if uci commit "$packageName"; then output_okn; else output_failn; fi
fi
output 1 '\n'
canaryDomains="${canaryDomains:+$canaryDomains }${canaryDomainsMozilla}"
fi
- for hf in $blocked_domain $canaryDomains; do echo "$hf" | sed "$domainsFilter" >> $B_TMP; done
+ append_newline "$B_TMP"
+ for hf in $blocked_domain $canaryDomains; do
+ printf "%s\n" "$(echo "$hf" | sed "$domainsFilter")" >> "$B_TMP"
+ done
allowed_domain="${allowed_domain}
$(cat $A_TMP)"
for hf in ${allowed_domain}; do hf="$(echo "$hf" | sed 's/\./\\./g')"; allow_filter="$allow_filter/(^|\.)${hf}$/d;"; done
output 1 'Processing downloads '
output 2 'Sorting combined list '
- json set status "statusProcessing"
- json set message "$(get_text "statusProcessing"): sorting combined list"
+ json set status 'statusProcessing'
+ json set message "$(get_text 'statusProcessing'): sorting combined list"
if [ "$allow_non_ascii" -gt 0 ]; then
if sort -u "$B_TMP" > "$A_TMP"; then
output_ok
else
output_failn
- json add error "errorSorting"
+ json add error 'errorSorting'
fi
else
if sort -u "$B_TMP" | grep -E -v '[^a-zA-Z0-9=/.-]' > "$A_TMP"; then
output_ok
else
output_failn
- json add error "errorSorting"
+ json add error 'errorSorting'
fi
fi
[ "$dns" = 'unbound.adb_list' ]; then
# TLD optimization written by Dirk Brenken (dev@brenken.org)
output 2 'Optimizing combined list '
- json set message "$(get_text "statusProcessing"): optimizing combined list"
+ json set message "$(get_text 'statusProcessing'): optimizing combined list"
# sed -E 'G;:t;s/(.*)(\.)(.*)(\n)(.*)/\1\4\5\2\3/;tt;s/(.*)\n(\.)(.*)/\3\2\1/' is actually slower than command below
+# shellcheck disable=SC2016
if $awk -F "." '{for(f=NF;f>1;f--)printf "%s.",$f;print $1}' "$A_TMP" > "$B_TMP"; then
if sort "$B_TMP" > "$A_TMP"; then
if $awk '{if(NR=1){tld=$NF};while(getline){if($NF!~tld"\\."){print tld;tld=$NF}}print tld}' "$A_TMP" > "$B_TMP"; then
output_ok
else
output_failn
- json add error "errorOptimization"
+ json add error 'errorOptimization'
mv "$A_TMP" "$B_TMP"
fi
else
output_failn
- json add error "errorOptimization"
+ json add error 'errorOptimization'
fi
else
output_failn
- json add error "errorOptimization"
+ json add error 'errorOptimization'
mv "$A_TMP" "$B_TMP"
fi
else
output_failn
- json add error "errorOptimization"
+ json add error 'errorOptimization'
fi
else
output_failn
- json add error "errorOptimization"
+ json add error 'errorOptimization'
mv "$A_TMP" "$B_TMP"
fi
else
if [ -n "$allow_filter" ]; then
output 2 'Allowing domains '
- json set message "$(get_text "statusProcessing"): allowing domains"
+ json set message "$(get_text 'statusProcessing'): allowing domains"
if sed -i -E "$allow_filter" "$B_TMP"; then
output_ok
else
output_failn
- json add error "errorAllowListProcessing"
+ json add error 'errorAllowListProcessing'
fi
fi
output 2 'Formatting merged file '
- json set message "$(get_text "statusProcessing"): formatting merged file"
+ json set message "$(get_text 'statusProcessing'): formatting merged file"
if [ -z "$outputFilterIPv6" ]; then
if sed "$outputFilter" "$B_TMP" > "$A_TMP"; then
output_ok
else
output_failn
- json add error "errorDataFileFormatting"
+ json add error 'errorDataFileFormatting'
fi
else
case "$dns" in
output_ok
else
output_failn
- json add error "errorDataFileFormatting"
+ json add error 'errorDataFileFormatting'
fi
;;
esac
case "$dns" in
dnsmasq.addnhosts)
output 2 'Creating dnsmasq addnhosts file '
- json set message "$(get_text "statusProcessing"): creating dnsmasq addnhosts file"
+ json set message "$(get_text 'statusProcessing'): creating dnsmasq addnhosts file"
;;
dnsmasq.conf)
output 2 'Creating dnsmasq config file '
- json set message "$(get_text "statusProcessing"): creating dnsmasq config file"
+ json set message "$(get_text 'statusProcessing'): creating dnsmasq config file"
;;
dnsmasq.ipset)
output 2 'Creating dnsmasq ipset file '
- json set message "$(get_text "statusProcessing"): creating dnsmasq ipset file"
+ json set message "$(get_text 'statusProcessing'): creating dnsmasq ipset file"
;;
dnsmasq.nftset)
output 2 'Creating dnsmasq nft set file '
- json set message "$(get_text "statusProcessing"): creating dnsmasq nft set file"
+ json set message "$(get_text 'statusProcessing'): creating dnsmasq nft set file"
;;
dnsmasq.servers)
output 2 'Creating dnsmasq servers file '
- json set message "$(get_text "statusProcessing"): creating dnsmasq servers file"
+ json set message "$(get_text 'statusProcessing'): creating dnsmasq servers file"
;;
unbound.adb_list)
output 2 'Creating Unbound adb_list file '
- json set message "$(get_text "statusProcessing"): creating Unbound adb_list file"
+ json set message "$(get_text 'statusProcessing'): creating Unbound adb_list file"
;;
esac
output_ok
else
output_failn
- json add error "errorMovingDataFile"
+ json add error 'errorMovingDataFile'
fi
if [ "$compressed_cache" -gt 0 ]; then
output 2 'Creating compressed cache '
- json set message "$(get_text "statusProcessing"): creating compressed cache"
+ json set message "$(get_text 'statusProcessing'): creating compressed cache"
if cache 'create_gzip'; then
output_ok
else
output_failn
- json add error "errorCreatingCompressedCache"
+ json add error 'errorCreatingCompressedCache'
fi
else
rm -f "$outputGzip"
fi
output 2 'Removing temporary files '
- json set message "$(get_text "statusProcessing"): removing temporary files"
+ json set message "$(get_text 'statusProcessing'): removing temporary files"
rm -f "/tmp/${packageName}_tmp.*" "$A_TMP" "$B_TMP" "$outputCache" || j=1
if [ $j -eq 0 ]; then
output_ok
else
output_failn
- json add error "errorRemovingTempFiles"
+ json add error 'errorRemovingTempFiles'
fi
output 1 '\n'
}
done
}
+adb_check_lists() {
+ _check_list() {
+ local cfg="$1"
+ local en size url R_TMP string c
+ config_get_bool en "$cfg" enabled '1'
+ config_get action "$cfg" action 'block'
+ config_get url "$cfg" url
+ [ "$en" = '0' ] && return 0
+ [ "$action" != 'block' ] && return 0
+ if is_https_url "$url" && [ -z "$isSSLSupported" ]; then
+ output "[DL] $url $__FAIL__\\n"
+ fi
+ while [ -z "$R_TMP" ] || [ -e "$R_TMP" ]; do
+ R_TMP="$(mktemp -u -q -t ${packageName}_tmp.XXXXXXXX)"
+ done
+ if [ -z "$url" ] || ! $dl_command "$url" "$dl_flag" "$R_TMP" 2>/dev/null || \
+ [ ! -s "$R_TMP" ]; then
+ output "[DL] $url $__FAIL__\\n"
+ else
+ append_newline "$R_TMP"
+ for string in ${param}; do
+ c="$(grep -c "$string" "$R_TMP")"
+ if [ "$c" -gt 0 ]; then
+ if [ "$c" -eq 1 ]; then
+ output "Found 1 match for '$string' in '$url'.\\n"
+ else
+ output "Found $c matches for '$string' in '$url'.\\n"
+ fi
+ grep "$string" "$R_TMP"
+ else
+ output "The '$string' is not found in '$url'.\\n"
+ fi
+ done
+ rm -f "$R_TMP"
+ fi
+ }
+ local param="$1"
+ local validation_result="$3"
+ load_environment "$validation_result" 'quiet' || return 1
+ if [ -z "$param" ]; then
+ output "Usage: /etc/init.d/${packageName} check_lists 'domain' ...\\n"
+ return 0
+ fi
+ config_load "$packageName"
+ config_foreach _check_list 'file_url'
+ return 0
+}
+
adb_config_update() {
local R_TMP label
local param validation_result="$3"
R_TMP="$(mktemp -u -q -t ${packageName}_tmp.XXXXXXXX)"
done
if ! $dl_command "$config_update_url" "$dl_flag" "$R_TMP" 2>/dev/null || [ ! -s "$R_TMP" ]; then
+ append_newline "$R_TMP"
output 1 "$_FAIL_\\n"
output 2 "[DL] Config Update: $label $__FAIL__\\n"
- json add error "errorDownloadingConfigUpdate"
+ json add error 'errorDownloadingConfigUpdate'
else
if [ -s "$R_TMP" ] && sed -f "$R_TMP" -i "$packageConfigFile" 2>/dev/null; then
output 1 "$_OK_\\n"
else
output 1 "$_FAIL_\\n"
output 2 "[DL] Config Update: $label $__FAIL__\\n"
- json add error "errorParsingConfigUpdate"
+ json add error 'errorParsingConfigUpdate'
fi
fi
rm -f "$R_TMP"
return 0
}
-_config_add_url_size() {
- local cfg="$1" url size
- config_get url "$cfg" url
- size="$(get_url_filesize "$url")"
- output "$url${size:+: $size} "
- if [ -n "$size" ]; then
- uci set "${packageName}.${cfg}.size=$size"
- output_okn
- else
- output_failn
- fi
-}
-
adb_sizes() {
+ _config_add_url_size() {
+ local cfg="$1" url size
+ config_get url "$cfg" url
+ size="$(get_url_filesize "$url")"
+ output "$url${size:+: $size} "
+ if [ -n "$size" ]; then
+ uci set "${packageName}.${cfg}.size=$size"
+ output_okn
+ else
+ output_failn
+ fi
+ }
local i
local validation_result="$3"
load_environment "$validation_result" 'quiet' || return 1
elif [ "$action" = 'restart' ] || [ "$param" = 'restart' ]; then
action='restart'
elif [ -s "$outputFile" ] && [ "$status" = "statusSuccess" ] && [ -z "$error" ]; then
- status_service
+ status_service 'quiet'
return 0
else
action='download'
if [ "$action" = 'restore' ]; then
output 0 "Starting $serviceName... "
output 3 "Starting $serviceName...\\n"
- json set status "statusStarting"
+ json set status 'statusStarting'
if cache 'test_gzip' && ! cache 'test' && [ ! -s "$outputFile" ]; then
output 3 'Found compressed cache file, unpacking it '
json set message 'found compressed cache file, unpacking it.'
output_okn
else
output_failn
- json add error "errorRestoreCompressedCache"
+ json add error 'errorRestoreCompressedCache'
output "${_ERROR_}: $(get_text 'errorRestoreCompressedCache')!\\n"
action='download'
fi
json set message 'found cache file, reusing it.'
if cache 'restore'; then
output_okn
- dns 'on_start'
+ resolver 'on_start'
else
output_failn
- json add error "errorRestoreCache"
+ json add error 'errorRestoreCache'
output "${_ERROR_}: $(get_text 'errorRestoreCache')!\\n"
action='download'
fi
fi
if [ "$action" = 'download' ]; then
if [ -z "$blocked_url" ] && [ -z "$blocked_domain" ]; then
- json set status "statusFail"
- json add error "errorNothingToDo"
+ json set status 'statusFail'
+ json add error 'errorNothingToDo'
output "${_ERROR_}: $(get_text 'errorNothingToDo')!\\n"
else
if [ -s "$outputFile" ] || cache 'test' || cache 'test_gzip'; then
output 0 "Force-reloading $serviceName... "
output 3 "Force-reloading $serviceName...\\n"
- json set status "statusForceReloading"
+ json set status 'statusForceReloading'
else
output 0 "Starting $serviceName... "
output 3 "Starting $serviceName...\\n"
- json set status "statusStarting"
+ json set status 'statusStarting'
fi
+ resolver 'cleanup'
if [ "$dns" = 'dnsmasq.conf' ] && [ -n "$dnsmasq_config_file_url" ]; then
download_dnsmasq_file
else
download_lists
fi
- dns 'on_start'
+ resolver 'on_start'
fi
fi
if [ "$action" = 'restart' ]; then
output 0 "Restarting $serviceName... "
output 3 "Restarting $serviceName...\\n"
- json set status "statusRestarting"
- dns 'on_start'
+ json set status 'statusRestarting'
+ resolver 'on_start'
fi
if [ "$action" = 'start' ]; then
output 0 "Starting $serviceName... "
output 3 "Starting $serviceName...\\n"
- json set status "statusStarting"
- dns 'on_start'
+ json set status 'statusStarting'
+ resolver 'on_start'
fi
if [ -s "$outputFile" ] && [ "$(json get status)" != "statusFail" ]; then
output 0 "$__OK__\\n";
json del message
- json set status "statusSuccess"
+ json set status 'statusSuccess'
json set stats "$serviceName is blocking $(wc -l < "$outputFile") domains (with ${dns})"
- status_service
+ status_service 'quiet'
+
else
output 0 "$__FAIL__\\n";
- json set status "statusFail"
- json add error "errorOhSnap"
- status_service
+ json set status 'statusFail'
+ json add error 'errorOhSnap'
+ status_service 'quiet'
fi
procd_open_instance 'main'
fi
json_add_array firewall
if [ "$force_dns" -ne 0 ]; then
+# shellcheck disable=SC3060
for c in ${force_dns_port/,/ }; do
if netstat -tuln | grep LISTEN | grep ":${c}" >/dev/null 2>&1; then
json_add_object ""
}
adb_status() {
- local c url status message error stats
- local validation_result="$3"
- load_environment "$validation_result" 'quiet' || return 1
+ local param="$1"
+ local c status message error warning stats text
status="$(json get status)"
message="$(json get message)"
error="$(json get error)"
+ warning="$(json get warning)"
stats="$(json get stats)"
if [ "$status" = "statusSuccess" ]; then
output "$stats "; output_okn;
if [ -n "$status" ] && [ -n "$message" ]; then
status="${status}: $message"
fi
- [ -n "$status" ] && output "$serviceName $status\\n"
+ [ -n "$status" ] && output "$serviceName $status!\\n"
fi
- if [ -n "$error" ]; then
+ if [ "$param" != 'quiet' ] && [ -n "$error" ]; then
for c in $error; do
- url="${c##*|}"
- c="${c%|*}"
- case "$c" in
- errorDownloadingList|errorParsingList)
- output "${_ERROR_}: $(get_text "$c") $url!\\n";;
- *)
- output "${_ERROR_}: $(get_text "$c")!\\n";;
- esac
- n=$((n+1))
+ local error_param="${c##*|}"
+ local error_code="${c%|*}"
+ output "${_ERROR_}: $(get_text "$error_code" "$error_param")!\\n"
+ done
+ fi
+ if [ "$param" != 'quiet' ] && [ -n "$warning" ]; then
+ for c in $warning; do
+ local warning_param="${c##*|}"
+ local warning_code="${c%|*}"
+ output "${_WARNING_}: $(get_text "$warning_code" "$warning_param").\\n"
done
fi
return 0
if [ -s "$outputFile" ]; then
output "Stopping $serviceName... "
cache 'create'
- if dns 'on_stop'; then
+ if resolver 'on_stop'; then
ipset -q -! flush adb
ipset -q -! destroy adb
nft delete set inet fw4 adb4
nft delete set inet fw4 adb6
led_off "$led"
output 0 "$__OK__\\n"; output_okn;
- json set status "statusStopped"
+ json set status 'statusStopped'
json del message
else
output 0 "$__FAIL__\\n"; output_fail;
- json set status "statusFail"
- json add error "errorStopping"
+ json set status 'statusFail'
+ json add error 'errorStopping'
output "${_ERROR_}: $(get_text 'errorStopping')!\\n"
fi
fi
local validation_result="$3"
adb_stop 'on_pause' '' "$validation_result"
output "Sleeping for $timeout seconds... "
- if sleep "$timeout"; then
+ if is_integer "$timeout" && sleep "$timeout"; then
output_okn
else
output_failn
allow() { load_validate_config 'config' adb_allow "'$*'"; }
boot() {
+ local procd_boot_delay
ubus -t 30 wait_for network.interface 2>/dev/null
- rc_procd start_service 'on_boot'
+ config_load "$packageName"
+ config_get procd_boot_delay 'config' 'procd_boot_delay' '0'
+# shellcheck disable=SC2154
+ { is_integer "$procd_boot_delay" && sleep "$procd_boot_delay"; \
+ rc_procd start_service 'on_boot' && service_started 'on_boot'; } &
}
check() { load_validate_config 'config' adb_check "'$*'"; }
+check_lists() { load_validate_config 'config' adb_check_lists "'$*'"; }
dl() { rc_procd start_service 'download'; }
killcache() {
local compressed_cache_dir
rm -f "$dnsmasqNftsetCache" "${compressed_cache_dir}/${dnsmasqNftsetGzip}"
rm -f "$dnsmasqServersCache" "${compressed_cache_dir}/${dnsmasqServersGzip}"
rm -f "$unboundCache" "$unboundGzip"
- config_load 'dhcp'
- config_foreach resolver_config 'dnsmasq' 'cleanup'
- uci_commit 'dhcp'
+ resolver 'cleanup'
return 0
}
reload_service() { rc_procd start_service 'restart'; }
local procd_trigger_wan6
config_load "$packageName"
config_get_bool procd_trigger_wan6 'config' 'procd_trigger_wan6' '0'
- . /lib/functions/network.sh
network_flush_cache
network_find_wan wan
wan="${wan:-wan}"
load_validate_config 'config' adb_config_update "'$*'"
load_validate_config 'config' adb_start "'$*'"
}
-status_service() { load_validate_config 'config' adb_status "''"; }
+status_service() { adb_status "$@"; }
stop_service() { load_validate_config 'config' adb_stop "'$*'"; }
pause() { load_validate_config 'config' adb_pause "'$*'"; }
version() { echo "$PKG_VERSION"; }
}
load_validate_config() {
- . /lib/functions/network.sh
- . /usr/share/libubox/jshn.sh
local enabled
local force_dns
local force_dns_port
#!/bin/sh
# Copyright 2023 MOSSDeF, Stan Grishin (stangri@melmac.ca)
-# shellcheck disable=SC1091,SC2015,SC3037,SC3043,SC2317,SC3060
+# shellcheck disable=SC2015,SC3043,SC3060
-readonly packageName='adblock-fast'
-readonly _OK_='\033[0;32m\xe2\x9c\x93\033[0m'
-readonly _FAIL_='\033[0;31m\xe2\x9c\x97\033[0m'
-readonly __OK__='\033[0;32m[\xe2\x9c\x93]\033[0m'
-readonly __FAIL__='\033[0;31m[\xe2\x9c\x97]\033[0m'
-readonly _ERROR_='\033[0;31mERROR\033[0m'
-readonly _WARNING_='\033[0;33mWARNING\033[0m'
-output() {
-# Can take a single parameter (text) to be output at any verbosity
-# Or target verbosity level and text to be output at specifc verbosity
- local msg memmsg logmsg
- local sharedMemoryOutput="/dev/shm/$packageName-output"
- verbosity="${verbosity:-2}"
- if [ "$#" -ne 1 ]; then
- if [ $((verbosity & $1)) -gt 0 ] || [ "$verbosity" = "$1" ]; then
- shift
- else
- return 0
- fi
- fi
- [ -t 1 ] && printf "%b" "$1"
- msg="$1";
- if [ "$(printf "%b" "$msg" | wc -l)" -gt 0 ]; then
- [ -s "$sharedMemoryOutput" ] && memmsg="$(cat "$sharedMemoryOutput")"
- logmsg="$(printf "%b" "${memmsg}${msg}" | sed 's/\x1b\[[0-9;]*m//g')"
- logger -t "${packageName:-service}" "$(printf "%b" "$logmsg")"
- rm -f "$sharedMemoryOutput"
- else
- printf "%b" "$msg" >> "$sharedMemoryOutput"
- fi
-}
-output_ok() { output 1 "$_OK_"; output 2 "$__OK__\\n"; }
-output_okn() { output 1 "$_OK_\\n"; output 2 "$__OK__\\n"; }
-output_fail() { output 1 "$_FAIL_"; output 2 "$__FAIL__\\n"; }
-output_failn() { output 1 "$_FAIL_\\n"; output 2 "$__FAIL__\\n"; }
-is_present() { command -v "$1" >/dev/null 2>&1; }
-get_url_filesize() {
- local url="$1" size size_command
- [ -n "$1" ] || return 0
- is_present 'curl' || return 0
- size_command='curl --silent --insecure --fail --head --request GET'
- size="$($size_command "$url" | grep -Po '^[cC]ontent-[lL]ength: \K\w+')"
- echo -en "$size"
-}
+readonly adbFunctionsFile='/etc/init.d/adblock-fast'
+if [ -s "$adbFunctionsFile" ]; then
+# shellcheck source=../../etc/init.d/adblock-fast
+ . "$adbFunctionsFile"
+else
+ printf "%b: adblock-fast init.d file (%s) not found! \n" '\033[0;31mERROR\033[0m' "$adbFunctionsFile"
+fi
# Transition from simple-adblock
_enable_url() {
include $(TOPDIR)/rules.mk
PKG_NAME:=aria2
-PKG_VERSION:=1.36.0
-PKG_RELEASE:=2
+PKG_VERSION:=1.37.0
+PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
PKG_SOURCE_URL:=https://github.com/aria2/aria2/releases/download/release-$(PKG_VERSION)/
-PKG_HASH:=58d1e7608c12404f0229a3d9a4953d0d00c18040504498b483305bcb3de907a5
+PKG_HASH:=60a420ad7085eb616cb6e2bdf0a7206d68ff3d37fb5a956dc44242eb2f79b66b
PKG_INSTALL:=1
PKG_BUILD_PARALLEL:=1
PKG_BUILD_FLAGS:=gc-sections lto
PKG_NAME:=banip
PKG_VERSION:=0.9.2
-PKG_RELEASE:=1
+PKG_RELEASE:=4
PKG_LICENSE:=GPL-3.0-or-later
PKG_MAINTAINER:=Dirk Brenken <dev@brenken.org>
for pid in ${pids}; do
pids="${pids} $(pgrep -P "${pid}" 2>/dev/null)"
done
+ for pid in ${pids}; do
+ kill -INT "${pid}" >/dev/null 2>&1
+ done
fi
- for pid in ${pids}; do
- kill -INT "${pid}" >/dev/null 2>&1
- done
: >"${ban_rdapfile}"
: >"${ban_pidfile}"
}
# restore local backups
#
- if { [ "${ban_action}" != "reload" ] || [ "${feed_url}" = "local" ] || [ -n "${ban_etagparm}" ]; } && [ "${feed%v*}" != "allowlist" ] && [ "${feed%v*}" != "blocklist" ]; then
- if [ -n "${ban_etagparm}" ] && [ "${ban_action}" = "reload" ] && [ "${feed_url}" != "local" ]; then
+ if [ "${feed%v*}" != "blocklist" ]; then
+ if [ -n "${ban_etagparm}" ] && [ "${ban_action}" = "reload" ] && [ "${feed_url}" != "local" ] && [ "${feed%v*}" != "allowlist" ]; then
etag_rc="0"
if [ "${feed%v*}" = "country" ]; then
for country in ${ban_country}; do
fi
fi
if [ "${etag_rc}" = "0" ] || [ "${ban_action}" != "reload" ] || [ "${feed_url}" = "local" ]; then
- f_restore "${feed}" "${feed_url}" "${tmp_load}" "${etag_rc}"
+ if [ "${feed%v*}" = "allowlist" ] && [ ! -f "${tmp_allow}" ]; then
+ f_restore "allowlist" "-" "${tmp_allow}" "${etag_rc}"
+ else
+ f_restore "${feed}" "${feed_url}" "${tmp_load}" "${etag_rc}"
+ fi
restore_rc="${?}"
feed_rc="${restore_rc}"
fi
fi
- # prepare local allowlist
+ # prepare local/remote allowlist
#
if [ "${feed%v*}" = "allowlist" ] && [ ! -f "${tmp_allow}" ]; then
"${ban_catcmd}" "${ban_allowlist}" 2>/dev/null >"${tmp_allow}"
+ feed_rc="${?}"
for feed_url in ${ban_allowurl}; do
feed_log="$("${ban_fetchcmd}" ${ban_fetchparm} "${tmp_load}" "${feed_url}" 2>&1)"
feed_rc="${?}"
"${ban_catcmd}" "${tmp_load}" 2>/dev/null >>"${tmp_allow}"
else
f_log "info" "download for feed '${feed%v*}' failed (rc: ${feed_rc:-"-"}/log: ${feed_log})"
+ break
fi
done
+ if [ "${feed_rc}" = "0" ]; then
+ f_backup "allowlist" "${tmp_allow}"
+ elif [ -z "${restore_rc}" ] && [ "${feed_rc}" != "0" ]; then
+ f_restore "allowlist" "-" "${tmp_allow}" "${feed_rc}"
+ fi
+ feed_rc="${?}"
fi
# handle local feeds
# load generated nft file in banIP table
#
if [ "${feed_rc}" = "0" ]; then
- cnt_dl="$("${ban_awkcmd}" 'END{printf "%d",NR}' "${tmp_split}" 2>/dev/null)"
+ if [ "${feed%v*}" = "allowlist" ]; then
+ cnt_dl="$("${ban_awkcmd}" 'END{printf "%d",NR}' "${tmp_allow}" 2>/dev/null)"
+ else
+ cnt_dl="$("${ban_awkcmd}" 'END{printf "%d",NR}' "${tmp_split}" 2>/dev/null)"
+ fi
if [ "${cnt_dl:-"0"}" -gt "0" ] || [ "${feed_url}" = "local" ] || [ "${feed%v*}" = "allowlist" ] || [ "${feed%v*}" = "blocklist" ]; then
feed_log="$("${ban_nftcmd}" -f "${tmp_nft}" 2>&1)"
feed_rc="${?}"
cnt_elements="$((cnt_elements + $("${ban_nftcmd}" -j list set inet banIP "${object}" 2>/dev/null | "${ban_jsoncmd}" -qe '@.nftables[*].set.elem[*]' | wc -l 2>/dev/null)))"
done
fi
- runtime="action: ${ban_action:-"-"}, fetch: ${ban_fetchcmd##*/}, duration: ${duration:-"-"}, date: $(date "+%Y-%m-%d %H:%M:%S")"
+ runtime="action: ${ban_action:-"-"}, log: ${ban_logreadcmd##*/}, fetch: ${ban_fetchcmd##*/}, duration: ${duration:-"-"}, date: $(date "+%Y-%m-%d %H:%M:%S")"
fi
[ -s "${ban_customfeedfile}" ] && custom_feed="1"
[ "${ban_splitsize:-"0"}" -gt "0" ] && split="1"
},
"urlhaus":{
"url_4": "https://urlhaus.abuse.ch/downloads/ids/",
- "rule_4": "match($0,/(([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5]))/){printf \"%s,\\n\",substr($0,RSTART,RLENGTH)}",
+ "rule_4": "match($0,/(content:\"([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5]))/){printf \"%s,\\n\",substr($0,RSTART+9,RLENGTH-9)}",
"descr": "urlhaus IDS IPs"
},
"urlvir":{
[ "${action}" = "boot" ] && "${ban_init}" running && exit 0
{ [ "${action}" = "stop" ] || [ "${action}" = "report" ] || [ "${action}" = "search" ] || [ "${action}" = "survey" ] || [ "${action}" = "lookup" ]; } && ! "${ban_init}" running && exit 0
+[ ! -r "${ban_funlib}" ] && { [ "${action}" = "boot" ] || [ "${action}" = "start" ] || [ "${action}" = "restart" ] || [ "${action}" = "reload" ] || [ "${action}" = "stop" ] || [ "${action}" = "report" ] || [ "${action}" = "search" ] || [ "${action}" = "lookup" ] || [ "${action}" = "status" ]; } && exit 1
[ -d "${ban_lock}" ] && { [ "${action}" = "boot" ] || [ "${action}" = "start" ] || [ "${action}" = "restart" ] || [ "${action}" = "reload" ] || [ "${action}" = "lookup" ]; } && exit 1
[ ! -d "${ban_lock}" ] && { [ "${action}" = "boot" ] || [ "${action}" = "start" ] || [ "${action}" = "restart" ] || [ "${action}" = "reload" ] || [ "${action}" = "lookup" ]; } && mkdir -p "${ban_lock}"
}
start_service() {
+ [ -z "$(command -v "f_system")" ] && . "${ban_funlib}"
if "${ban_init}" enabled; then
- [ -z "$(command -v "f_system")" ] && . "${ban_funlib}"
f_rmpid
procd_open_instance "banip-service"
procd_set_param command "${ban_service}" "${@:-"${action}"}"
procd_set_param stderr 1
procd_close_instance
else
- [ -z "$(command -v "f_system")" ] && . "${ban_funlib}"
f_log "err" "banIP service autostart is disabled"
rm -rf "${ban_lock}"
fi
+++ /dev/null
-include $(TOPDIR)/rules.mk
-
-PKG_NAME:=cni-protocol
-PKG_VERSION:=20231008
-PKG_RELEASE:=1
-
-PKG_MAINTAINER:=Oskari Rauta <oskari.rauta@gmail.com>
-
-include $(INCLUDE_DIR)/package.mk
-
-define Package/cni-protocol
- SECTION:=net
- CATEGORY:=Network
- TITLE:=cni netifd protocol
- PKGARCH:=all
-endef
-
-define Package/cni-protocol/description
- protocol support for netavark/cni networks for netifd
- makes defining networks for podman and other similar
- systems easier and simple.
-
- with protocol, a network where firewall and portmapper
- management is disabled, control of firewalling, whether
- it was exposing ports, and forwarding to them from wan,
- or limiting/accepting access to other networks such
- as lan can made through openwrt's own firewalling
- configuration.
-
- example configuration could be as following:
- - lan network: 10.0.0.0/16 (255.255.0.0)
- - container network: 10.129.0.1/24 (255.255.255.0)
-
- Add a network configuration for your container network
- using cni protocol. Then create firewall zone for it.
-
- You could create a new container/pod with static ip
- address 10.129.0.2 (as 10.129.0.1 as container network's
- gateway).
-
- Easily define permissions so that local networks can
- connect to cni network, but not the other way around.
- Also you want to allow forwarding from/to wan.
-
- Now, as cni cannot access local dns, make a rule for
- your firewall to accept connections from cni network
- to port 53 (dns).
-
- Now all you have to do, is make redirects to your firewall
- and point them to 10.129.0.2 and connections from wan are
- redirectered to containers/pods.
-
- Protocol has 2 settings: device and delay. Sometimes polling
- interfaces takes some time, and in that case you might want
- to add few seconds to delay. Otherwise, it can be excluded
- from configuration.
-endef
-
-define Build/Configure
-endef
-
-define Build/Compile
-endef
-
-define Package/cni-protocol/install
- $(INSTALL_DIR) $(1)/lib/netifd/proto
- $(INSTALL_BIN) ./files/cni.sh $(1)/lib/netifd/proto/cni.sh
-endef
-
-$(eval $(call BuildPackage,cni-protocol))
+++ /dev/null
-#!/bin/sh
-
-[ -n "$INCLUDE_ONLY" ] || {
- . /lib/functions.sh
- . ../netifd-proto.sh
- init_proto "$@"
-}
-
-proto_cni_init_config() {
- no_device=0
- available=0
-
- proto_config_add_string "device:device"
- proto_config_add_int "delay"
-}
-
-proto_cni_setup() {
- local cfg="$1"
- local iface="$2"
- local device delay
-
- json_get_vars device delay
-
- [ -n "$device" ] || {
- echo "No cni interface specified"
- proto_notify_error "$cfg" NO_DEVICE
- proto_set_available "$cfg" 0
- return 1
- }
-
- [ -n "$delay" ] && sleep "$delay"
-
- [ -L "/sys/class/net/${iface}" ] || {
- echo "The specified interface $iface is not present"
- proto_notify_error "$cfg" NO_DEVICE
- proto_set_available "$cfg" 0
- return 1
- }
-
- local ipaddr netmask broadcast route routemask routesrc
-
- ipaddr=$(ip -4 -o a show "$iface" | awk '{ print $4 }' | cut -d '/' -f1)
- netmask=$(ip -4 -o a show "$iface" | awk '{ print $4 }' | cut -d '/' -f2)
- broadcast=$(ip -4 -o a show "$iface" | awk '{ print $6 }')
- route=$(ip -4 -o r show dev "$iface" | awk '{ print $1 }' | cut -d '/' -f1)
- routemask=$(ip -4 -o r show dev "$iface" | awk '{ print $1 }' | cut -d '/' -f2)
- routesrc=$(ip -4 -o r show dev "$iface" | awk '{ print $7 }')
-
- [ -z "$ipaddr" ] && {
- echo "interface $iface does not have ip address"
- proto_notify_error "$cfg" NO_IPADDRESS
- return 1
- }
-
- proto_init_update "$iface" 1
- [ -n "$ipaddr" ] && proto_add_ipv4_address "$ipaddr" "$netmask" "$broadcast" ""
- [ -n "$route" ] && proto_add_ipv4_route "$route" "$routemask" "" "$routesrc" ""
- proto_send_update "$cfg"
-}
-
-proto_cni_teardown() {
- local cfg="$1"
- return 0
-}
-
-[ -n "$INCLUDE_ONLY" ] || {
- add_protocol cni
-}
include $(TOPDIR)/rules.mk
PKG_NAME:=croc
-PKG_VERSION:=9.6.5
+PKG_VERSION:=9.6.6
PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://codeload.github.com/schollz/croc/tar.gz/v$(PKG_VERSION)?
-PKG_HASH:=2d3ba7bae3c49e3870e2f8523c6be00e92fe6e46828269a8cea34d4034102cad
+PKG_HASH:=9dd954e0068df2be416c71161665bfc283f150d30ba0bf96cee723701e93616f
PKG_LICENSE:=MIT
PKG_LICENSE_FILES:=LICENSE
include $(TOPDIR)/rules.mk
PKG_NAME:=crowdsec
-PKG_VERSION:=1.5.4
+PKG_VERSION:=1.5.5
PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://codeload.github.com/crowdsecurity/crowdsec/tar.gz/v$(PKG_VERSION)?
-PKG_HASH:=afa4021f77e9cb87d7fd11cd86146770836dc15cad1ae8a4edce1314b14be98a
+PKG_HASH:=ec7b2815405be4c3a1c9c3dcb1110030c29b7408dbf2a82d25537843c8831329
PKG_LICENSE:=MIT
PKG_LICENSE_FILES:=LICENSE
PKG_NAME:=ddns-scripts
PKG_VERSION:=2.8.2
-PKG_RELEASE:=41
+PKG_RELEASE:=42
PKG_LICENSE:=GPL-2.0
ENDPOINT="route53.amazonaws.com"
RECORD_TTL=300
RECORD_NAME="${lookup_host}."
+RECORD_VALUE="${__IP}"
[ ${use_ipv6} -eq 0 ] && RECORD_TYPE="A"
[ ${use_ipv6} -eq 1 ] && RECORD_TYPE="AAAA"
-RECORD_VALUE="${LOCAL_IP}"
+
HOSTED_ZONE_ID="${domain}"
API_PATH="/2013-04-01/hostedzone/${HOSTED_ZONE_ID}/rrset/"
--- /dev/null
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=dhtd
+PKG_VERSION:=0.2.5
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://codeload.github.com/mwarning/dhtd/tar.gz/v$(PKG_VERSION)?
+PKG_HASH:=0e239c969400537fda549b74f0555bddc2f1fe4ab3c00abe539970dfefab6599
+
+PKG_MAINTAINER:=Moritz Warning <moritzwarning@web.de>
+PKG_LICENSE:=MIT
+PKG_LICENSE_FILES:=LICENSE
+
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/dhtd
+ SECTION:=net
+ CATEGORY:=Network
+ SUBMENU:=IP Addresses and Names
+ TITLE:=DHT Daemon
+ URL:=https://github.com/mwarning/dhtd
+endef
+
+define Package/dhtd/description
+ Standalone BitTorrent DHT daemon. Lookup and announce
+ hash identifiers via command line interface.
+endef
+
+MAKE_FLAGS += FEATURES="cli lpd"
+
+define Package/dhtd/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/build/dhtd $(1)/usr/bin/
+ $(LN) /usr/bin/dhtd $(1)/usr/bin/dhtd-ctl
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(INSTALL_BIN) files/dhtd.init $(1)/etc/init.d/dhtd
+ $(INSTALL_DIR) $(1)/etc/config
+ $(INSTALL_CONF) files/dhtd.config $(1)/etc/config/dhtd
+endef
+
+$(eval $(call BuildPackage,dhtd))
--- /dev/null
+##
+## DHTd is a distributed hash table daemon that uses the BitTorrent network.
+##
+
+config dhtd
+ option enabled 1
+
+## Add hashes to announce them to the network
+# list announce '00112233445566778899aabbcceeff0011223344'
+
+## Load and store good nodes every 24h and on start/shutdown.
+# option peerfile '/etc/dhtd/peers.txt'
+
+## Add static peer addresses.
+ list peer 'bttracker.debian.org:6881'
+ list peer 'router.bittorrent.com:6881'
+
+## Execute a script for each result
+# option execute '/root/on_result.sh'
+
+## Bind the DHT to this port.
+# option port '6881'
+
+## Limit DHT communication to this interface.
+# option ifname 'lan'
+
+## Verbosity: quiet, verbose or debug
+# option verbosity 'quiet'
+
+## Disable multicast peer discovery on the LAN.
+# option lpd_disable '1'
+
+## Path for dhtd-cli to connect to.
+# option cli_path '/tmp/dhtd.sock'
--- /dev/null
+#!/bin/sh /etc/rc.common
+
+START=95
+USE_PROCD=1
+PROG=/usr/bin/dhtd
+OPTS=""
+
+
+boot() {
+ # Wait for the loopback interface to be ready
+ ubus -t 30 wait_for network.interface network.loopback 2>/dev/null
+ rc_procd start_service
+}
+
+xappend() {
+ local name="$2" value="$1"
+ OPTS="$OPTS\n--${name//_/-} ${value//'/\\'}"
+}
+
+append_opts_list() {
+ local name cfg="$1"; shift
+ for name in $*; do
+ config_list_foreach "$cfg" "$name" xappend "$name"
+ done
+}
+
+append_opts() {
+ local name value cfg="$1"; shift
+ for name in $*; do
+ config_get value "$cfg" "$name"
+ [ -n "$value" ] && xappend "$value" "$name"
+ done
+}
+
+append_opts_boolean() {
+ local name value cfg="$1"; shift
+ for name in $*; do
+ config_get_bool value "$cfg" "$name" 0
+ [ $value -gt 0 ] && xappend '' $name
+ done
+}
+
+section_enabled() {
+ config_get_bool enabled "$1" 'enabled' 0
+ [ $enabled -gt 0 ]
+}
+
+start_instance() {
+ local cfg="$1"
+ local CONFIG_FILE=/tmp/dhtd.${cfg}.conf
+
+ section_enabled "$cfg" || return
+ . /lib/functions/network.sh
+
+ OPTS=""
+
+ append_opts "$cfg" verbosity peerfile port execute
+
+ config_get ifname "$cfg" "ifname"
+ if network_get_device IFNAME "$ifname";then
+ xappend "$IFNAME" "ifname"
+ else
+ [ -n "$ifname" ] && xappend "$ifname" "ifname"
+ fi
+
+ append_opts_list "$cfg" announce peer
+
+ append_opts_boolean "$cfg" lpd_disable ipv4 ipv6
+
+ # Close stdin when command line interface is present
+ if [ $($PROG --version | grep -c cli) -eq 1 ]; then
+ xappend "" "cli_disable_stdin"
+ fi
+
+ echo -e "$OPTS" > $CONFIG_FILE
+
+ procd_open_instance
+ procd_set_param command $PROG
+ procd_set_param file $CONFIG_FILE
+ procd_set_param stderr 1
+ procd_set_param stdout 1
+ procd_append_param command --config $CONFIG_FILE
+ procd_close_instance
+}
+
+stop_instance() {
+ local cfg="$1"
+ local CONFIG_FILE=/tmp/dhtd.${cfg}.conf
+
+ rm -f $CONFIG_FILE
+}
+
+add_interface_trigger() {
+ local ifname
+
+ config_get ifname "$1" ifname
+
+ [ -n "$ifname" ] && procd_add_interface_trigger "interface.*" "$ifname" /etc/init.d/dhtd restart
+}
+
+service_triggers() {
+ procd_add_reload_trigger "dhtd"
+
+ config_load dhtd
+ config_foreach add_interface_trigger dhtd
+}
+
+start_service() {
+ config_load 'dhtd'
+ config_foreach start_instance 'dhtd'
+}
+
+stop_service() {
+ config_load 'dhtd'
+ config_foreach stop_instance 'dhtd'
+}
include $(TOPDIR)/rules.mk
PKG_NAME:=dnsproxy
-PKG_VERSION:=0.56.2
-PKG_RELEASE:=2
+PKG_VERSION:=0.59.1
+PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://codeload.github.com/AdguardTeam/dnsproxy/tar.gz/v$(PKG_VERSION)?
-PKG_HASH:=b20a77e88567fbcb80a07faa0f47aee7446b4d32ee7c17036fbdf07c03f05e3a
+PKG_HASH:=151616e2562b9bc8de85725293b264e7769d84fe1cd462e74be6fdc8505b0cbb
PKG_MAINTAINER:=Tianling Shen <cnsztl@immortalwrt.org>
PKG_LICENSE:=Apache-2.0
--- /dev/null
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=external-protocol
+PKG_VERSION:=20231119
+PKG_RELEASE:=1
+
+PKG_MAINTAINER:=Oskari Rauta <oskari.rauta@gmail.com>
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/external-protocol
+ SECTION:=net
+ CATEGORY:=Network
+ TITLE:=externally managed protocol
+ PKGARCH:=all
+endef
+
+define Package/external-protocol/description
+ external protocol is a general protocol for assisting
+ setup of many virtual devices that lack proper
+ protocol support in openwrt. Such as netavark, cni and
+ netbird for example. External protocol is supposed
+ to be managed with external software, not directly.
+
+ external protocol works automaticly on the background
+ and sets up netifd details when interface comes up or
+ goes down. This allows one to easily add interface to
+ a firewall zone.
+
+ as a example use case, podman, with network where it's
+ internal firewall and portmapper are disabled, control
+ of firewalling, whether it was exposing ports or
+ limiting/accepting access between networks, such as
+ lan can be made through openwrt's own firewalling
+ configuration if you used external protocol.
+
+ podman example configuration could be as following:
+ - lan network: 10.0.0.0/16 (255.255.0.0)
+ - container network: 10.129.0.1/24 (255.255.255.0)
+
+ Add a network configuration for your container network
+ using external protocol. Then create firewall zone for it.
+
+ You could create a new container/pod with static ip
+ address 10.129.0.2 (as 10.129.0.1 as container network's
+ gateway).
+
+ Easily define permissions so that local networks can
+ connect to container network, but not the other way around.
+ Also you want to allow forwarding from/to wan.
+
+ Now, as container cannot access local dns, make a rule for
+ your firewall to accept connections from container network
+ to port 53 (dns).
+
+ Now all you have to do, is make redirects to your firewall
+ and point them to 10.129.0.2 and connections from wan are
+ redirectered to containers/pods.
+
+ external protocol also works for other applications as
+ well that are using veth/tun/etc devices and don't have
+ a hand-tailored protocol available, such as vpn service
+ netbird.
+
+ Protocol has 3 settings: device, searchdomain and delay.
+ Sometimes polling interfaces takes some time, and in
+ that case you might want to add few seconds to delay.
+ Otherwise, it can be excluded from configuration.
+ Option for searchdomain is also completely optional.
+
+ package was previously known as cni protocol but as
+ it can be used on so many other things, naming became
+ mis-leading and it was renamed to external protocol.
+endef
+
+define Build/Configure
+endef
+
+define Build/Compile
+endef
+
+define Package/external-protocol/install
+ $(INSTALL_DIR) $(1)/lib/netifd/proto
+ $(INSTALL_BIN) ./files/external.sh $(1)/lib/netifd/proto/external.sh
+endef
+
+$(eval $(call BuildPackage,external-protocol))
--- /dev/null
+#!/bin/sh
+
+[ -n "$INCLUDE_ONLY" ] || {
+ . /lib/functions.sh
+ . ../netifd-proto.sh
+ init_proto "$@"
+}
+
+proto_external_init_config() {
+ no_device=0
+ available=0
+
+ proto_config_add_string "device:device"
+ proto_config_add_string "searchdomain"
+ proto_config_add_int "delay"
+}
+
+proto_external_setup() {
+ local cfg="$1"
+ local iface="$2"
+ local device searchdomain delay
+
+ json_get_vars device searchdomain delay
+
+ [ -n "$device" ] || {
+ echo "External protocol interface is not specified"
+ proto_notify_error "$cfg" NO_DEVICE
+ proto_set_available "$cfg" 0
+ return 1
+ }
+
+ [ -n "$delay" ] && sleep "$delay"
+
+ [ -L "/sys/class/net/${iface}" ] || {
+ echo "External protocol interface $iface is not present"
+ proto_notify_error "$cfg" NO_DEVICE
+ proto_set_available "$cfg" 0
+ return 1
+ }
+
+ IP4ADDRS=
+ IP6ADDRS=
+
+ local addresses="$(ip -json address list dev "$iface")"
+ json_init
+ json_load "{\"addresses\":${addresses}}"
+
+ if json_is_a addresses array; then
+ json_select addresses
+ json_select 1
+
+ if json_is_a addr_info array; then
+ json_select addr_info
+
+ local i=1
+ while json_is_a ${i} object; do
+ json_select ${i}
+ json_get_vars scope family local prefixlen broadcast
+
+ if [ "${scope}" == "global" ]; then
+ case "${family}" in
+ inet)
+ append IP4ADDRS "$local/$prefixlen/$broadcast/"
+ ;;
+
+ inet6)
+ append IP6ADDRS "$local/$prefixlen/$broadcast///"
+ ;;
+ esac
+ fi
+
+ json_select ..
+ i=$(( i + 1 ))
+ done
+ fi
+ fi
+
+ IP4ROUTES=
+ IP6ROUTES=
+
+ local routes="$(ip -json route list dev "$iface")"
+ json_init
+ json_load "{\"routes\":${routes}}"
+
+ if json_is_a routes array;then
+ json_select routes
+
+ local i=1
+ while json_is_a ${i} object; do
+ json_select ${i}
+ json_get_vars dst gateway metric prefsrc
+
+ case "${dst}" in
+ *:*/*)
+ append IP6ROUTES "$dst/$gateway/$metric///$prefsrc"
+ ;;
+ *.*/*)
+ append IP4ROUTES "$dst/$gateway/$metric///$prefsrc"
+ ;;
+ *:*)
+ append IP6ROUTES "$dst/128/$gateway/$metric///$prefsrc"
+ ;;
+ *.*)
+ append IP4ROUTES "$dst/32/$gateway/$metric///$prefsrc"
+ ;;
+ esac
+
+ json_select ..
+ i=$(( i + 1 ))
+ done
+ fi
+
+ [ -z "${IP4ADDRS}" -a -z "${IP6ADDRS}" ] && {
+ echo "interface $iface does not have ip address"
+ proto_notify_error "$cfg" NO_IPADDRESS
+ return 1
+ }
+
+ proto_init_update "$iface" 1
+
+ PROTO_IPADDR="${IP4ADDRS}"
+ PROTO_IP6ADDR="${IP6ADDRS}"
+
+ PROTO_ROUTE="${IP4ROUTES}"
+ PROTO_ROUTE6="${IP6ROUTES}"
+
+ [ -n "$searchdomain" ] && proto_add_dns_search "$searchdomain"
+
+ echo "$iface is up"
+
+ proto_send_update "$cfg"
+}
+
+proto_external_teardown() {
+ local cfg="$1"
+ return 0
+}
+
+[ -n "$INCLUDE_ONLY" ] || {
+ add_protocol external
+}
PKG_NAME:=fail2ban
PKG_VERSION:=0.11.2
-PKG_RELEASE:=8
+PKG_RELEASE:=9
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://codeload.github.com/fail2ban/fail2ban/tar.gz/$(PKG_VERSION)?
--- /dev/null
+From 7e2ab36d86998575853150c0a57de5e22518cf66 Mon Sep 17 00:00:00 2001
+From: sebres <info@sebres.de>
+Date: Tue, 21 Jun 2022 16:55:57 +0200
+Subject: [PATCH] move global groups to start of expression (python 3.11
+ compat)
+
+[remove change to regex not in 0.11.2]
+Signed-off-by: Jeffery To <jeffery.to@gmail.com>
+---
+ fail2ban/client/fail2banregex.py | 2 +-
+ fail2ban/server/datetemplate.py | 8 ++++++++
+ 2 files changed, 9 insertions(+), 1 deletion(-)
+
+--- a/fail2ban/server/datetemplate.py
++++ b/fail2ban/server/datetemplate.py
+@@ -35,6 +35,7 @@ logSys = getLogger(__name__)
+ # check already grouped contains "(", but ignores char "\(" and conditional "(?(id)...)":
+ RE_GROUPED = re.compile(r'(?<!(?:\(\?))(?<!\\)\((?!\?)')
+ RE_GROUP = ( re.compile(r'^((?:\(\?\w+\))?\^?(?:\(\?\w+\))?)(.*?)(\$?)$'), r"\1(\2)\3" )
++RE_GLOBALFLAGS = re.compile(r'((?:^|(?!<\\))\(\?[a-z]+\))')
+
+ RE_EXLINE_NO_BOUNDS = re.compile(r'^\{UNB\}')
+ RE_EXLINE_BOUND_BEG = re.compile(r'^\{\^LN-BEG\}')
+@@ -110,6 +111,11 @@ class DateTemplate(object):
+ # because it may be very slow in negative case (by long log-lines not matching pattern)
+
+ regex = regex.strip()
++ # cut global flags like (?iu) from RE in order to pre-set it after processing:
++ gf = RE_GLOBALFLAGS.search(regex)
++ if gf:
++ regex = RE_GLOBALFLAGS.sub('', regex, count=1)
++ # check word boundaries needed:
+ boundBegin = wordBegin and not RE_NO_WRD_BOUND_BEG.search(regex)
+ boundEnd = wordEnd and not RE_NO_WRD_BOUND_END.search(regex)
+ # if no group add it now, should always have a group(1):
+@@ -135,6 +141,8 @@ class DateTemplate(object):
+ self.flags |= DateTemplate.LINE_END
+ # remove possible special pattern "**" in front and end of regex:
+ regex = RE_DEL_WRD_BOUNDS[0].sub(RE_DEL_WRD_BOUNDS[1], regex)
++ if gf: # restore global flags:
++ regex = gf.group(1) + regex
+ self._regex = regex
+ logSys.log(7, ' constructed regex %s', regex)
+ self._cRegex = None
--- /dev/null
+From 4337e366163278815ea9fc6c952bffb579e885a0 Mon Sep 17 00:00:00 2001
+From: sebres <info@sebres.de>
+Date: Tue, 21 Jun 2022 16:56:57 +0200
+Subject: [PATCH] wrap global flags like ((?i)xxx) or (?:(?i)xxx) to local
+ flags (?i:xxx) if supported by RE-engine in the python version
+
+---
+ fail2ban/server/failregex.py | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+--- a/fail2ban/server/failregex.py
++++ b/fail2ban/server/failregex.py
+@@ -91,6 +91,13 @@ R_MAP = {
+ "port": "fport",
+ }
+
++# map global flags like ((?i)xxx) or (?:(?i)xxx) to local flags (?i:xxx) if supported by RE-engine in this python version:
++try:
++ re.search("^re(?i:val)$", "reVAL")
++ R_GLOB2LOCFLAGS = ( re.compile(r"(?<!\\)\((?:\?:)?(\(\?[a-z]+)\)"), r"\1:" )
++except:
++ R_GLOB2LOCFLAGS = ()
++
+ def mapTag2Opt(tag):
+ tag = tag.lower()
+ return R_MAP.get(tag, tag)
+@@ -128,6 +135,9 @@ class Regex:
+ #
+ if regex.lstrip() == '':
+ raise RegexException("Cannot add empty regex")
++ # special handling wrapping global flags to local flags:
++ if R_GLOB2LOCFLAGS:
++ regex = R_GLOB2LOCFLAGS[0].sub(R_GLOB2LOCFLAGS[1], regex)
+ try:
+ self._regexObj = re.compile(regex, re.MULTILINE if multiline else 0)
+ self._regex = regex
PKG_NAME:=freeradius3
PKG_VERSION:=3.0.26
-PKG_RELEASE:=2
+PKG_RELEASE:=3
PKG_SOURCE:=freeradius-server-$(PKG_VERSION).tar.bz2
PKG_SOURCE_URL:=https://github.com/FreeRADIUS/freeradius-server/releases/download/release_$(subst .,_,$(PKG_VERSION))/
define Package/freeradius3-common
$(call Package/freeradius3/Default)
TITLE:=common files
- DEPENDS:=+USE_GLIBC:libpthread +USE_GLIBC:libbsd +FREERADIUS3_OPENSSL:libopenssl +libcap +libpcap +libncurses +libpcre2 +libreadline +libtalloc +libatomic
+ DEPENDS:=+USE_GLIBC:libpthread +USE_GLIBC:libbsd +FREERADIUS3_OPENSSL:libopenssl +libcap +libpcap +libncurses +libreadline +libtalloc +libatomic
endef
define Package/freeradius3-default
--with-radacctdir=/var/db/radacct \
--with-logdir=/var/log \
--without-edir \
+ --without-pcre \
--without-snmp \
--without-rlm_cache \
--without-rlm_cache_memcached \
--$(if $(CONFIG_GENSIO_GLIB),with,without)-glib \
--$(if $(CONFIG_GENSIO_TCL),with,without)-tcl \
--without-afskmdm \
- --without-ax25 \
--without-alsa \
+ --without-ax25 \
+ --without-cm108gpio \
+ --without-dnssd \
--without-go \
--without-ipmisol \
--without-kiss \
--without-openipmi \
--without-portaudio \
--without-sound \
+ --without-udev \
--with-cplusplus \
--with-flock-locking \
--with-uucp-locking \
PYTHON_LIBS="$(shell $(STAGING_DIR)/host/bin/$(PYTHON3)-config --ldflags) -l${PYTHON3}" \
PYTHON_CPPFLAGS="$(shell $(STAGING_DIR)/host/bin/$(PYTHON3)-config --includes)" \
PYTHON="$(STAGING_DIR_HOSTPKG)/bin/$(PYTHON3)"
+
+MAKE_VARS += \
+ PYTHON_LIBS="$(shell $(STAGING_DIR)/host/bin/$(PYTHON3)-config --ldflags) -l${PYTHON3}"
else
CONFIGURE_ARGS += \
--without-python \
--- /dev/null
+From 6bbc3056c4b9192010d888672d97810609ee23f9 Mon Sep 17 00:00:00 2001
+From: Michael Heimpold <mhei@heimpold.de>
+Date: Sat, 18 Nov 2023 21:46:15 +0100
+Subject: [PATCH] Ensure that $ax_python_devel_found is defined
+
+Otherwise in case of --without-python, it triggers an error like:
+-snip-
+...
+checking consistency of all components of python development environment... yes
+./configure: line 23729: test: =: unary operator expected
+...
+-snap-
+
+Signed-off-by: Michael Heimpold <mhei@heimpold.de>
+---
+ configure.ac | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/configure.ac
++++ b/configure.ac
+@@ -1997,6 +1997,9 @@ if test "x$trypython" = "xyes"; then
+ PYTHON_CPPFLAGS="$pythoncflags"
+ fi
+ AX_PYTHON_DEVEL([], [true])
++ ax_python_devel_found=yes
++else
++ ax_python_devel_found=no
+ fi
+ if test $ax_python_devel_found = yes; then
+ AX_PROG_PYTHON_VERSION([3.0.0],
--- /dev/null
+--- a/m4/ax_python_devel.m4
++++ b/m4/ax_python_devel.m4
+@@ -72,7 +72,7 @@
+ # modified version of the Autoconf Macro, you may extend this special
+ # exception to the GPL to apply to your modified version as well.
+
+-#serial 34
++#serial 35
+
+ AU_ALIAS([AC_PYTHON_DEVEL], [AX_PYTHON_DEVEL])
+ AC_DEFUN([AX_PYTHON_DEVEL],[
--- /dev/null
+From f53fc85ee9734dd21447ea3438b7ba1edcd1bcf8 Mon Sep 17 00:00:00 2001
+From: Michael Heimpold <mhei@heimpold.de>
+Date: Tue, 21 Nov 2023 23:27:45 +0100
+Subject: [PATCH] Revert ax_pkg_swig.m4 to latest vanilla version
+
+And instead of extending the macro, we can use the already
+create variable 'available_swig_vernum' to compare the
+required version number.
+
+Signed-off-by: Michael Heimpold <mhei@heimpold.de>
+---
+ configure.ac | 26 ++++++++++++--------------
+ m4/ax_pkg_swig.m4 | 20 +++++++++-----------
+ 2 files changed, 21 insertions(+), 25 deletions(-)
+
+--- a/configure.ac
++++ b/configure.ac
+@@ -1956,21 +1956,19 @@ AC_CHECK_LIB(nsl, main, [HAVE_LIBNSL=1;
+ SWIG_DIR=
+ SWIG_CPP_DIR=
+ SWIG=
+-SWIG_NUMVERSION=0
++available_swig_vernum=0
+ if test "x$tryswig" = "xyes"; then
+ if test "x$swigprog" != "x"; then
+ SWIG="$swigprog"
+ fi
+- AX_PKG_SWIG([1.3.21])
+- if test "x$SWIG" != "x"; then
+- AC_DEFINE([HAVE_SWIG], [], [Have swig installed])
+- SWIG_DIR=swig
+- if test $SWIG_NUMVERSION -ge 40100; then
+- SWIG_CPP_DIR=swig
+- else
+- AC_MSG_WARN([SWIG version >= 4.1.0 is required for C++ swig.])
+- fi
+- fi
++ AX_PKG_SWIG(4.1.0,
++ [
++ AC_DEFINE([HAVE_SWIG], [], [Have swig installed])
++ SWIG_DIR=swig
++ SWIG_CPP_DIR=swig
++ ], [
++ AC_MSG_WARN([SWIG version >= 4.1.0 is required for C++ swig.])
++ ])
+ fi
+ AC_SUBST(SWIG_DIR)
+ AC_SUBST(SWIG_CPP_DIR)
+@@ -2055,7 +2053,7 @@ AC_SUBST(PYTHON_UNDEF_LIBS)
+ PYTHON_EXECUTABLE="${PYTHON}"
+ AC_SUBST(PYTHON_EXECUTABLE)
+
+-if test $SWIG_NUMVERSION -ge 40100 -a "${enable_shared}" = yes; then
++if test $available_swig_vernum -ge 40100 -a "${enable_shared}" = yes; then
+ trygo=yes
+ else
+ trygo=no
+@@ -2076,7 +2074,7 @@ AC_ARG_WITH(go,
+ fi,
+ )
+
+-if test $trygo = yes -a $SWIG_NUMVERSION -lt 40100; then
++if test $trygo = yes -a $available_swig_vernum -lt 40100; then
+ AC_MSG_ERROR([Go enabled, but swig version must be >= 4.1.0 for that])
+ fi
+ GODIR=
+@@ -2363,7 +2361,7 @@ pr_op " shared libraries: " $enable_sh
+ pr_op " sctp sendv: " $ac_cv_lib_sctp_sctp_sendv
+ pr_vop " python: " "$ax_python_version"
+ if test "$SWIG_CPP_DIR" = "swig"; then
+- prrw " swig: " "$SWIG_NUMVERSION"
++ prrw " swig: " "$available_swig_vernum"
+ else
+ prrw " swig: " "no"
+ fi
+--- a/m4/ax_pkg_swig.m4
++++ b/m4/ax_pkg_swig.m4
+@@ -19,11 +19,6 @@
+ # 1.3.17), AX_PKG_SWIG checks that the swig package is this version number
+ # or higher.
+ #
+-# If successful, SWIG_NUMVERSION is set to a numeric value for the
+-# version found in the format NNnnpp where NN is the major version,
+-# nn is the minor version, and pp is the patch version. This is
+-# easy to directly compare with a number.
+-#
+ # As usual, action-if-found is executed if SWIG is found, otherwise
+ # action-if-not-found is executed.
+ #
+@@ -41,6 +36,8 @@
+ # Copyright (c) 2008 Rafael Laboissiere <rafael@laboissiere.net>
+ # Copyright (c) 2008 Andrew Collier
+ # Copyright (c) 2011 Murray Cumming <murrayc@openismus.com>
++# Copyright (c) 2018 Reini Urban <rurban@cpan.org>
++# Copyright (c) 2021 Vincent Danjean <Vincent.Danjean@ens-lyon.org>
+ #
+ # 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
+@@ -68,14 +65,16 @@
+ # modified version of the Autoconf Macro, you may extend this special
+ # exception to the GPL to apply to your modified version as well.
+
+-#serial 13
++#serial 15
+
+ AC_DEFUN([AX_PKG_SWIG],[
+ # Find path to the "swig" executable.
+ AC_PATH_PROGS([SWIG],[swig swig3.0 swig2.0])
+ if test -z "$SWIG" ; then
+ m4_ifval([$3],[$3],[:])
+- elif test -n "$1" ; then
++ elif test -z "$1" ; then
++ m4_ifval([$2],[$2],[:])
++ else
+ AC_MSG_CHECKING([SWIG version])
+ [swig_version=`$SWIG -version 2>&1 | grep 'SWIG Version' | sed 's/.*\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\).*/\1/g'`]
+ AC_MSG_RESULT([$swig_version])
+@@ -86,12 +85,12 @@ AC_DEFUN([AX_PKG_SWIG],[
+ if test -z "$required_major" ; then
+ [required_major=0]
+ fi
+- [required=`echo $required | sed 's/[0-9]*[^0-9]//'`]
++ [required=`echo $required. | sed 's/[0-9]*[^0-9]//'`]
+ [required_minor=`echo $required | sed 's/[^0-9].*//'`]
+ if test -z "$required_minor" ; then
+ [required_minor=0]
+ fi
+- [required=`echo $required | sed 's/[0-9]*[^0-9]//'`]
++ [required=`echo $required. | sed 's/[0-9]*[^0-9]//'`]
+ [required_patch=`echo $required | sed 's/[^0-9].*//'`]
+ if test -z "$required_patch" ; then
+ [required_patch=0]
+@@ -126,10 +125,9 @@ AC_DEFUN([AX_PKG_SWIG],[
+ m4_ifval([$3],[$3],[])
+ else
+ AC_MSG_CHECKING([for SWIG library])
+- SWIG_LIB=`$SWIG -swiglib | tail -1`
++ SWIG_LIB=`$SWIG -swiglib | tr '\r\n' ' '`
+ AC_MSG_RESULT([$SWIG_LIB])
+ m4_ifval([$2],[$2],[])
+- SWIG_NUMVERSION=$available_swig_vernum
+ fi
+ else
+ AC_MSG_WARN([cannot determine SWIG version])
include $(TOPDIR)/rules.mk
PKG_NAME:=haproxy
-PKG_VERSION:=2.8.3
-PKG_RELEASE:=2
+PKG_VERSION:=2.8.4
+PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://www.haproxy.org/download/2.8/src
-PKG_HASH:=9ecc6ffe67a977d1ed279107bbdab790d73ae2a626bc38eee23fa1f6786a759e
+PKG_HASH:=81bacbf50ec6d0f7ecaaad7c03e59978b00322fbdad6ed4a989dd31754b6f25d
PKG_MAINTAINER:=Thomas Heil <heil@terminal-consulting.de>, \
Christian Lachner <gladiac@gmail.com>
#!/bin/sh
CLONEURL=https://git.haproxy.org/git/haproxy-2.8.git
-BASE_TAG=v2.8.3
+BASE_TAG=v2.8.4
TMP_REPODIR=tmprepo
PATCHESDIR=patches
include $(TOPDIR)/rules.mk
PKG_NAME:=hcxdumptool
-PKG_VERSION:=6.2.4
+PKG_VERSION:=6.3.2
PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://codeload.github.com/zerbea/hcxdumptool/tar.gz/$(PKG_VERSION)?
-PKG_HASH:=cadeb4b2f00da3a1df65cb53080e134f201ef73825d35049110764faf699028d
+PKG_HASH:=1f6fe2b4757a5f20adeb6cc469693b4d0e8c49ba290450e10a37699d9f9a2a42
PKG_MAINTAINER:=Andreas Nilsen <adde88@gmail.com>
PKG_LICENSE:=MIT
+++ /dev/null
---- a/hcxdumptool.c
-+++ b/hcxdumptool.c
-@@ -571,10 +571,6 @@ if(rebootflag == true)
- }
- }
-
--EVP_cleanup();
--CRYPTO_cleanup_all_ex_data();
--ERR_free_strings();
--
- if(errorcount != 0) exit(EXIT_FAILURE);
- if(totflag == true) exit(USER_EXIT_TOT);
- exit(EXIT_SUCCESS);
-@@ -7777,8 +7773,6 @@ return true;
- /*===========================================================================*/
- static inline bool tlsinit()
- {
--SSL_load_error_strings();
--OpenSSL_add_ssl_algorithms();
- if((tlsctx = SSL_CTX_new(SSLv23_server_method())) == NULL)
- {
- fprintf(stderr, "OpenSSl can't create SSL context\n");
-@@ -7797,7 +7791,6 @@ if(SSL_CTX_use_PrivateKey_file(tlsctx, e
- if((eaptlsctx = (eaptlsctx_t*)malloc(EAPTLSCTX_SIZE)) == NULL) return false;
- memset(eaptlsctx, 0, EAPTLSCTX_SIZE);
- SSL_CTX_set_session_cache_mode(tlsctx, SSL_SESS_CACHE_OFF);
--SSL_CTX_set_ecdh_auto(tlsctx, 1);
- SSL_CTX_set_verify(tlsctx, (SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE), eap_tls_clientverify_cb);
- #if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
- SSL_CTX_set_min_proto_version(tlsctx, TLS1_VERSION);
-@@ -7872,8 +7865,6 @@ if(gpiostatusled > 0)
- }
-
-
--ERR_load_crypto_strings();
--OpenSSL_add_all_algorithms();
- opensslversion = OpenSSL_version_num();
- opensslversionmajor = (opensslversion & 0x10000000L) >> 28;
- opensslversionminor = (opensslversion & 0x01100000L) >> 20;
include $(TOPDIR)/rules.mk
PKG_NAME:=hcxtools
-PKG_VERSION:=6.2.4
+PKG_VERSION:=6.3.2
PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://codeload.github.com/zerbea/hcxtools/tar.gz/$(PKG_VERSION)?
-PKG_HASH:=74299313dd15ed38f07b42201903ab85ebbc3ad220a01fff1bd5c967cfea817d
+PKG_HASH:=555e46a59df6a77c5aa73b99ffa8c1e84fa79e24ffaf5180de1d3a7f4ab7a470
PKG_MAINTAINER:=Andreas Nilsen <adde88@gmail.com>
PKG_LICENSE:=MIT
PKG_LICENSE_FILES:=license.txt
include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/meson.mk
define Package/hcxtools
SECTION:=net
for the use with latest hashcat or John the Ripper.
endef
-define Build/Compile
- $(MAKE) -C $(PKG_BUILD_DIR)/ \
- $(TARGET_CONFIGURE_OPTS) \
- CFLAGS="$(TARGET_CFLAGS)"
-endef
-
define Package/hcxtools/install
- $(INSTALL_DIR) $(1)/sbin
- $(INSTALL_BIN) $(PKG_BUILD_DIR)/hcxeiutool $(1)/sbin/
- $(INSTALL_BIN) $(PKG_BUILD_DIR)/hcxessidtool $(1)/sbin/
- $(INSTALL_BIN) $(PKG_BUILD_DIR)/hcxhash2cap $(1)/sbin/
- $(INSTALL_BIN) $(PKG_BUILD_DIR)/hcxhashcattool $(1)/sbin/
- $(INSTALL_BIN) $(PKG_BUILD_DIR)/hcxhashtool $(1)/sbin/
- $(INSTALL_BIN) $(PKG_BUILD_DIR)/hcxmactool $(1)/sbin/
- $(INSTALL_BIN) $(PKG_BUILD_DIR)/hcxpcapngtool $(1)/sbin/
- $(INSTALL_BIN) $(PKG_BUILD_DIR)/hcxpmkidtool $(1)/sbin/
- $(INSTALL_BIN) $(PKG_BUILD_DIR)/hcxpmktool $(1)/sbin/
- $(INSTALL_BIN) $(PKG_BUILD_DIR)/hcxpsktool $(1)/sbin/
- $(INSTALL_BIN) $(PKG_BUILD_DIR)/hcxwltool $(1)/sbin/
- $(INSTALL_BIN) $(PKG_BUILD_DIR)/whoismac $(1)/sbin/
- $(INSTALL_BIN) $(PKG_BUILD_DIR)/wlancap2wpasec $(1)/sbin/
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/hcxeiutool $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/hcxhash2cap $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/hcxhashtool $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/hcxpcapngtool $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/hcxpmktool $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/hcxpsktool $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/hcxwltool $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/whoismac $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/wlancap2wpasec $(1)/usr/bin/
endef
$(eval $(call BuildPackage,hcxtools))
+++ /dev/null
---- a/hcxhashtool.c
-+++ b/hcxhashtool.c
-@@ -107,9 +107,6 @@ static void closelists()
- {
- if(hashlist != NULL) free(hashlist);
- if(ouilist != NULL) free(ouilist);
--EVP_cleanup();
--CRYPTO_cleanup_all_ex_data();
--ERR_free_strings();
- return;
- }
- /*===========================================================================*/
-@@ -128,8 +125,6 @@ eapolwrittencount = 0;
- essidwrittencount = 0;
- hccapxwrittencount = 0;
- hccapwrittencount = 0;
--ERR_load_crypto_strings();
--OpenSSL_add_all_algorithms();
- if((hashlist = (hashlist_t*)calloc(hashlistcount, HASHLIST_SIZE)) == NULL) return false;
- if((ouilist = (ouilist_t*)calloc(ouilistcount, OUILIST_SIZE)) == NULL) return false;
- return true;
---- a/hcxpcapngtool.c
-+++ b/hcxpcapngtool.c
-@@ -366,9 +366,6 @@ if(eapmschapv2msglist != NULL) free(eapm
- if(eapmschapv2hashlist != NULL) free(eapmschapv2hashlist);
- if(tacacsplist != NULL) free(tacacsplist);
-
--EVP_cleanup();
--CRYPTO_cleanup_all_ex_data();
--ERR_free_strings();
- return;
- }
- /*===========================================================================*/
-@@ -377,8 +374,6 @@ static bool initlists()
- static unsigned long opensslversion;
- static const char nastring[] = { "N/A" };
-
--ERR_load_crypto_strings();
--OpenSSL_add_all_algorithms();
- opensslversion = OpenSSL_version_num();
- opensslversionmajor = (opensslversion & 0x10000000L) >> 28;
- opensslversionminor = (opensslversion & 0x01100000L) >> 20;
---- a/hcxpmktool.c
-+++ b/hcxpmktool.c
-@@ -923,8 +923,6 @@ while((auswahl = getopt_long(argc, argv,
- }
- }
-
--ERR_load_crypto_strings();
--OpenSSL_add_all_algorithms();
- printf("\n");
- if((essidstring != NULL) && (pskstring != NULL) && (pmkstring == NULL) && (hashlinestring == NULL))
- {
-@@ -956,9 +954,6 @@ else if((essidstring != NULL) && (pskstr
- }
-
- printf("\n");
--EVP_cleanup();
--CRYPTO_cleanup_all_ex_data();
--ERR_free_strings();
- return EXIT_SUCCESS;
- }
- /*===========================================================================*/
---- a/hcxpsktool.c
-+++ b/hcxpsktool.c
-@@ -63,8 +63,6 @@ essidglen = 32;
- t = time(NULL);
- tm = localtime(&t);
- thisyear = tm->tm_year +1900;
--ERR_load_crypto_strings();
--OpenSSL_add_all_algorithms();
- return;
- }
- /*===========================================================================*/
-@@ -2832,10 +2830,6 @@ if(pskname != NULL)
- fclose(fhpsk);
- }
-
--EVP_cleanup();
--CRYPTO_cleanup_all_ex_data();
--ERR_free_strings();
--
- return EXIT_SUCCESS;
- }
- /*===========================================================================*/
PKG_NAME:=https-dns-proxy
PKG_VERSION:=2023-10-25
-PKG_RELEASE:=1
+PKG_RELEASE:=4
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL:=https://github.com/aarond10/https_dns_proxy/
PKG_SOURCE_DATE:=$(PKG_VERSION)
PKG_SOURCE_VERSION:=977341a4e35a37ee454e97e82caf4276b1b4961a
PKG_MIRROR_HASH:=8622846f1038ac05436a48d9b36a07c516cbb6504ce68e7ee8c5529788fac39b
+
PKG_MAINTAINER:=Stan Grishin <stangri@melmac.ca>
PKG_LICENSE:=MIT
PKG_LICENSE_FILES:=LICENSE
on_boot_trigger=
-str_contains() { [ -n "$1" ] &&[ -n "$2" ] && [ "${1//$2}" != "$1" ]; }
+dnsmasq_restart() { [ -x /etc/init.d/dnsmasq ] || return 1; /etc/init.d/dnsmasq restart >/dev/null 2>&1; }
is_mac_address() { expr "$1" : '[0-9A-F][0-9A-F]:[0-9A-F][0-9A-F]:[0-9A-F][0-9A-F]:[0-9A-F][0-9A-F]:[0-9A-F][0-9A-F]:[0-9A-F][0-9A-F]$' >/dev/null; }
is_ipv4() { expr "$1" : '[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*$' >/dev/null; }
is_ipv6() { ! is_mac_address "$1" && str_contains "$1" ":"; }
+is_resolver_working() { resolveip -t 3 one.one.one.one >/dev/null 2>&1; }
output() {
local msg memmsg logmsg
local sharedMemoryOutput="/dev/shm/$packageName-output"
output_okn() { output "${_OK_}\\n"; }
output_fail() { output "$_FAIL_"; }
output_failn() { output "${_FAIL_}\\n"; }
+str_contains() { [ -n "$1" ] &&[ -n "$2" ] && [ "${1//$2}" != "$1" ]; }
uci_add_list_if_new() {
local PACKAGE="$1"
local CONFIG="$2"
local OPTION="$3"
/sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} changes "$PACKAGE${CONFIG:+.$CONFIG}${OPTION:+.$OPTION}"
}
-
-dnsmasq_restart() { [ -x /etc/init.d/dnsmasq ] || return 1; /etc/init.d/dnsmasq restart >/dev/null 2>&1; }
-
version() { echo "$PKG_VERSION"; }
xappend() { PROG_param="$PROG_param $1"; }
[ "$ipv6_resolvers_only" -eq 0 ] && xappend '-4'
}
-resolver_health_check() { resolveip -t 3 one.one.one.one >/dev/null 2>&1; }
-
boot() {
ubus -t 30 wait_for network.interface 2>/dev/null
on_boot_trigger=1
- rc_procd start_service 'on_boot' && rc_procd service_started 'on_boot'
- resolver_health_check || rc_procd stop_service 'on_boot'
+ rc_procd start_service 'on_boot' && service_started 'on_boot'
+ is_resolver_working || { rc_procd stop_service 'on_boot' && service_stopped 'on_boot'; }
}
start_instance() {
procd_close_data
procd_close_instance
- if [ "$?" ]; then
+# shellcheck disable=SC2181
+ if [ "$?" -eq 0 ]; then
config_get listen_addr "$cfg" 'listen_addr' '127.0.0.1'
config_get listen_port "$cfg" 'listen_port' "$port"
if [ "$dnsmasq_config_update" = '*' ]; then
return SW_VERSION;
#else
- return "2023.10.10-atLeast"; // update date sometimes, like 1-2 times a year
-+ return "2023-10-25-1"; // update date sometimes, like 1-2 times a year
++ return "2023-10-25-4"; // update date sometimes, like 1-2 times a year
#endif
}
PKG_NAME:=iperf
PKG_VERSION:=3.15
-PKG_RELEASE:=1
+PKG_RELEASE:=2
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://downloads.es.net/pub/iperf
TITLE+= with iperf_auth support
VARIANT:=ssl
DEPENDS:=+libopenssl
+ CONFLICTS:=iperf3
endef
define Package/libiperf3
include $(TOPDIR)/rules.mk
PKG_NAME:=netbird
-PKG_VERSION:=0.23.9
+PKG_VERSION:=0.24.2
PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://codeload.github.com/netbirdio/netbird/tar.gz/v$(PKG_VERSION)?
-PKG_HASH:=1b037f35d3e426d8cbeba17e4d89d12265cd7e6fbd7c975ce552293e468db35a
+PKG_HASH:=7fd90c6004c7fde6393bd618e106410e708f2d84f7884055acda6b016be42858
PKG_MAINTAINER:=Oskari Rauta <oskari.rauta@gmail.com>
PKG_LICENSE:=BSD-3-Clause
endef
define Package/netbird/description
- NetBird is an open-source VPN management platform built on top of WireGuard® making it easy to create
+ NetBird is an open-source VPN management platform built on top of WireGuard® making it easy to create
secure private networks for your organization or home.
- It requires zero configuration effort leaving behind the hassle of opening ports, complex firewall rules, VPN
+ It requires zero configuration effort leaving behind the hassle of opening ports, complex firewall rules, VPN
gateways, and so forth.
endef
/etc/netbird/config.json
endef
+# Workaround for musl 1.2.4 compability in mattn/go-sqlite3
+# https://github.com/mattn/go-sqlite3/issues/1164
+ifneq ($(CONFIG_USE_MUSL),)
+ TARGET_CFLAGS += -D_LARGEFILE64_SOURCE
+endif
+
define Package/netbird/install
$(call GoPackage/Package/Install/Bin,$(PKG_INSTALL_DIR))
$(INSTALL_DIR) $(1)/usr/bin $(1)/etc/init.d
#!/bin/sh /etc/rc.common
+. /lib/netifd/netifd-proto.sh
+
START=99
STOP=10
USE_PROCD=1
+service_triggers() {
+ procd_add_interface_trigger "interface.*" "wan" /etc/init.d/netbird restart
+}
+
start_service() {
+ local device
+
procd_open_instance
procd_set_param command /usr/bin/netbird
procd_append_param command service run
PKG_NAME:=openvpn
-PKG_VERSION:=2.6.6
+PKG_VERSION:=2.6.8
PKG_RELEASE:=1
PKG_SOURCE_URL:=\
https://build.openvpn.net/downloads/releases/ \
https://swupdate.openvpn.net/community/releases/
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
-PKG_HASH:=3b074f392818b31aa529b84f76e8b5e4ad03fca764924f46d906bceaaf421034
+PKG_HASH:=5ede1565c8a6d880100f7f235317a7ee9eea83d5052db5547f13a9e76af7805d
PKG_MAINTAINER:=Magnus Kroken <mkroken@gmail.com>
--- a/src/openvpn/ssl_mbedtls.c
+++ b/src/openvpn/ssl_mbedtls.c
-@@ -1535,7 +1535,7 @@ const char *
+@@ -1533,7 +1533,7 @@ const char *
get_ssl_library_version(void)
{
static char mbedtls_version[30];
--- a/src/openvpn/crypto_openssl.c
+++ b/src/openvpn/crypto_openssl.c
-@@ -51,7 +51,7 @@
+@@ -49,7 +49,7 @@
#include <openssl/rand.h>
#include <openssl/ssl.h>
#include <openssl/kdf.h>
#endif
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
-@@ -1436,7 +1436,7 @@ engine_load_key(const char *file, SSL_CT
- #endif /* if HAVE_OPENSSL_ENGINE */
+@@ -1374,7 +1374,7 @@ memcmp_constant_time(const void *a, cons
+ return CRYPTO_memcmp(a, b, size);
}
-#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)
--- a/src/openvpn/ssl_openssl.c
+++ b/src/openvpn/ssl_openssl.c
-@@ -1351,7 +1351,7 @@ err:
+@@ -1347,7 +1347,7 @@ err:
return 0;
}
/* called when EC_KEY is destroyed */
static void
-@@ -1512,7 +1512,7 @@ tls_ctx_use_management_external_key(stru
+@@ -1508,7 +1508,7 @@ tls_ctx_use_management_external_key(stru
goto cleanup;
}
}
--- a/src/openvpn/ssl_verify_openssl.c
+++ b/src/openvpn/ssl_verify_openssl.c
-@@ -269,6 +269,9 @@ backend_x509_get_username(char *common_n
+@@ -267,6 +267,9 @@ backend_x509_get_username(char *common_n
return FAILURE;
}
}
include $(TOPDIR)/rules.mk
PKG_NAME:=pdns-recursor
-PKG_VERSION:=4.9.1
+PKG_VERSION:=4.9.2
PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
PKG_SOURCE_URL:=https://downloads.powerdns.com/releases/
-PKG_HASH:=0a1edc13e8f2bd661f39e316387d941e22de6a03b8a7a2fc662fdf8b942ea2be
+PKG_HASH:=4cb8180458ecfb528a3d9a34ba2844b6cd2ed69ca1c461dde24a0ebd66829144
PKG_MAINTAINER:=Peter van Dijk <peter.van.dijk@powerdns.com>
PKG_LICENCE:=GPL-2.0-only
endef
define Package/pdns-recursor/conffiles
-/etc/powerdns/pdns-recursor.conf
+/etc/powerdns/recursor.conf
/etc/init.d/pdns-recursor
endef
PKG_NAME:=pptpd
PKG_VERSION:=1.4.0
-PKG_RELEASE:=5
+PKG_RELEASE:=6
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=@SF/poptop
validate_pptpd_section() {
uci_load_validate pptpd service "$1" "$2" \
- 'enabled:uinteger' \
+ 'enabled:bool:1' \
'localip:string' \
'remoteip:string' \
'mppe:list(string):required no40 no56 stateless' \
- 'logwtmp:uinteger'
+ 'logwtmp:bool:0'
}
setup_login() {
+++ /dev/null
-#
-# Copyright (C) 2016 Ben Rosser <rosser.bjr@gmail.com>
-#
-# This is free software, licensed under the GNU General Public License v2.
-# See /LICENSE for more information.
-#
-
-include $(TOPDIR)/rules.mk
-
-PKG_NAME:=quassel-irssi
-PKG_SOURCE_DATE:=2017-11-30
-PKG_SOURCE_VERSION:=079be662dde374a383646256108a4974c2bc7796
-PKG_RELEASE:=3
-
-PKG_SOURCE:=$(PKG_NAME)-$(PKG_SOURCE_DATE).tar.gz
-PKG_SOURCE_URL:=https://codeload.github.com/phhusson/quassel-irssi/tar.gz/$(PKG_SOURCE_VERSION)?
-PKG_HASH:=c276a92a47f8edf5ae1d9db0e72a69d078f2f3f80e055853fc6d06099d898966
-PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_SOURCE_VERSION)
-
-PKG_MAINTAINER:=Ben Rosser <rosser.bjr@gmail.com>
-PKG_LICENSE:=GPL-3.0-or-later
-PKG_LICENSE_FILES:=core/COPYING
-
-PKG_BUILD_PARALLEL:=1
-PKG_INSTALL:=1
-
-include $(INCLUDE_DIR)/package.mk
-include $(INCLUDE_DIR)/nls.mk
-
-MAKE_PATH := core
-MAKE_VARS += SYSTEM_QUASSELC=1 IRSSI_CFLAGS="$(TARGET_CFLAGS) $(EXTRA_CFLAGS) $(TARGET_CPPFLAGS) $(EXTRA_CPPFLAGS)" IRSSI_INCLUDE=$(STAGING_DIR)/usr/include/irssi
-
-define Package/quassel-irssi
- SECTION:=net
- CATEGORY:=Network
- DEPENDS:=+irssi +quasselc
- SUBMENU:=Instant Messaging
- URL:=https://github.com/phhusson/quassel-irssi
- TITLE:=An irssi plugin to connect to quassel core
-endef
-
-define Package/quassel-irssi/description
- An irssi plugin that supports connecting to a quassel core.
-endef
-
-define Package/quassel-irssi/install
- $(INSTALL_DIR) $(1)/usr/lib/irssi/modules/
- $(CP) $(PKG_INSTALL_DIR)/usr/lib/irssi/modules/libquassel_core.so* $(1)/usr/lib/irssi/modules/
-endef
-
-$(eval $(call BuildPackage,quassel-irssi))
+++ /dev/null
---- a/core/Makefile
-+++ b/core/Makefile
-@@ -3,7 +3,7 @@ DESTDIR ?=
- LIBDIR ?= /usr/lib
-
- #IRSSI_INCLUDE:=/home/phh/irssi-0.8.16-rc1.phh/
--IRSSI_INCLUDE:=/usr/include/irssi/
-+IRSSI_INCLUDE?=/usr/include/irssi/
- IRSSI_LIB?=$(DESTDIR)/$(LIBDIR)/irssi
- IRSSI_CFLAGS+=-I$(IRSSI_INCLUDE)/src/
- IRSSI_CFLAGS+=-I$(IRSSI_INCLUDE)/src/core/
-@@ -28,7 +28,7 @@ else
- LDFLAGS += -lquasselc
- endif
-
--CFLAGS=-std=gnu11 -Wall -Wextra -Werror -g -O2 $(IRSSI_CFLAGS) $(QUASSELC_FLAGS) -Wmissing-prototypes -Wmissing-declarations
-+CFLAGS+=-std=gnu11 -Wall -Wextra -g $(IRSSI_CFLAGS) $(QUASSELC_FLAGS) -Wmissing-prototypes -Wmissing-declarations
-
- CFLAGS += $(SSL_CFLAGS)
- LDFLAGS+= $(SSL_LDLAGS)
+++ /dev/null
---- a/core/Makefile
-+++ b/core/Makefile
-@@ -49,7 +49,7 @@ irssi/network-openssl.o: CFLAGS:=$(IRSSI
- quasselc-connector.o: CFLAGS:=$(CFLAGS)
-
- $(TARGET): $(OBJECTS)
-- gcc -shared $^ -o $@ -lz $(LDFLAGS)
-+ $(CC) -shared $^ -o $@ -lz $(LDFLAGS)
-
- install: $(TARGET)
- $(INSTALL) -d $(IRSSI_LIB)/modules
+++ /dev/null
---- a/core/Makefile
-+++ b/core/Makefile
-@@ -25,7 +25,7 @@ ifndef SYSTEM_QUASSELC
- QUASSELC_FLAGS:=-Ilib
- else
- QUASSELC_FLAGS:=$(shell pkg-config --cflags quasselc)
-- LDFLAGS += -lquasselc
-+ LDFLAGS += $(shell pkg-config --libs quasselc)
- endif
-
- CFLAGS+=-std=gnu11 -Wall -Wextra -g $(IRSSI_CFLAGS) $(QUASSELC_FLAGS) -Wmissing-prototypes -Wmissing-declarations
+++ /dev/null
-From 19e810405789a35b92026b56ea49d01a3f544b07 Mon Sep 17 00:00:00 2001
-From: Pierre-Hugues Husson <phh@phh.me>
-Date: Tue, 17 Jan 2017 23:09:24 +0100
-Subject: [PATCH] Get compatible with potential irssi abi 8, and drop polling
-
----
- core/Makefile | 1 -
- core/quassel-net.c | 64 ++++++++++++++++++++++++++++++++++++++--------
- 2 files changed, 53 insertions(+), 10 deletions(-)
-
---- a/core/Makefile
-+++ b/core/Makefile
-@@ -16,7 +16,6 @@ SSL_CFLAGS=$(shell pkg-config --cflags o
- SSL_LDLAGS=$(shell pkg-config --libs openssl)
- OBJECTS:=quasselc-connector.o quassel-core.o
- OBJECTS+=quassel-net.o quassel-msgs.o quassel-cmds.o
--OBJECTS+=irssi/network-openssl.o
- OBJECTS+=quassel-fe-window.o quassel-fe-level.o quassel-cfg.o
-
- LDFLAGS ?=
---- a/core/quassel-net.c
-+++ b/core/quassel-net.c
-@@ -132,10 +132,10 @@ static SERVER_REC* quassel_server_init_c
- ret->got = 0;
- server_connect_ref(SERVER_CONNECT(conn));
-
-- if(conn->use_ssl) {
-+ if(conn->use_tls) {
- ret->ssl = 1;
- }
-- ret->connrec->use_ssl = 0;
-+ ret->connrec->use_tls = 0;
-
- ret->channels_join = quassel_irssi_channels_join;
- ret->send_message = quassel_irssi_send_message;
-@@ -161,12 +161,59 @@ void quassel_net_init(CHAT_PROTOCOL_REC*
- signal_add_first("server connected", (SIGNAL_FUNC) sig_connected);
- }
-
--GIOChannel *irssi_ssl_get_iochannel(GIOChannel *handle, int port, SERVER_REC *server);
-+static void quassel_net_final_setup(SERVER_REC* server, GIOChannel *handle) {
-+ quassel_login(handle, server->connrec->nick, server->connrec->password);
-+ server->handle->handle = handle;
-+
-+ server->readtag =
-+ g_input_add(handle,
-+ G_INPUT_READ,
-+ (GInputFunction) quassel_parse_incoming, server);
-+}
-+
-+static void quassel_net_ssl_callback(SERVER_REC *server, GIOChannel *handle) {
-+ int error;
-+
-+ g_return_if_fail(IS_SERVER(server));
-+
-+ error = irssi_ssl_handshake(handle);
-+ if (error == -1) {
-+ server->connection_lost = TRUE;
-+ server_connect_failed(server, NULL);
-+ return;
-+ }
-+ if (error & 1) {
-+ if (server->connect_tag != -1)
-+ g_source_remove(server->connect_tag);
-+ server->connect_tag = g_input_add(handle, error == 1 ? G_INPUT_READ : G_INPUT_WRITE,
-+ (GInputFunction)
-+ quassel_net_ssl_callback,
-+ server);
-+ return;
-+ }
-+
-+ if (server->connect_tag != -1) {
-+ g_source_remove(server->connect_tag);
-+ server->connect_tag = -1;
-+ }
-+
-+ quassel_net_final_setup(server, handle);
-+}
-+
- void quassel_irssi_init_ack(void *arg) {
- Quassel_SERVER_REC *server = (Quassel_SERVER_REC*)arg;
-- if(!server->ssl)
-- goto login;
-- GIOChannel* ssl_handle = irssi_ssl_get_iochannel(server->handle->handle, 1337, SERVER(server));
-+ GIOChannel* ssl_handle = net_start_ssl((SERVER_REC*)server);
-+
-+ if(server->readtag != -1) {
-+ g_source_remove(server->readtag);
-+ server->readtag = -1;
-+ }
-+
-+ if(!server->ssl) {
-+ quassel_net_final_setup((SERVER_REC*)server, server->handle->handle);
-+ return;
-+ }
-+
- int error;
- //That's polling, and that's really bad...
- while( (error=irssi_ssl_handshake(ssl_handle)) & 1) {
-@@ -175,10 +222,7 @@ void quassel_irssi_init_ack(void *arg) {
- return;
- }
- }
-- server->handle->handle = ssl_handle;
--
--login:
-- quassel_login(server->handle->handle, server->connrec->nick, server->connrec->password);
-+ quassel_net_ssl_callback((SERVER_REC*)server, ssl_handle);
- }
-
- void quassel_irssi_init_nack(void *arg) {
include $(TOPDIR)/rules.mk
PKG_NAME:=sing-box
-PKG_VERSION:=1.6.0
+PKG_VERSION:=1.6.6
PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://codeload.github.com/SagerNet/sing-box/tar.gz/v$(PKG_VERSION)?
-PKG_HASH:=3272c9ac447d009749429f38d76e9879609c0c321442c3235ba806d995c0838a
+PKG_HASH:=88c8825f6e8af2e46a16e8a85ceb5e1c7c0795b59cad93c8327288ec7b8249e0
PKG_LICENSE:=GPL-3.0-or-later
PKG_LICENSE_FILES:=LICENSE
include $(TOPDIR)/rules.mk
PKG_NAME:=snort3
-PKG_VERSION:=3.1.73.0
-PKG_RELEASE:=1
+PKG_VERSION:=3.1.74.0
+PKG_RELEASE:=2
PKG_SOURCE:=$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://github.com/snort3/snort3/archive/refs/tags/
-PKG_HASH:=d04edf07e9b695fb22de73f0987537d35b4c8466119940e39a056d1a13888b27
+PKG_HASH:=4a4529e74bc202303c0330ae8b2317f0bef3ac92ae7216df8cfedfce24ddd129
PKG_MAINTAINER:=W. Michael Petullo <mike@flyn.org>
PKG_LICENSE:=GPL-2.0-only
--- /dev/null
+--- a/src/network_inspectors/packet_capture/packet_capture.h
++++ b/src/network_inspectors/packet_capture/packet_capture.h
+@@ -20,9 +20,10 @@
+ #ifndef PACKET_CAPTURE_H
+ #define PACKET_CAPTURE_H
+
++#include <cstdint>
+ #include <string>
+
+-void packet_capture_enable(const std::string&, const int16_t g = -1);
++void packet_capture_enable(const std::string&, const std::int16_t g = -1);
+ void packet_capture_disable();
+
+ #endif
include $(TOPDIR)/rules.mk
PKG_NAME:=sstp-client
-PKG_VERSION:=1.0.15
+PKG_VERSION:=1.0.19
PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
-PKG_SOURCE_URL:=@SF/sstp-client/$(PKG_VERSION)
-PKG_HASH:=8484aa51fbfbe418a0ebad58ad20a8ee1c46ed71f800be18bcd23b42e6baad64
+PKG_SOURCE_URL:=https://gitlab.com/sstp-project/sstp-client/-/archive/1.0.19/
+PKG_HASH:=e2652365f69f5037102e78f4e115ff764a390b27bb3fd513a8a50b10a61bb613
PKG_MAINTAINER:=Federico Di Marco <fededim@gmail.com>
PKG_LICENSE:=GPL-2.0-or-later
PKG_LICENSE_FILES:=COPYING
+PKG_FIXUP:=autoreconf
+
include $(INCLUDE_DIR)/package.mk
define Package/sstp-client
--- a/src/sstp-client.c
+++ b/src/sstp-client.c
-@@ -542,6 +542,7 @@ static status_t sstp_init_ssl(sstp_clien
+@@ -546,6 +546,7 @@ static status_t sstp_init_ssl(sstp_clien
int retval = SSTP_FAIL;
int status = 0;
/* Initialize the OpenSSL library */
status = SSL_library_init();
if (status != 1)
-@@ -555,6 +556,9 @@ static status_t sstp_init_ssl(sstp_clien
+@@ -575,6 +576,9 @@ static status_t sstp_init_ssl(sstp_clien
/* Create a new crypto context */
client->ssl_ctx = SSL_CTX_new(SSLv23_client_method());
include $(TOPDIR)/rules.mk
PKG_NAME:=strongswan
-PKG_VERSION:=5.9.11
-PKG_RELEASE:=2
+PKG_VERSION:=5.9.12
+PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
PKG_SOURCE_URL:=https://download.strongswan.org/ https://download2.strongswan.org/
-PKG_HASH:=ddf53f1f26ad26979d5f55e8da95bd389552f5de3682e35593f9a70b2584ed2d
+PKG_HASH:=5e6018b07cbe9f72c044c129955a13be3e2f799ceb53f53a4459da6a922b95e5
PKG_LICENSE:=GPL-2.0-or-later
PKG_MAINTAINER:=Philip Prindeville <philipp@redfish-solutions.com>, Noel Kuntze <noel.kuntze@thermi.consulting>
PKG_CPE_ID:=cpe:/a:strongswan:strongswan
local lifebytes
local rekeypackets
local lifepackets
+ local replay_window
config_get startaction "$conf" startaction "route"
config_get local_nat "$conf" local_nat ""
config_get lifebytes "$conf" lifebytes ""
config_get rekeypackets "$conf" rekeypackets ""
config_get lifepackets "$conf" lifepackets ""
+ config_get replay_window "$conf" replay_window ""
config_list_foreach "$conf" local_subnet append_var local_subnet ","
config_list_foreach "$conf" remote_subnet append_var remote_subnet ","
[ -n "$updown" ] && swanctl_xappend4 "updown = $updown"
[ -n "$dpdaction" ] && swanctl_xappend4 "dpd_action = $dpdaction"
+ [ -n "$replay_window" ] && swanctl_xappend4 "replay_window = $replay_window"
swanctl_xappend3 "}"
}
#include <linux/rtnetlink.h>
--- a/src/libstrongswan/library.h
+++ b/src/libstrongswan/library.h
-@@ -120,6 +120,7 @@
+@@ -121,6 +121,7 @@
#include "utils/leak_detective.h"
#include "plugins/plugin_loader.h"
#include "settings/settings.h"
ARG_DISBL_SET([curve25519], [disable Curve25519 Diffie-Hellman plugin.])
ARG_DISBL_SET([hmac], [disable HMAC crypto implementation plugin.])
ARG_DISBL_SET([kdf], [disable KDF (prf+) implementation plugin.])
-@@ -1565,6 +1566,7 @@ ADD_PLUGIN([pkcs8], [s ch
+@@ -1574,6 +1575,7 @@ ADD_PLUGIN([pkcs8], [s ch
ADD_PLUGIN([af-alg], [s charon pki scripts medsrv attest nm cmd aikgen])
ADD_PLUGIN([fips-prf], [s charon nm cmd])
ADD_PLUGIN([gmp], [s charon pki scripts manager medsrv attest nm cmd aikgen fuzz])
ADD_PLUGIN([curve25519], [s charon pki scripts nm cmd])
ADD_PLUGIN([agent], [s charon nm cmd])
ADD_PLUGIN([keychain], [s charon cmd])
-@@ -1706,6 +1708,7 @@ AM_CONDITIONAL(USE_SHA3, test x$sha3 = x
+@@ -1716,6 +1718,7 @@ AM_CONDITIONAL(USE_SHA3, test x$sha3 = x
AM_CONDITIONAL(USE_MGF1, test x$mgf1 = xtrue)
AM_CONDITIONAL(USE_FIPS_PRF, test x$fips_prf = xtrue)
AM_CONDITIONAL(USE_GMP, test x$gmp = xtrue)
AM_CONDITIONAL(USE_CURVE25519, test x$curve25519 = xtrue)
AM_CONDITIONAL(USE_RDRAND, test x$rdrand = xtrue)
AM_CONDITIONAL(USE_AESNI, test x$aesni = xtrue)
-@@ -1983,6 +1986,7 @@ AC_CONFIG_FILES([
+@@ -1996,6 +1999,7 @@ AC_CONFIG_FILES([
src/libstrongswan/plugins/mgf1/Makefile
src/libstrongswan/plugins/fips_prf/Makefile
src/libstrongswan/plugins/gmp/Makefile
src/libstrongswan/plugins/aesni/Makefile
--- a/src/libstrongswan/Makefile.am
+++ b/src/libstrongswan/Makefile.am
-@@ -353,6 +353,13 @@ if MONOLITHIC
+@@ -357,6 +357,13 @@ if MONOLITHIC
endif
endif
include $(TOPDIR)/rules.mk
PKG_NAME:=tailscale
-PKG_VERSION:=1.50.1
+PKG_VERSION:=1.54.0
PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://codeload.github.com/tailscale/tailscale/tar.gz/v$(PKG_VERSION)?
-PKG_HASH:=183a7d559590a759dd77aa9c2b65486ab6e13c26f3c07fad0b536e318ad5e233
+PKG_HASH:=c895a0f489706535ed400b0599d7d932d9eebc5f1bad2c236408a1e4b86620e7
PKG_MAINTAINER:=Jan Pavlinec <jan.pavlinec1@gmail.com>
PKG_LICENSE:=BSD-3-Clause
PKG_NAME:=travelmate
PKG_VERSION:=2.1.1
-PKG_RELEASE:=2
+PKG_RELEASE:=3
PKG_LICENSE:=GPL-3.0-or-later
PKG_MAINTAINER:=Dirk Brenken <dev@brenken.org>
--- /dev/null
+#!/bin/sh
+# captive portal auto-login script for H-Reward Hotelss
+# This is free software, licensed under the GNU General Public License v3.
+
+# set (s)hellcheck exceptions
+# shellcheck disable=1091,2039,3040
+#
+#
+# Username and password can be passed to the script, to get fast wifi
+# If not provided, the option with the slower wifi will be selected
+
+
+. "/lib/functions.sh"
+
+
+export LC_ALL=C
+export PATH="/usr/sbin:/usr/bin:/sbin:/bin"
+
+
+# From https://stackoverflow.com/a/17336953/819367 converted to sh
+rawurlencode() {
+ string="$1"
+ strlen=${#string}
+ encoded=""
+ pos=0
+ c=""
+ o=""
+
+ while [ $pos -lt $strlen ]; do
+ c=$(expr substr "$string" $((pos + 1)) 1)
+ case "$c" in
+ [-_.~a-zA-Z0-9] ) o="${c}" ;;
+ * ) o=$(printf '%%%02x' "'$c")
+ esac
+ encoded="${encoded}${o}"
+ pos=$((pos + 1))
+ done
+
+ echo "${encoded}"
+}
+
+user=$(rawurlencode "${1}")
+password=$(rawurlencode "${2}")
+
+successUrl="https://hrewards.com/en"
+trm_useragent="$(uci_get travelmate global trm_useragent "Mozilla/5.0 (Linux x86_64; rv:90.0) Gecko/20100101 Firefox/90.0")"
+trm_maxwait="$(uci_get travelmate global trm_maxwait "30")"
+
+set -e
+
+
+session_key="$(curl -sL --user-agent "${trm_useragent}" \
+ --connect-timeout $((trm_maxwait / 6)) \
+ "http://nossl.com/?cmd=redirect&arubalp=12345" \
+ | awk -F 'name="session_key" value="' 'NF>1{split($2,a,"\""); print a[1]; exit}')"
+
+if [ -n "$user" ] && [ -n "$password" ]; then
+ response="$(curl -sL --user-agent "${trm_useragent}" \
+ --connect-timeout $((trm_maxwait / 6)) \
+ -w %{url_effective} \
+ -o /dev/null \
+ --header "Content-Type:application/x-www-form-urlencoded" \
+ --data "session_key=${session_key}&accept_terms=1&email=${user}&password=${password}&password_reset_form_email=&password_update_form_password=&password_update_form_password_repeat=&room_number=&last_name=&voucher=" \
+ "https://cp.deutschehospitality.com/aruba/login?lang=en")"
+else
+ response="$(curl -sL --user-agent "${trm_useragent}" \
+ --connect-timeout $((trm_maxwait / 6)) \
+ -w %{url_effective} \
+ -o /dev/null \
+ --header "Content-Type:application/x-www-form-urlencoded" \
+ --data "session_key=${session_key}&email=&password=&accept_terms=1&password_reset_form_email=&password_update_form_password=&password_update_form_password_repeat=&room_number=&last_name=&voucher=" \
+ "https://cp.deutschehospitality.com/aruba/skip-registration?lang=en")"
+fi
+
+if [ "$response" != "$successUrl" ]; then
+ exit 255
+fi
include $(TOPDIR)/rules.mk
PKG_NAME:=udp-broadcast-relay-redux
-PKG_RELEASE:=2
+PKG_RELEASE:=3
PKG_LICENSE:=GPL-2.0
PKG_SOURCE_PROTO:=git
'port:port' \
'network:list(string)' \
'src_override:ip4addr' \
- 'dest_override:ip4addr'
+ 'dest_override:ip4addr' \
+ 'multicast:ip4addr'
[ -z "$id" ] && return 1
}
udp_broadcast_relay_redux_instance() {
- local net network ifname id port src_override dest_override
+ local net network ifname id port src_override dest_override multicast
validate_section_udp_broadcast_relay_redux "${1}" || {
echo "Validation failed"
procd_append_param command "-t" "$dest_override"
fi
+ if [ -n "$multicast" ] ; then
+ procd_append_param command "--multicast" "$multicast"
+ fi
+
procd_add_jail ubr-${PIDCOUNT} cgroupsns
procd_close_instance
}
# list network lan
# list network vpnsrv
# option dest_override 10.66.2.13
+# option multicast 239.255.255.250
include $(TOPDIR)/rules.mk
PKG_NAME:=unbound
-PKG_VERSION:=1.18.0
-PKG_RELEASE:=1
+PKG_VERSION:=1.19.0
+PKG_RELEASE:=2
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://nlnetlabs.nl/downloads/unbound
-PKG_HASH:=3da95490a85cff6420f26fae0b84a49f5112df1bf1b7fc34f8724f02082cb712
+PKG_HASH:=a97532468854c61c2de48ca4170de854fd3bc95c8043bb0cfb0fe26605966624
PKG_MAINTAINER:=Eric Luehrsen <ericluehrsen@gmail.com>
PKG_LICENSE:=BSD-3-Clause
##############################################################################
-create_host_record() {
+create_host_record_from_domain() {
local cfg="$1"
local ip name debug_ip
##############################################################################
+create_host_record_from_host() {
+ local cfg="$1"
+ local dns ip name
+
+ # basefiles dhcp "host" clause which means host A and PTR records
+ config_get dns "$cfg" dns 0
+ config_get ip "$cfg" ip
+ config_get name "$cfg" name
+
+
+ if [ -n "$name" ] && [ -n "$ip" ] && [ $dns -eq 1 ] ; then
+ case $name in
+ *.*)
+ # domain present, do nothing
+ ;;
+ *)
+ name="$name.$UB_TXT_DOMAIN"
+ ;;
+ esac
+
+
+ create_local_zone "$name"
+ DM_LIST_LOCAL_DATA="$DM_LIST_LOCAL_DATA $name.@@300@@IN@@A@@$ip"
+ DM_LIST_LOCAL_PTR="$DM_LIST_LOCAL_PTR $ip@@300@@$name"
+ fi
+}
+
+##############################################################################
+
create_mx_record() {
local cfg="$1"
local domain relay pref record
# Parasite from the uci.dhcp.domain clauses
DM_LIST_KNOWN_ZONES="$DM_LIST_KNOWN_ZONES $UB_TXT_DOMAIN"
config_load dhcp
- config_foreach create_host_record domain
+ config_foreach create_host_record_from_domain domain
+ config_foreach create_host_record_from_host host
if [ $UB_D_EXTRA_DNS -gt 1 ] ; then
target. Use "uname" on host only if "UNAME" variable is empty.
--- a/configure.ac
+++ b/configure.ac
-@@ -840,7 +840,7 @@ if test x_$ub_test_python != x_no; then
+@@ -842,7 +842,7 @@ if test x_$ub_test_python != x_no; then
fi
fi
include $(TOPDIR)/rules.mk
PKG_NAME:=v2ray-core
-PKG_VERSION:=5.11.0
+PKG_VERSION:=5.12.1
PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://codeload.github.com/v2fly/v2ray-core/tar.gz/v$(PKG_VERSION)?
-PKG_HASH:=c25490d6b0600cd316409f112d39e10f5d7c66bb89f18dafcd3a95d26f889bc2
+PKG_HASH:=fa1845d42b46c6b5046a8f95d49cc7a9175e40efc5c13b95174b4c556567aca1
PKG_LICENSE:=MIT
PKG_LICENSE_FILES:=LICENSE
include $(INCLUDE_DIR)/package.mk
-GEOIP_VER:=202310120354
+GEOIP_VER:=202311160040
GEOIP_FILE:=geoip.dat.$(GEOIP_VER)
define Download/geoip
URL:=https://github.com/v2fly/geoip/releases/download/$(GEOIP_VER)/
URL_FILE:=geoip.dat
FILE:=$(GEOIP_FILE)
- HASH:=7107cfe4e211d4df5234d0d2b1c47bdcd19f6602c2b7969f3a5e12f7cf48692e
+ HASH:=fe44648629b12e4818eae1a9f703e83f02261e7dcc91b06edf531f343bf16170
endef
-GEOSITE_VER:=20231015073627
+GEOSITE_VER:=20231118232758
GEOSITE_FILE:=dlc.dat.$(GEOSITE_VER)
define Download/geosite
URL:=https://github.com/v2fly/domain-list-community/releases/download/$(GEOSITE_VER)/
URL_FILE:=dlc.dat
FILE:=$(GEOSITE_FILE)
- HASH:=2042c47d520634236fbf238a4168196bea64a2d61ca5e6cbab9fd0ac37c7e659
+ HASH:=91844afa5918b0465b2ffaaf9ee35d09bffd0a2b47b669afdf77ff576262b048
endef
-GEOSITE_IRAN_VER:=202310160024
+GEOSITE_IRAN_VER:=202311130025
GEOSITE_IRAN_FILE:=iran.dat.$(GEOSITE_IRAN_VER)
define Download/geosite-ir
URL:=https://github.com/bootmortis/iran-hosted-domains/releases/download/$(GEOSITE_IRAN_VER)/
URL_FILE:=iran.dat
FILE:=$(GEOSITE_IRAN_FILE)
- HASH:=70db057c5c1d07de251c4543e6c20ff0a352c95977e120d1522a7f826ff08cf2
+ HASH:=286b48d780010349ce759daba30a05e550ea7e3f45082026d2e5f53803223f90
endef
define Package/v2ray-geodata/template
include $(TOPDIR)/rules.mk
PKG_NAME:=v2rayA
-PKG_VERSION:=2.2.4
+PKG_VERSION:=2.2.4.1
PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://codeload.github.com/v2rayA/v2rayA/tar.gz/v$(PKG_VERSION)?
-PKG_HASH:=844da2a4c1ac1f7eae02519a0833255a63938f08a554cbea043606b28ee6ebed
+PKG_HASH:=e0d8a2250f9933ca1d1efe023a7ec7d6d5f9a4d058a8a7270c457a8d1e0b4ab9
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)/service
PKG_LICENSE:=AGPL-3.0-only
URL:=https://github.com/v2rayA/v2rayA/releases/download/v$(PKG_VERSION)/
URL_FILE:=web.zip
FILE:=$(WEB_FILE)
- HASH:=2699dacdf39137af408a9ffcb91734e5af487bef4dccaa51f1bb3de6c4d3e8fe
+ HASH:=76735aa46253dc29b9605798173fafc3ae545089e3da8090f76d6a3f65780e37
endef
define Build/Prepare
include $(TOPDIR)/rules.mk
PKG_NAME:=xray-core
-PKG_VERSION:=1.8.4
+PKG_VERSION:=1.8.6
PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://codeload.github.com/XTLS/Xray-core/tar.gz/v$(PKG_VERSION)?
-PKG_HASH:=89f73107abba9bd438111edfe921603ddb3c2b631b2716fbdc6be78552f0d322
+PKG_HASH:=d828296c9f29f9e59a61ab73d44f072ab2a30fe979679e39aea43b33ddb7d6bf
PKG_MAINTAINER:=Tianling Shen <cnsztl@immortalwrt.org>
PKG_LICENSE:=MPL-2.0
PKG_NAME:=pulseaudio
PKG_VERSION:=16.1
-PKG_RELEASE:=1
+PKG_RELEASE:=2
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
PKG_SOURCE_URL:=https://freedesktop.org/software/pulseaudio/releases
-Dx11=disabled \
-Dadrian-aec=true \
-Dwebrtc-aec=disabled \
- -Ddoxygen=false
+ -Ddoxygen=false \
+ -Dtcpwrap=disabled \
+ -Dbluez5-gstreamer=disabled
ifeq ($(BUILD_VARIANT),avahi)
MESON_ARGS += \
+++ /dev/null
-#
-# Copyright (C) 2014-2016 OpenWrt.org
-#
-# This is free software, licensed under the GNU General Public License v2.
-# See /LICENSE for more information.
-#
-
-include $(TOPDIR)/rules.mk
-
-PKG_NAME:=shairplay
-PKG_SOURCE_DATE:=2018-08-24
-PKG_SOURCE_VERSION:=096b61ad14c90169f438e690d096e3fcf87e504e
-PKG_RELEASE:=2
-
-PKG_SOURCE:=$(PKG_NAME)-$(PKG_SOURCE_DATE).tar.gz
-PKG_SOURCE_URL:=https://codeload.github.com/juhovh/shairplay/tar.gz/$(PKG_SOURCE_VERSION)?
-PKG_HASH:=7e2b013ffe75ea2f13fb12b1aa38b8e2e8b1899ac292d57f05d7b352a3a181cf
-PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_SOURCE_VERSION)
-
-PKG_MAINTAINER:=Álvaro Fernández Rojas <noltari@gmail.com>
-PKG_LICENSE:=MIT
-PKG_LICENSE_FILES:=LICENSE
-
-PKG_FIXUP:=autoreconf
-PKG_BUILD_PARALLEL:=1
-
-include $(INCLUDE_DIR)/package.mk
-
-define Package/shairplay
- SECTION:=sound
- CATEGORY:=Sound
- DEPENDS:=+libao +libavahi-compat-libdnssd +libltdl +libpthread
- TITLE:=Shairplay
-endef
-
-define Package/shairplay/description
- Free portable AirPlay server implementation similar to ShairPort.
-endef
-
-define Package/shairplay/conffiles
-/etc/config/shairplay
-endef
-
-define Package/shairplay/install
- $(INSTALL_DIR) $(1)/usr/bin
- $(INSTALL_BIN) $(PKG_BUILD_DIR)/src/shairplay $(1)/usr/bin/
- $(INSTALL_DIR) $(1)/usr/share/shairplay
- $(INSTALL_DATA) $(PKG_BUILD_DIR)/airport.key $(1)/usr/share/shairplay/
- $(INSTALL_DIR) $(1)/etc/init.d
- $(INSTALL_BIN) files/shairplay.init $(1)/etc/init.d/shairplay
- $(INSTALL_DIR) $(1)/etc/config
- $(INSTALL_CONF) files/shairplay.config $(1)/etc/config/shairplay
-endef
-
-$(eval $(call BuildPackage,shairplay))
+++ /dev/null
-config shairplay main
- option disabled '1'
- option respawn '1'
- option apname 'AirPlay'
- option port '5000'
- option password ''
- option hwaddr ''
- option ao_driver 'oss'
- option ao_devicename ''
- option ao_deviceid ''
+++ /dev/null
-#!/bin/sh /etc/rc.common
-# Copyright (C) 2014 OpenWrt.org
-
-START=90
-USE_PROCD=1
-
-append_arg() {
- local cfg="$1"
- local var="$2"
- local opt="$3"
- local def="$4"
- local val
-
- config_get val "$cfg" "$var"
- [ -n "$val" -o -n "$def" ] && procd_append_param command $opt="${val:-$def}"
-}
-
-start_instance() {
- local cfg="$1"
- local aux
-
- config_get_bool aux "$cfg" 'disabled' '0'
- [ "$aux" = 1 ] && return 1
-
- procd_open_instance
-
- procd_set_param command /usr/bin/shairplay
-
- append_arg "$cfg" apname "--apname" "AirPlay"
- append_arg "$cfg" port "--server_port"
- append_arg "$cfg" password "--password"
- append_arg "$cfg" hwaddr "--hwaddr"
-
- append_arg "$cfg" ao_driver "--ao_driver"
- append_arg "$cfg" ao_devicename "--ao_devicename"
- append_arg "$cfg" ao_deviceid "--ao_deviceid"
-
- config_get_bool aux "$cfg" 'respawn' '0'
- [ "$aux" = 1 ] && procd_set_param respawn
-
- procd_close_instance
-}
-
-service_triggers() {
- procd_add_reload_trigger "shairplay"
-}
-
-start_service() {
- config_load shairplay
- config_foreach start_instance shairplay
-}
+++ /dev/null
---- a/src/shairplay.c
-+++ b/src/shairplay.c
-@@ -350,7 +350,7 @@ main(int argc, char *argv[])
- raop_cbs.audio_destroy = audio_destroy;
- raop_cbs.audio_set_volume = audio_set_volume;
-
-- raop = raop_init_from_keyfile(10, &raop_cbs, "airport.key", NULL);
-+ raop = raop_init_from_keyfile(10, &raop_cbs, "/usr/share/shairplay/airport.key", NULL);
- if (raop == NULL) {
- fprintf(stderr, "Could not initialize the RAOP service\n");
- fprintf(stderr, "Please make sure the airport.key file is in the current directory.\n");
+++ /dev/null
---- a/src/lib/alac/alac.c
-+++ b/src/lib/alac/alac.c
-@@ -29,7 +29,7 @@
- *
- */
-
--static const int host_bigendian = 0;
-+#define host_bigendian (htonl(42) == 42)
-
- #include <stdio.h>
- #include <stdlib.h>
+++ /dev/null
-From 031c3d802e51bbc233b1044f812402a66bfcf237 Mon Sep 17 00:00:00 2001
-From: Memphiz <memphis@machzwo.de>
-Date: Fri, 21 Dec 2018 20:39:11 +0100
-Subject: [PATCH] [configure] - only check for dns_sd.h in case libdl was not
- found
-
----
- configure.ac | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/configure.ac
-+++ b/configure.ac
-@@ -19,7 +19,7 @@ LT_LIB_DLLOAD
-
- # Checks for header files.
- AC_HEADER_STDC
--if test yes = "$libltdl_cv_func_dlopen" || test yes = "$libltdl_cv_lib_dl_dlopen"
-+if test no = "$libltdl_cv_func_dlopen" && test no = "$libltdl_cv_lib_dl_dlopen"
- then
- AC_CHECK_HEADERS([dns_sd.h], [],
- [AC_MSG_ERROR([Could not find dns_sd.h header, please install libavahi-compat-libdnssd-dev or equivalent.])])
include $(TOPDIR)/rules.mk
PKG_NAME:=upmpdcli
-PKG_VERSION:=1.5.19
+PKG_VERSION:=1.8.6
PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://www.lesbonscomptes.com/upmpdcli/downloads
-PKG_HASH:=67fa1f5c06fecd404f3414b25a070c9deabe917241ed6881b7a8e41e8379ed09
+PKG_HASH:=55e3d27bea5bef4560f319137f1a5c7d08abbba5a9aae90ee3240903fdb8c3e4
PKG_MAINTAINER:=
PKG_LICENSE:=LGPL-2.1-or-later
include $(TOPDIR)/rules.mk
PKG_NAME:=compose
-PKG_VERSION:=2.23.0
+PKG_VERSION:=2.23.3
PKG_RELEASE:=1
PKG_LICENSE:=Apache-2.0
PKG_LICENSE_FILES:=LICENSE
PKG_SOURCE:=v$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://codeload.github.com/docker/compose/tar.gz/v${PKG_VERSION}?
-PKG_HASH:=805ff38df265d05c7b0c9d5df1b77e9391f7995ac5ec66bde0325b03563e7b23
+PKG_HASH:=29ba96c8d398fbc6f7c791c65e70b97e7df116223f2996062441093258d914fe
PKG_MAINTAINER:=Javier Marcet <javier@marcet.info>
include $(TOPDIR)/rules.mk
PKG_NAME:=domoticz
-PKG_VERSION:=2022.1
-PKG_RELEASE:=5
+PKG_VERSION:=2023.2
+PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://codeload.github.com/domoticz/domoticz/tar.gz/$(PKG_VERSION)?
-PKG_HASH:=8282cb71c924b6ef92503976d50f966f2c785eab8f8cffa1136ac133f0241157
+PKG_HASH:=32bcf49df8c80c470352e63004a82d9601b90ccf406096099656250a4515ac28
PKG_MAINTAINER:=David Woodhouse <dwmw2@infradead.org>
PKG_LICENSE:=GPL-3.0
+++ /dev/null
-From 2975b1113d9540f39b6bade3b6d459b61c2e5007 Mon Sep 17 00:00:00 2001
-From: Arjen de Korte <build+github@de-korte.org>
-Date: Sun, 15 May 2022 19:00:02 +0200
-Subject: [PATCH] Fix compilation with GCC12
-
-Building domoticz fails under GCC12 with the following error:
-
-In file included from /usr/include/c++/12/utility:68,
- from /home/abuild/rpmbuild/BUILD/domoticz-2022.1/main/LuaTable.cpp:10:
-/usr/include/c++/12/bits/stl_relops.h:86:5: error: template with C linkage
- 86 | template <class _Tp>
- | ^~~~~~~~
----
- main/LuaTable.cpp | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/main/LuaTable.cpp
-+++ b/main/LuaTable.cpp
-@@ -6,9 +6,9 @@ extern "C" {
- #include <lua.h>
- #include <lualib.h>
- #include <lauxlib.h>
-+}
-
- #include <utility>
--}
-
- CLuaTable::CLuaTable(lua_State *lua_state, const std::string &Name)
- {
+++ /dev/null
-From 3c23a7863c0b01273d4c36423769443ea7e4a7bb Mon Sep 17 00:00:00 2001
-From: David Woodhouse <dwmw2@infradead.org>
-Date: Fri, 5 Jun 2020 15:02:41 +0100
-Subject: [PATCH 1/2] unzip: reduce file name size to 65535 to work with
- external minizip
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-The external minizip project has changed the unzGetCurrentFileInfo()
-function to take a uint16_t as the filename size, instead of a uLong
-as in the original version in zlib.
-
-(Reported as https://github.com/nmoinvaz/minizip/issues/490 but it
-was 3½ years ago and might be too late to fix it now, although changing
-it back to a *larger* type is a lot safer than reducing the size, and
-perhaps they should.)
-
-This means that our 65536-byte buffer gets truncated to zero, as the
-compiler tells us when we build agaisnt the external minizip:
-
-domoticz/main/unzip_stream.h:140:50: warning: conversion from ‘long unsigned int’ to ‘uint16_t’ {aka ‘short unsigned int’} changes value from ‘65536’ to ‘0’ [-Woverflow]
- 140 | unzGetCurrentFileInfo(handler_, &info, path, sizeof(path), NULL, 0, NULL, 0);
- | ^~~~~~~~~~~~
-
-Reduce the buffer size to 65535 bytes instead.
----
- main/unzip_stream.h | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/main/unzip_stream.h
-+++ b/main/unzip_stream.h
-@@ -143,7 +143,7 @@ namespace clx {
- basic_unzip_stream& open(handler_type h) {
- handler_ = h;
- if (handler_) {
-- char path[65536];
-+ char path[65535];
- unz_file_info info;
- unzGetCurrentFileInfo(handler_, &info, path, sizeof(path), NULL, 0, NULL, 0);
- path_ = path;
+++ /dev/null
-From 8f01ed77d5831090f34ad59d22ef1f7cd4d740f2 Mon Sep 17 00:00:00 2001
-From: dnpwwo <kendel.boul@gmail.com>
-Date: Mon, 21 Feb 2022 10:27:06 +1100
-Subject: [PATCH] Convert Python implementation to use Python's stable ABI
-
----
- hardware/plugins/DelayedLink.h | 199 +++---
- hardware/plugins/PluginManager.cpp | 17 +-
- hardware/plugins/PluginMessages.h | 1 -
- hardware/plugins/PluginProtocols.cpp | 356 ++++++-----
- hardware/plugins/PluginTransports.cpp | 64 +-
- hardware/plugins/Plugins.cpp | 883 +++++++++-----------------
- hardware/plugins/Plugins.h | 37 +-
- hardware/plugins/PythonObjectEx.cpp | 60 +-
- hardware/plugins/PythonObjectEx.h | 83 +--
- hardware/plugins/PythonObjects.cpp | 147 +++--
- hardware/plugins/PythonObjects.h | 119 ----
- main/EventSystem.cpp | 3 +-
- main/EventsPythonDevice.cpp | 12 +-
- main/EventsPythonDevice.h | 42 +-
- main/EventsPythonModule.cpp | 321 ++++++----
- main/SQLHelper.cpp | 2 +-
- 16 files changed, 980 insertions(+), 1366 deletions(-)
-
---- a/hardware/plugins/DelayedLink.h
-+++ b/hardware/plugins/DelayedLink.h
-@@ -9,10 +9,19 @@
- #ifdef WITH_THREAD
- # undefine WITH_THREAD
- #endif
-+
-+#pragma push_macro("_DEBUG")
-+#ifdef _DEBUG
-+# undef _DEBUG // Not compatible with Py_LIMITED_API
-+#endif
-+#define Py_LIMITED_API 0x03040000
- #include <Python.h>
- #include <structmember.h>
--#include <frameobject.h>
--#include "../../main/Helper.h"
-+#include "../../main/Logger.h"
-+
-+#ifndef WIN32
-+# include "../../main/Helper.h"
-+#endif
-
- namespace Plugins {
-
-@@ -29,6 +38,8 @@ namespace Plugins {
- #define DECLARE_PYTHON_SYMBOL(type, symbol, params) typedef type (PYTHON_CALL symbol##_t)(params); symbol##_t symbol
- #define RESOLVE_PYTHON_SYMBOL(symbol) symbol = (symbol##_t)RESOLVE_SYMBOL(shared_lib_, #symbol)
-
-+#undef Py_None
-+
- struct SharedLibraryProxy
- {
- #ifdef WIN32
-@@ -36,6 +47,8 @@ namespace Plugins {
- #else
- void* shared_lib_;
- #endif
-+ PyObject* Py_None;
-+
- // Shared library interface begin.
- DECLARE_PYTHON_SYMBOL(const char*, Py_GetVersion, );
- DECLARE_PYTHON_SYMBOL(int, Py_IsInitialized, );
-@@ -50,6 +63,9 @@ namespace Plugins {
- DECLARE_PYTHON_SYMBOL(wchar_t*, Py_GetProgramFullPath, );
- DECLARE_PYTHON_SYMBOL(int, PyImport_AppendInittab, const char *COMMA PyObject *(*initfunc)());
- DECLARE_PYTHON_SYMBOL(int, PyType_Ready, PyTypeObject*);
-+ DECLARE_PYTHON_SYMBOL(PyObject*, PyObject_Type, PyObject*);
-+ DECLARE_PYTHON_SYMBOL(PyObject*, PyType_FromSpec, PyType_Spec*);
-+ DECLARE_PYTHON_SYMBOL(void*, PyType_GetSlot, PyTypeObject* COMMA int);
- DECLARE_PYTHON_SYMBOL(int, PyCallable_Check, PyObject*);
- DECLARE_PYTHON_SYMBOL(PyObject*, PyObject_GetAttrString, PyObject* pObj COMMA const char*);
- DECLARE_PYTHON_SYMBOL(int, PyObject_HasAttrString, PyObject* COMMA const char *);
-@@ -60,7 +76,6 @@ namespace Plugins {
- DECLARE_PYTHON_SYMBOL(wchar_t*, PyUnicode_AsWideCharString, PyObject* COMMA Py_ssize_t*);
- DECLARE_PYTHON_SYMBOL(const char*, PyUnicode_AsUTF8, PyObject*);
- DECLARE_PYTHON_SYMBOL(char*, PyByteArray_AsString, PyObject*);
-- DECLARE_PYTHON_SYMBOL(PyObject*, PyUnicode_FromKindAndData, int COMMA const void* COMMA Py_ssize_t);
- DECLARE_PYTHON_SYMBOL(PyObject*, PyLong_FromLong, long);
- DECLARE_PYTHON_SYMBOL(PY_LONG_LONG, PyLong_AsLongLong, PyObject*);
- DECLARE_PYTHON_SYMBOL(PyObject*, PyModule_GetDict, PyObject*);
-@@ -91,8 +106,6 @@ namespace Plugins {
- DECLARE_PYTHON_SYMBOL(PyObject *, PyImport_ImportModule, const char *);
- DECLARE_PYTHON_SYMBOL(int, PyObject_RichCompareBool, PyObject* COMMA PyObject* COMMA int);
- DECLARE_PYTHON_SYMBOL(PyObject *, PyObject_CallObject, PyObject *COMMA PyObject *);
-- DECLARE_PYTHON_SYMBOL(PyObject *, PyObject_CallNoArgs, PyObject *); // Python 3.9 !!!!
-- DECLARE_PYTHON_SYMBOL(int, PyFrame_GetLineNumber, PyFrameObject*);
- DECLARE_PYTHON_SYMBOL(void, PyEval_InitThreads, );
- DECLARE_PYTHON_SYMBOL(int, PyEval_ThreadsInitialized, );
- DECLARE_PYTHON_SYMBOL(PyThreadState*, PyThreadState_Get, );
-@@ -102,17 +115,12 @@ namespace Plugins {
- DECLARE_PYTHON_SYMBOL(void, PyEval_RestoreThread, PyThreadState *);
- DECLARE_PYTHON_SYMBOL(void, PyEval_ReleaseLock, );
- DECLARE_PYTHON_SYMBOL(PyThreadState*, PyThreadState_Swap, PyThreadState*);
-- DECLARE_PYTHON_SYMBOL(int, PyGILState_Check, );
- DECLARE_PYTHON_SYMBOL(void, _Py_NegativeRefcount, const char* COMMA int COMMA PyObject*);
- DECLARE_PYTHON_SYMBOL(PyObject *, _PyObject_New, PyTypeObject *);
- DECLARE_PYTHON_SYMBOL(int, PyObject_IsInstance, PyObject* COMMA PyObject*);
- DECLARE_PYTHON_SYMBOL(int, PyObject_IsSubclass, PyObject *COMMA PyObject *);
- DECLARE_PYTHON_SYMBOL(PyObject *, PyObject_Dir, PyObject *);
--#ifdef _DEBUG
-- DECLARE_PYTHON_SYMBOL(PyObject*, PyModule_Create2TraceRefs, struct PyModuleDef* COMMA int);
--#else
- DECLARE_PYTHON_SYMBOL(PyObject*, PyModule_Create2, struct PyModuleDef* COMMA int);
--#endif
- DECLARE_PYTHON_SYMBOL(int, PyModule_AddObject, PyObject* COMMA const char* COMMA PyObject*);
- DECLARE_PYTHON_SYMBOL(int, PyArg_ParseTuple, PyObject* COMMA const char* COMMA ...);
- DECLARE_PYTHON_SYMBOL(int, PyArg_ParseTupleAndKeywords, PyObject* COMMA PyObject* COMMA const char* COMMA char*[] COMMA ...);
-@@ -120,8 +128,6 @@ namespace Plugins {
- DECLARE_PYTHON_SYMBOL(PyObject*, Py_BuildValue, const char* COMMA ...);
- DECLARE_PYTHON_SYMBOL(void, PyMem_Free, void*);
- DECLARE_PYTHON_SYMBOL(PyObject*, PyBool_FromLong, long);
-- DECLARE_PYTHON_SYMBOL(int, PyRun_SimpleStringFlags, const char* COMMA PyCompilerFlags*);
-- DECLARE_PYTHON_SYMBOL(int, PyRun_SimpleFileExFlags, FILE* COMMA const char* COMMA int COMMA PyCompilerFlags*);
- DECLARE_PYTHON_SYMBOL(void*, PyCapsule_Import, const char *name COMMA int);
- DECLARE_PYTHON_SYMBOL(void*, PyType_GenericAlloc, const PyTypeObject * COMMA Py_ssize_t);
- DECLARE_PYTHON_SYMBOL(PyObject*, PyUnicode_DecodeUTF8, const char * COMMA Py_ssize_t COMMA const char *);
-@@ -132,44 +138,32 @@ namespace Plugins {
- DECLARE_PYTHON_SYMBOL(long, PyLong_AsLong, PyObject*);
- DECLARE_PYTHON_SYMBOL(PyObject*, PyUnicode_AsUTF8String, PyObject*);
- DECLARE_PYTHON_SYMBOL(PyObject*, PyImport_AddModule, const char*);
-- DECLARE_PYTHON_SYMBOL(void, PyEval_SetProfile, Py_tracefunc COMMA PyObject*);
-- DECLARE_PYTHON_SYMBOL(void, PyEval_SetTrace, Py_tracefunc COMMA PyObject*);
- DECLARE_PYTHON_SYMBOL(PyObject*, PyObject_Str, PyObject*);
- DECLARE_PYTHON_SYMBOL(int, PyObject_IsTrue, PyObject*);
- DECLARE_PYTHON_SYMBOL(double, PyFloat_AsDouble, PyObject*);
- DECLARE_PYTHON_SYMBOL(PyObject*, PyObject_GetIter, PyObject*);
- DECLARE_PYTHON_SYMBOL(PyObject*, PyIter_Next, PyObject*);
- DECLARE_PYTHON_SYMBOL(void, PyErr_SetString, PyObject* COMMA const char*);
--
--#ifdef _DEBUG
-- // In a debug build dealloc is a function but for release builds its a macro
-+ DECLARE_PYTHON_SYMBOL(PyObject*, PyObject_CallFunctionObjArgs, PyObject* COMMA ...);
-+ DECLARE_PYTHON_SYMBOL(PyObject*, Py_CompileString, const char* COMMA const char* COMMA int);
-+ DECLARE_PYTHON_SYMBOL(PyObject*, PyEval_EvalCode, PyObject* COMMA PyObject* COMMA PyObject*);
-+ DECLARE_PYTHON_SYMBOL(long, PyType_GetFlags, PyTypeObject*);
- DECLARE_PYTHON_SYMBOL(void, _Py_Dealloc, PyObject*);
--#endif
-- Py_ssize_t _Py_RefTotal;
-- PyObject _Py_NoneStruct;
-- PyObject * dzPy_None;
-
- SharedLibraryProxy() {
-+ Py_None = nullptr;
- shared_lib_ = nullptr;
-- _Py_RefTotal = 0;
- if (!shared_lib_) {
- #ifdef WIN32
--# ifdef _DEBUG
-- if (!shared_lib_) shared_lib_ = LoadLibrary("python39_d.dll");
-- if (!shared_lib_) shared_lib_ = LoadLibrary("python38_d.dll");
-- if (!shared_lib_) shared_lib_ = LoadLibrary("python37_d.dll");
-- if (!shared_lib_) shared_lib_ = LoadLibrary("python36_d.dll");
-- if (!shared_lib_) shared_lib_ = LoadLibrary("python35_d.dll");
-- if (!shared_lib_) shared_lib_ = LoadLibrary("python34_d.dll");
--# else
-+ if (!shared_lib_) shared_lib_ = LoadLibrary("python310.dll");
- if (!shared_lib_) shared_lib_ = LoadLibrary("python39.dll");
- if (!shared_lib_) shared_lib_ = LoadLibrary("python38.dll");
- if (!shared_lib_) shared_lib_ = LoadLibrary("python37.dll");
- if (!shared_lib_) shared_lib_ = LoadLibrary("python36.dll");
- if (!shared_lib_) shared_lib_ = LoadLibrary("python35.dll");
- if (!shared_lib_) shared_lib_ = LoadLibrary("python34.dll");
--# endif
- #else
-+ if (!shared_lib_) FindLibrary("python3.10", true);
- if (!shared_lib_) FindLibrary("python3.9", true);
- if (!shared_lib_) FindLibrary("python3.8", true);
- if (!shared_lib_) FindLibrary("python3.7", true);
-@@ -198,6 +192,9 @@ namespace Plugins {
- RESOLVE_PYTHON_SYMBOL(Py_GetProgramFullPath);
- RESOLVE_PYTHON_SYMBOL(PyImport_AppendInittab);
- RESOLVE_PYTHON_SYMBOL(PyType_Ready);
-+ RESOLVE_PYTHON_SYMBOL(PyObject_Type);
-+ RESOLVE_PYTHON_SYMBOL(PyType_FromSpec);
-+ RESOLVE_PYTHON_SYMBOL(PyType_GetSlot);
- RESOLVE_PYTHON_SYMBOL(PyCallable_Check);
- RESOLVE_PYTHON_SYMBOL(PyObject_GetAttrString);
- RESOLVE_PYTHON_SYMBOL(PyObject_HasAttrString);
-@@ -208,7 +205,6 @@ namespace Plugins {
- RESOLVE_PYTHON_SYMBOL(PyUnicode_AsWideCharString);
- RESOLVE_PYTHON_SYMBOL(PyUnicode_AsUTF8);
- RESOLVE_PYTHON_SYMBOL(PyByteArray_AsString);
-- RESOLVE_PYTHON_SYMBOL(PyUnicode_FromKindAndData);
- RESOLVE_PYTHON_SYMBOL(PyLong_FromLong);
- RESOLVE_PYTHON_SYMBOL(PyLong_AsLongLong);
- RESOLVE_PYTHON_SYMBOL(PyModule_GetDict);
-@@ -239,8 +235,6 @@ namespace Plugins {
- RESOLVE_PYTHON_SYMBOL(PyImport_ImportModule);
- RESOLVE_PYTHON_SYMBOL(PyObject_RichCompareBool);
- RESOLVE_PYTHON_SYMBOL(PyObject_CallObject);
-- RESOLVE_PYTHON_SYMBOL(PyObject_CallNoArgs);
-- RESOLVE_PYTHON_SYMBOL(PyFrame_GetLineNumber);
- RESOLVE_PYTHON_SYMBOL(PyEval_InitThreads);
- RESOLVE_PYTHON_SYMBOL(PyEval_ThreadsInitialized);
- RESOLVE_PYTHON_SYMBOL(PyThreadState_Get);
-@@ -250,28 +244,18 @@ namespace Plugins {
- RESOLVE_PYTHON_SYMBOL(PyEval_RestoreThread);
- RESOLVE_PYTHON_SYMBOL(PyEval_ReleaseLock);
- RESOLVE_PYTHON_SYMBOL(PyThreadState_Swap);
-- RESOLVE_PYTHON_SYMBOL(PyGILState_Check);
- RESOLVE_PYTHON_SYMBOL(_Py_NegativeRefcount);
- RESOLVE_PYTHON_SYMBOL(_PyObject_New);
- RESOLVE_PYTHON_SYMBOL(PyObject_IsInstance);
- RESOLVE_PYTHON_SYMBOL(PyObject_IsSubclass);
- RESOLVE_PYTHON_SYMBOL(PyObject_Dir);
--#ifdef _DEBUG
-- RESOLVE_PYTHON_SYMBOL(PyModule_Create2TraceRefs);
--#else
- RESOLVE_PYTHON_SYMBOL(PyModule_Create2);
--#endif
- RESOLVE_PYTHON_SYMBOL(PyModule_AddObject);
- RESOLVE_PYTHON_SYMBOL(PyArg_ParseTuple);
- RESOLVE_PYTHON_SYMBOL(PyArg_ParseTupleAndKeywords);
- RESOLVE_PYTHON_SYMBOL(PyUnicode_FromFormat);
- RESOLVE_PYTHON_SYMBOL(Py_BuildValue);
- RESOLVE_PYTHON_SYMBOL(PyMem_Free);
--#ifdef _DEBUG
-- RESOLVE_PYTHON_SYMBOL(_Py_Dealloc);
--#endif
-- RESOLVE_PYTHON_SYMBOL(PyRun_SimpleFileExFlags);
-- RESOLVE_PYTHON_SYMBOL(PyRun_SimpleStringFlags);
- RESOLVE_PYTHON_SYMBOL(PyBool_FromLong);
- RESOLVE_PYTHON_SYMBOL(PyCapsule_Import);
- RESOLVE_PYTHON_SYMBOL(PyType_GenericAlloc);
-@@ -283,17 +267,19 @@ namespace Plugins {
- RESOLVE_PYTHON_SYMBOL(PyLong_AsLong);
- RESOLVE_PYTHON_SYMBOL(PyUnicode_AsUTF8String);
- RESOLVE_PYTHON_SYMBOL(PyImport_AddModule);
-- RESOLVE_PYTHON_SYMBOL(PyEval_SetProfile);
-- RESOLVE_PYTHON_SYMBOL(PyEval_SetTrace);
- RESOLVE_PYTHON_SYMBOL(PyObject_Str);
- RESOLVE_PYTHON_SYMBOL(PyObject_IsTrue);
- RESOLVE_PYTHON_SYMBOL(PyFloat_AsDouble);
- RESOLVE_PYTHON_SYMBOL(PyObject_GetIter);
- RESOLVE_PYTHON_SYMBOL(PyIter_Next);
- RESOLVE_PYTHON_SYMBOL(PyErr_SetString);
-+ RESOLVE_PYTHON_SYMBOL(PyObject_CallFunctionObjArgs);
-+ RESOLVE_PYTHON_SYMBOL(Py_CompileString);
-+ RESOLVE_PYTHON_SYMBOL(PyEval_EvalCode);
-+ RESOLVE_PYTHON_SYMBOL(PyType_GetFlags);
-+ RESOLVE_PYTHON_SYMBOL(_Py_Dealloc);
- }
- }
-- _Py_NoneStruct.ob_refcnt = 1;
- };
- ~SharedLibraryProxy() = default;
-
-@@ -412,15 +398,7 @@ namespace Plugins {
-
- extern SharedLibraryProxy* pythonLib;
-
--// Create local pointer to Py_None, required to work around build complaints
--#ifdef Py_None
-- #undef Py_None
--#endif
--#define Py_None pythonLib->dzPy_None
--#ifdef Py_RETURN_NONE
-- #define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None
--#endif
--#define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None
-+#define Py_None pythonLib->Py_None
- #define Py_LoadLibrary pythonLib->Py_LoadLibrary
- #define Py_GetVersion pythonLib->Py_GetVersion
- #define Py_IsInitialized pythonLib->Py_IsInitialized
-@@ -435,6 +413,9 @@ extern SharedLibraryProxy* pythonLib;
- #define Py_GetProgramFullPath pythonLib->Py_GetProgramFullPath
- #define PyImport_AppendInittab pythonLib->PyImport_AppendInittab
- #define PyType_Ready pythonLib->PyType_Ready
-+#define PyObject_Type pythonLib->PyObject_Type
-+#define PyType_FromSpec pythonLib->PyType_FromSpec
-+#define PyType_GetSlot pythonLib->PyType_GetSlot
- #define PyCallable_Check pythonLib->PyCallable_Check
- #define PyObject_GetAttrString pythonLib->PyObject_GetAttrString
- #define PyObject_HasAttrString pythonLib->PyObject_HasAttrString
-@@ -446,7 +427,6 @@ extern SharedLibraryProxy* pythonLib;
- #define PyUnicode_AsWideCharString pythonLib->PyUnicode_AsWideCharString
- #define PyUnicode_AsUTF8 pythonLib->PyUnicode_AsUTF8
- #define PyByteArray_AsString pythonLib->PyByteArray_AsString
--#define PyUnicode_FromKindAndData pythonLib->PyUnicode_FromKindAndData
- #define PyLong_FromLong pythonLib->PyLong_FromLong
- #define PyLong_AsLongLong pythonLib->PyLong_AsLongLong
- #define PyModule_GetDict pythonLib->PyModule_GetDict
-@@ -460,7 +440,7 @@ extern SharedLibraryProxy* pythonLib;
- #define PyDict_SetItem pythonLib->PyDict_SetItem
- #define PyDict_DelItem pythonLib->PyDict_DelItem
- #define PyDict_DelItemString pythonLib->PyDict_DelItemString
--#define PyDict_Next pythonLib->PyDict_Next
-+#define PyDict_Next pythonLib->PyDict_Next
- #define PyDict_Items pythonLib->PyDict_Items
- #define PyList_New pythonLib->PyList_New
- #define PyList_Size pythonLib->PyList_Size
-@@ -477,8 +457,6 @@ extern SharedLibraryProxy* pythonLib;
- #define PyImport_ImportModule pythonLib->PyImport_ImportModule
- #define PyObject_RichCompareBool pythonLib->PyObject_RichCompareBool
- #define PyObject_CallObject pythonLib->PyObject_CallObject
--#define PyObject_CallNoArgs pythonLib->PyObject_CallNoArgs
--#define PyFrame_GetLineNumber pythonLib->PyFrame_GetLineNumber
- #define PyEval_InitThreads pythonLib->PyEval_InitThreads
- #define PyEval_ThreadsInitialized pythonLib->PyEval_ThreadsInitialized
- #define PyThreadState_Get pythonLib->PyThreadState_Get
-@@ -488,7 +466,6 @@ extern SharedLibraryProxy* pythonLib;
- #define PyEval_RestoreThread pythonLib->PyEval_RestoreThread
- #define PyEval_ReleaseLock pythonLib->PyEval_ReleaseLock
- #define PyThreadState_Swap pythonLib->PyThreadState_Swap
--#define PyGILState_Check pythonLib->PyGILState_Check
- #define _Py_NegativeRefcount pythonLib->_Py_NegativeRefcount
- #define _PyObject_New pythonLib->_PyObject_New
- #define PyObject_IsInstance pythonLib->PyObject_IsInstance
-@@ -497,22 +474,10 @@ extern SharedLibraryProxy* pythonLib;
- #define PyArg_ParseTuple pythonLib->PyArg_ParseTuple
- #define Py_BuildValue pythonLib->Py_BuildValue
- #define PyMem_Free pythonLib->PyMem_Free
--#ifdef _DEBUG
--# define PyModule_Create2TraceRefs pythonLib->PyModule_Create2TraceRefs
--#else
--# define PyModule_Create2 pythonLib->PyModule_Create2
--#endif
-+#define PyModule_Create2 pythonLib->PyModule_Create2
- #define PyModule_AddObject pythonLib->PyModule_AddObject
- #define PyArg_ParseTupleAndKeywords pythonLib->PyArg_ParseTupleAndKeywords
--
--#ifdef _DEBUG
--# define _Py_Dealloc pythonLib->_Py_Dealloc
--#endif
--
- #define _Py_RefTotal pythonLib->_Py_RefTotal
--#define _Py_NoneStruct pythonLib->_Py_NoneStruct
--#define PyRun_SimpleStringFlags pythonLib->PyRun_SimpleStringFlags
--#define PyRun_SimpleFileExFlags pythonLib->PyRun_SimpleFileExFlags
- #define PyBool_FromLong pythonLib->PyBool_FromLong
- #define PyCapsule_Import pythonLib->PyCapsule_Import
- #define PyType_GenericAlloc pythonLib->PyType_GenericAlloc
-@@ -524,80 +489,88 @@ extern SharedLibraryProxy* pythonLib;
- #define PyLong_AsLong pythonLib->PyLong_AsLong
- #define PyUnicode_AsUTF8String pythonLib->PyUnicode_AsUTF8String
- #define PyImport_AddModule pythonLib->PyImport_AddModule
--#define PyEval_SetProfile pythonLib->PyEval_SetProfile
--#define PyEval_SetTrace pythonLib->PyEval_SetTrace
- #define PyObject_Str pythonLib->PyObject_Str
- #define PyObject_IsTrue pythonLib->PyObject_IsTrue
- #define PyFloat_AsDouble pythonLib->PyFloat_AsDouble
- #define PyObject_GetIter pythonLib->PyObject_GetIter
- #define PyIter_Next pythonLib->PyIter_Next
- #define PyErr_SetString pythonLib->PyErr_SetString
--
--#ifndef _Py_DEC_REFTOTAL
--/* _Py_DEC_REFTOTAL macro has been removed from Python 3.9 by: https://github.com/python/cpython/commit/49932fec62c616ec88da52642339d83ae719e924 */
--#ifdef Py_REF_DEBUG
--#define _Py_DEC_REFTOTAL _Py_RefTotal--
-+#define PyObject_CallFunctionObjArgs pythonLib->PyObject_CallFunctionObjArgs
-+#define Py_CompileString pythonLib->Py_CompileString
-+#define PyEval_EvalCode pythonLib->PyEval_EvalCode
-+#define PyType_GetFlags pythonLib->PyType_GetFlags
-+#ifdef WIN32
-+# define _Py_Dealloc pythonLib->_Py_Dealloc // Builds against a low Python version
-+#elif PY_VERSION_HEX < 0x03090000
-+# define _Py_Dealloc pythonLib->_Py_Dealloc
- #else
--#define _Py_DEC_REFTOTAL
--#define _Py_Dealloc
--#endif
-+# ifndef _Py_DEC_REFTOTAL
-+ /* _Py_DEC_REFTOTAL macro has been removed from Python 3.9 by: https://github.com/python/cpython/commit/49932fec62c616ec88da52642339d83ae719e924 */
-+# ifdef Py_REF_DEBUG
-+# define _Py_DEC_REFTOTAL _Py_RefTotal--
-+# else
-+# define _Py_DEC_REFTOTAL
-+# define _Py_Dealloc
-+# endif
-+# endif
- #endif
-
- #if PY_VERSION_HEX >= 0x030800f0
-- static inline void py3__Py_INCREF(PyObject *op)
-- {
-+static inline void py3__Py_INCREF(PyObject* op)
-+{
- #ifdef Py_REF_DEBUG
-- _Py_RefTotal++;
-+ _Py_RefTotal++;
- #endif
-- op->ob_refcnt++;
-- }
-+ op->ob_refcnt++;
-+}
-
- #undef Py_INCREF
- #define Py_INCREF(op) py3__Py_INCREF(_PyObject_CAST(op))
-
-- static inline void py3__Py_XINCREF(PyObject *op)
-+static inline void py3__Py_XINCREF(PyObject* op)
-+{
-+ if (op != NULL)
- {
-- if (op != NULL)
-- {
-- Py_INCREF(op);
-- }
-+ Py_INCREF(op);
- }
-+}
-
- #undef Py_XINCREF
- #define Py_XINCREF(op) py3__Py_XINCREF(_PyObject_CAST(op))
-
-- static inline void py3__Py_DECREF(const char *filename, int lineno, PyObject *op)
-+static inline void py3__Py_DECREF(const char* filename, int lineno, PyObject* op)
-+{
-+ (void)filename; /* may be unused, shut up -Wunused-parameter */
-+ (void)lineno; /* may be unused, shut up -Wunused-parameter */
-+ _Py_DEC_REFTOTAL;
-+ if (--op->ob_refcnt != 0)
- {
-- (void)filename; /* may be unused, shut up -Wunused-parameter */
-- (void)lineno; /* may be unused, shut up -Wunused-parameter */
-- _Py_DEC_REFTOTAL;
-- if (--op->ob_refcnt != 0)
-- {
- #ifdef Py_REF_DEBUG
-- if (op->ob_refcnt < 0)
-- {
-- _Py_NegativeRefcount(filename, lineno, op);
-- }
--#endif
-- }
-- else
-+ if (op->ob_refcnt < 0)
- {
-- _Py_Dealloc(op);
-+ _Py_NegativeRefcount(filename, lineno, op);
- }
-+#endif
-+ }
-+ else
-+ {
-+ _Py_Dealloc(op);
- }
-+}
-
- #undef Py_DECREF
- #define Py_DECREF(op) py3__Py_DECREF(__FILE__, __LINE__, _PyObject_CAST(op))
-
-- static inline void py3__Py_XDECREF(PyObject *op)
-+static inline void py3__Py_XDECREF(PyObject* op)
-+{
-+ if (op != nullptr)
- {
-- if (op != nullptr)
-- {
-- Py_DECREF(op);
-- }
-+ Py_DECREF(op);
- }
-+}
-
- #undef Py_XDECREF
- #define Py_XDECREF(op) py3__Py_XDECREF(_PyObject_CAST(op))
- #endif
-+#pragma pop_macro("_DEBUG")
- } // namespace Plugins
---- a/hardware/plugins/PluginManager.cpp
-+++ b/hardware/plugins/PluginManager.cpp
-@@ -31,7 +31,9 @@
- #include "DelayedLink.h"
- #include "../../main/EventsPythonModule.h"
-
--#define MINIMUM_PYTHON_VERSION "3.4.0"
-+// Python version constants
-+#define MINIMUM_MAJOR_VERSION 3
-+#define MINIMUM_MINOR_VERSION 4
-
- #define ATTRIBUTE_VALUE(pElement, Name, Value) \
- { \
-@@ -105,9 +107,18 @@ namespace Plugins {
- }
-
- std::string sVersion = szPyVersion.substr(0, szPyVersion.find_first_of(' '));
-- if (sVersion < MINIMUM_PYTHON_VERSION)
-+
-+ std::string sMajorVersion = sVersion.substr(0, sVersion.find_first_of('.'));
-+ if (std::stoi(sMajorVersion) < MINIMUM_MAJOR_VERSION)
-+ {
-+ _log.Log(LOG_STATUS, "PluginSystem: Invalid Python version '%s' found, Major version '%d' or above required.", sVersion.c_str(), MINIMUM_MAJOR_VERSION);
-+ return false;
-+ }
-+
-+ std::string sMinorVersion = sVersion.substr(sMajorVersion.length()+1);
-+ if (std::stoi(sMinorVersion) < MINIMUM_MINOR_VERSION)
- {
-- _log.Log(LOG_STATUS, "PluginSystem: Invalid Python version '%s' found, '%s' or above required.", sVersion.c_str(), MINIMUM_PYTHON_VERSION);
-+ _log.Log(LOG_STATUS, "PluginSystem: Invalid Python version '%s' found, Minor version '%d.%d' or above required.", sVersion.c_str(), MINIMUM_MAJOR_VERSION, MINIMUM_MINOR_VERSION);
- return false;
- }
-
---- a/hardware/plugins/PluginMessages.h
-+++ b/hardware/plugins/PluginMessages.h
-@@ -60,7 +60,6 @@ namespace Plugins {
- InitializeMessage() : CPluginMessageBase() { m_Name = __func__; };
- void Process(CPlugin* pPlugin) override
- {
-- //std::lock_guard<std::mutex> l(PythonMutex);
- pPlugin->Initialise();
- };
- void ProcessLocked(CPlugin* pPlugin) override{};
---- a/hardware/plugins/PluginProtocols.cpp
-+++ b/hardware/plugins/PluginProtocols.cpp
-@@ -5,6 +5,7 @@
- //
- #ifdef ENABLE_PYTHON
-
-+#include "../../main/Helper.h"
- #include "PluginMessages.h"
- #include "PluginProtocols.h"
- #include "../../main/Helper.h"
-@@ -52,32 +53,37 @@ namespace Plugins {
- std::vector<byte> CPluginProtocol::ProcessOutbound(const WriteDirective* WriteMessage)
- {
- std::vector<byte> retVal;
-+ PyBorrowedRef pObject(WriteMessage->m_Object);
-
- // Handle Bytes objects
-- if ((((PyObject*)WriteMessage->m_Object)->ob_type->tp_flags & (Py_TPFLAGS_BYTES_SUBCLASS)) != 0)
-+ if (pObject.IsBytes())
- {
-- const char* pData = PyBytes_AsString(WriteMessage->m_Object);
-- int iSize = PyBytes_Size(WriteMessage->m_Object);
-+ const char* pData = PyBytes_AsString(pObject);
-+ int iSize = PyBytes_Size(pObject);
- retVal.reserve((size_t)iSize);
- retVal.assign(pData, pData + iSize);
- }
- // Handle ByteArray objects
-- else if ((((PyObject*)WriteMessage->m_Object)->ob_type->tp_name == std::string("bytearray")))
-+ else if (pObject.IsByteArray())
- {
-- size_t len = PyByteArray_Size(WriteMessage->m_Object);
-- char* data = PyByteArray_AsString(WriteMessage->m_Object);
-+ size_t len = PyByteArray_Size(pObject);
-+ char* data = PyByteArray_AsString(pObject);
- retVal.reserve(len);
- retVal.assign((const byte*)data, (const byte*)data + len);
- }
-- // Handle String objects
-- else if ((((PyObject*)WriteMessage->m_Object)->ob_type->tp_flags & (Py_TPFLAGS_UNICODE_SUBCLASS)) != 0)
-+ // Try forcing a String conversion
-+ else
- {
-- std::string sData = PyUnicode_AsUTF8(WriteMessage->m_Object);
-- retVal.reserve((size_t)sData.length());
-- retVal.assign((const byte*)sData.c_str(), (const byte*)sData.c_str() + sData.length());
-+ PyNewRef pStr = PyObject_Str(pObject);
-+ if (pStr)
-+ {
-+ std::string sData = PyUnicode_AsUTF8(pStr);
-+ retVal.reserve((size_t)sData.length());
-+ retVal.assign((const byte*)sData.c_str(), (const byte*)sData.c_str() + sData.length());
-+ }
-+ else
-+ _log.Log(LOG_ERROR, "(%s) Unable to convert data (%s) to string representation, ignored.", __func__, pObject.Type().c_str());
- }
-- else
-- _log.Log(LOG_ERROR, "(%s) Send request Python object parameter was not of type Unicode or Byte, ignored.", __func__);
-
- return retVal;
- }
-@@ -120,7 +126,7 @@ namespace Plugins {
- if (PyDict_SetItemString(pDict, key, pObj) == -1)
- _log.Log(LOG_ERROR, "(%s) failed to add key '%s', value '%s' to dictionary.", __func__, key, value.c_str());
- }
--
-+
- static void AddStringToDict(PyObject* pDict, const char* key, const std::string& value)
- {
- PyNewRef pObj = Py_BuildValue("s#", value.c_str(), value.length());
-@@ -166,7 +172,7 @@ namespace Plugins {
- Py_ssize_t Index = 0;
- for (auto &pRef : *pJSON)
- {
-- // PyList_SetItem 'steal' a reference so use PyBorrowedRef instead of PyNewRef
-+ // PyList_SetItem 'steals' a reference so use PyBorrowedRef instead of PyNewRef
- if (pRef.isArray() || pRef.isObject())
- {
- PyBorrowedRef pObj = JSONtoPython(&pRef);
-@@ -239,7 +245,7 @@ namespace Plugins {
- bool bRet = ParseJSon(sData, root);
- if ((!bRet) || (!root.isObject()))
- {
-- _log.Log(LOG_ERROR, "JSON Protocol: Parse Error on '%s'", sData.c_str());
-+ _log.Log(LOG_ERROR, "(%s) Parse Error on '%s'", __func__, sData.c_str());
- Py_RETURN_NONE;
- }
- else
-@@ -253,66 +259,77 @@ namespace Plugins {
- std::string CPluginProtocolJSON::PythontoJSON(PyObject* pObject)
- {
- std::string sJson;
-+ PyBorrowedRef pObj(pObject);
-
-- if (PyUnicode_Check(pObject))
-- {
-- sJson += '"' + std::string(PyUnicode_AsUTF8(pObject)) + '"';
-- }
-- else if (pObject->ob_type->tp_name == std::string("bool"))
-- {
-- sJson += (PyObject_IsTrue(pObject) ? "true" : "false");
-- }
-- else if (PyLong_Check(pObject))
-- {
-- sJson += std::to_string(PyLong_AsLong(pObject));
-- }
-- else if (PyBytes_Check(pObject))
-- {
-- sJson += '"' + std::string(PyBytes_AsString(pObject)) + '"';
-- }
-- else if (pObject->ob_type->tp_name == std::string("bytearray"))
-- {
-- sJson += '"' + std::string(PyByteArray_AsString(pObject)) + '"';
-- }
-- else if (pObject->ob_type->tp_name == std::string("float"))
-- {
-- sJson += std::to_string(PyFloat_AsDouble(pObject));
-- }
-- else if (PyDict_Check(pObject))
-+ if (pObj.IsDict())
- {
- sJson += "{ ";
- PyObject* key, * value;
- Py_ssize_t pos = 0;
-- while (PyDict_Next(pObject, &pos, &key, &value))
-+ while (PyDict_Next(pObj, &pos, &key, &value))
- {
- sJson += PythontoJSON(key) + ':' + PythontoJSON(value) + ',';
- }
- sJson[sJson.length() - 1] = '}';
- }
-- else if (PyList_Check(pObject))
-+ else if (pObj.IsList())
- {
- sJson += "[ ";
-- for (Py_ssize_t i = 0; i < PyList_Size(pObject); i++)
-+ for (Py_ssize_t i = 0; i < PyList_Size(pObj); i++)
- {
-- sJson += PythontoJSON(PyList_GetItem(pObject, i)) + ',';
-+ sJson += PythontoJSON(PyList_GetItem(pObj, i)) + ',';
- }
- sJson[sJson.length() - 1] = ']';
- }
-- else if (PyTuple_Check(pObject))
-+ else if (pObj.IsTuple())
- {
- sJson += "[ ";
-- for (Py_ssize_t i = 0; i < PyTuple_Size(pObject); i++)
-+ for (Py_ssize_t i = 0; i < PyTuple_Size(pObj); i++)
- {
-- sJson += PythontoJSON(PyTuple_GetItem(pObject, i)) + ',';
-+ sJson += PythontoJSON(PyTuple_GetItem(pObj, i)) + ',';
- }
- sJson[sJson.length() - 1] = ']';
- }
-+ else if (pObj.IsBool())
-+ {
-+ sJson += (PyObject_IsTrue(pObj) ? "true" : "false");
-+ }
-+ else if (pObj.IsLong())
-+ {
-+ sJson += std::to_string(PyLong_AsLong(pObj));
-+ }
-+ else if (pObj.IsFloat())
-+ {
-+ sJson += std::to_string(PyFloat_AsDouble(pObj));
-+ }
-+ else if (pObj.IsBytes())
-+ {
-+ sJson += '"' + std::string(PyBytes_AsString(pObj)) + '"';
-+ }
-+ else if (pObj.IsByteArray())
-+ {
-+ sJson += '"' + std::string(PyByteArray_AsString(pObj)) + '"';
-+ }
-+ else
-+ {
-+ // Try forcing a String conversion
-+ PyNewRef pStr = PyObject_Str(pObject);
-+ if (pStr)
-+ {
-+ sJson += '"' + std::string(PyUnicode_AsUTF8(pStr)) + '"';
-+ }
-+ else
-+ _log.Log(LOG_ERROR, "(%s) Unable to convert data type (%s) to string representation, ignored.", __func__, pObj.Type().c_str());
-+ }
-
- return sJson;
- }
-
- void CPluginProtocolJSON::ProcessInbound(const ReadEvent* Message)
- {
-+ CConnection* pConnection = Message->m_pConnection;
-+ CPlugin* pPlugin = pConnection->pPlugin;
-+
- //
- // Handles the cases where a read contains a partial message or multiple messages
- //
-@@ -332,13 +349,13 @@ namespace Plugins {
- bool bRet = ParseJSon(sData, root);
- if ((!bRet) || (!root.isObject()))
- {
-- _log.Log(LOG_ERROR, "JSON Protocol: Parse Error on '%s'", sData.c_str());
-- Message->m_pConnection->pPlugin->MessagePlugin(new onMessageCallback(Message->m_pConnection, sData));
-+ pPlugin->Log(LOG_ERROR, "(%s) Parse Error on '%s'", __func__, sData.c_str());
-+ pPlugin->MessagePlugin(new onMessageCallback(pConnection, sData));
- }
- else
- {
- PyObject* pMessage = JSONtoPython(&root);
-- Message->m_pConnection->pPlugin->MessagePlugin(new onMessageCallback(Message->m_pConnection, pMessage));
-+ pPlugin->MessagePlugin(new onMessageCallback(pConnection, pMessage));
- }
- sData.clear();
- }
-@@ -350,13 +367,13 @@ namespace Plugins {
- bool bRet = ParseJSon(sMessage, root);
- if ((!bRet) || (!root.isObject()))
- {
-- _log.Log(LOG_ERROR, "JSON Protocol: Parse Error on '%s'", sData.c_str());
-- Message->m_pConnection->pPlugin->MessagePlugin(new onMessageCallback(Message->m_pConnection, sMessage));
-+ pPlugin->Log(LOG_ERROR, "(%s) Parse Error on '%s'", __func__, sData.c_str());
-+ pPlugin->MessagePlugin(new onMessageCallback(pConnection, sMessage));
- }
- else
- {
- PyObject* pMessage = JSONtoPython(&root);
-- Message->m_pConnection->pPlugin->MessagePlugin(new onMessageCallback(Message->m_pConnection, pMessage));
-+ pPlugin->MessagePlugin(new onMessageCallback(pConnection, pMessage));
- }
- }
- }
-@@ -467,7 +484,7 @@ namespace Plugins {
- {
- PyObject* pListObj = pPrevObj;
- // First duplicate? Create a list and add previous value
-- if (!PyList_Check(pListObj))
-+ if (!pPrevObj.IsList())
- {
- pListObj = PyList_New(1);
- if (!pListObj)
-@@ -732,7 +749,7 @@ namespace Plugins {
- std::string sHttp;
-
- // Sanity check input
-- if (!WriteMessage->m_Object || !PyDict_Check(WriteMessage->m_Object))
-+ if (PyBorrowedRef(WriteMessage->m_Object).Type() != "dict")
- {
- _log.Log(LOG_ERROR, "(%s) HTTP Send parameter was not a dictionary, ignored. See Python Plugin wiki page for help.", __func__);
- return retVal;
-@@ -763,7 +780,7 @@ namespace Plugins {
- //
- // param1=value¶m2=other+value
-
-- if (!PyUnicode_Check(pVerb))
-+ if (!pVerb.IsString())
- {
- _log.Log(LOG_ERROR, "(%s) HTTP 'Verb' dictionary entry not a string, ignored. See Python Plugin wiki page for help.", __func__);
- return retVal;
-@@ -774,7 +791,7 @@ namespace Plugins {
-
- PyBorrowedRef pURL = PyDict_GetItemString(WriteMessage->m_Object, "URL");
- std::string sHttpURL = "/";
-- if (pURL && PyUnicode_Check(pURL))
-+ if (pURL.IsString())
- {
- sHttpURL = PyUnicode_AsUTF8(pURL);
- }
-@@ -840,7 +857,7 @@ namespace Plugins {
- // </body>
- // </html>
-
-- if (!PyUnicode_Check(pStatus))
-+ if (!pStatus.IsString())
- {
- _log.Log(LOG_ERROR, "(%s) HTTP 'Status' dictionary entry was not a string, ignored. See Python Plugin wiki page for help.", __func__);
- return retVal;
-@@ -886,53 +903,53 @@ namespace Plugins {
- // Did we get headers to send?
- if (pHeaders)
- {
-- if (PyDict_Check(pHeaders))
-+ if (pHeaders.IsDict())
- {
- PyObject* key, * value;
- Py_ssize_t pos = 0;
- while (PyDict_Next(pHeaders, &pos, &key, &value))
- {
- std::string sKey = PyUnicode_AsUTF8(key);
-- if (PyUnicode_Check(value))
-+ PyBorrowedRef pValue(value);
-+ if (pValue.IsString())
- {
- std::string sValue = PyUnicode_AsUTF8(value);
- sHttp += sKey + ": " + sValue + "\r\n";
- }
-- else if (PyBytes_Check(value))
-+ else if (pValue.IsBytes())
- {
- const char* pBytes = PyBytes_AsString(value);
- sHttp += sKey + ": " + pBytes + "\r\n";
- }
-- else if (value->ob_type->tp_name == std::string("bytearray"))
-+ else if (pValue.IsByteArray())
- {
- const char* pByteArray = PyByteArray_AsString(value);
- sHttp += sKey + ": " + pByteArray + "\r\n";
- }
-- else if (PyList_Check(value))
-+ else if (pValue.IsList())
- {
-- PyObject* iterator = PyObject_GetIter(value);
-- PyObject* item;
-- while ((item = PyIter_Next(iterator)))
-+ PyNewRef iterator = PyObject_GetIter(value);
-+ PyObject* item;
-+ while (item = PyIter_Next(iterator))
- {
-- if (PyUnicode_Check(item))
-+ PyBorrowedRef pItem(item);
-+ if (pItem.IsString())
- {
- std::string sValue = PyUnicode_AsUTF8(item);
- sHttp += sKey + ": " + sValue + "\r\n";
- }
-- else if (PyBytes_Check(item))
-+ else if (pItem.IsBytes())
- {
- const char* pBytes = PyBytes_AsString(item);
- sHttp += sKey + ": " + pBytes + "\r\n";
- }
-- else if (item->ob_type->tp_name == std::string("bytearray"))
-+ else if (pItem.IsByteArray())
- {
- const char* pByteArray = PyByteArray_AsString(item);
- sHttp += sKey + ": " + pByteArray + "\r\n";
- }
- Py_DECREF(item);
- }
--
-- Py_DECREF(iterator);
- }
- }
- }
-@@ -949,11 +966,11 @@ namespace Plugins {
- if (!pLength && pData && !pChunk)
- {
- Py_ssize_t iLength = 0;
-- if (PyUnicode_Check(pData))
-+ if (pData.IsString())
- iLength = PyUnicode_GetLength(pData);
-- else if (pData->ob_type->tp_name == std::string("bytearray"))
-+ else if (pData.IsByteArray())
- iLength = PyByteArray_Size(pData);
-- else if (PyBytes_Check(pData))
-+ else if (pData.IsBytes())
- iLength = PyBytes_Size(pData);
- sHttp += "Content-Length: " + std::to_string(iLength) + "\r\n";
- }
-@@ -977,15 +994,12 @@ namespace Plugins {
- if (pChunk)
- {
- long lChunkLength = 0;
-- if (pData)
-- {
-- if (PyUnicode_Check(pData))
-- lChunkLength = PyUnicode_GetLength(pData);
-- else if (pData->ob_type->tp_name == std::string("bytearray"))
-- lChunkLength = PyByteArray_Size(pData);
-- else if (PyBytes_Check(pData))
-- lChunkLength = PyBytes_Size(pData);
-- }
-+ if (pData.IsString())
-+ lChunkLength = PyUnicode_GetLength(pData);
-+ else if (pData.IsByteArray())
-+ lChunkLength = PyByteArray_Size(pData);
-+ else if (pData.IsBytes())
-+ lChunkLength = PyBytes_Size(pData);
- std::stringstream stream;
- stream << std::hex << lChunkLength;
- sHttp += std::string(stream.str());
-@@ -993,13 +1007,13 @@ namespace Plugins {
- }
-
- // Append data if supplied (for POST) or Response
-- if (pData && PyUnicode_Check(pData))
-+ if (pData.IsString())
- {
- sHttp += PyUnicode_AsUTF8(pData);
- retVal.reserve(sHttp.length() + 2);
- retVal.assign(sHttp.c_str(), sHttp.c_str() + sHttp.length());
- }
-- else if (pData && (pData->ob_type->tp_name == std::string("bytearray")))
-+ else if (pData.IsByteArray())
- {
- retVal.reserve(sHttp.length() + PyByteArray_Size(pData) + 2);
- retVal.assign(sHttp.c_str(), sHttp.c_str() + sHttp.length());
-@@ -1010,7 +1024,7 @@ namespace Plugins {
- retVal.push_back(pByteArray[i]);
- }
- }
-- else if (pData && PyBytes_Check(pData))
-+ else if (pData.IsBytes())
- {
- retVal.reserve(sHttp.length() + PyBytes_Size(pData) + 2);
- retVal.assign(sHttp.c_str(), sHttp.c_str() + sHttp.length());
-@@ -1700,7 +1714,7 @@ namespace Plugins {
- std::vector<byte> retVal;
-
- // Sanity check input
-- if (!WriteMessage->m_Object || !PyDict_Check(WriteMessage->m_Object))
-+ if (!PyBorrowedRef(WriteMessage->m_Object).IsDict())
- {
- _log.Log(LOG_ERROR, "(%s) MQTT Send parameter was not a dictionary, ignored. See Python Plugin wiki page for help.", __func__);
- return retVal;
-@@ -1710,7 +1724,7 @@ namespace Plugins {
- PyBorrowedRef pVerb = PyDict_GetItemString(WriteMessage->m_Object, "Verb");
- if (pVerb)
- {
-- if (!PyUnicode_Check(pVerb))
-+ if (!pVerb.IsString())
- {
- _log.Log(LOG_ERROR, "(%s) MQTT 'Verb' dictionary entry not a string, ignored. See Python Plugin wiki page for help.", __func__);
- return retVal;
-@@ -1726,7 +1740,7 @@ namespace Plugins {
-
- // Client Identifier
- PyBorrowedRef pID = PyDict_GetItemString(WriteMessage->m_Object, "ID");
-- if (pID && PyUnicode_Check(pID))
-+ if (pID.IsString())
- {
- MQTTPushBackStringWLen(std::string(PyUnicode_AsUTF8(pID)), vPayload);
- }
-@@ -1735,7 +1749,7 @@ namespace Plugins {
-
- byte bCleanSession = 1;
- PyBorrowedRef pCleanSession = PyDict_GetItemString(WriteMessage->m_Object, "CleanSession");
-- if (pCleanSession && PyLong_Check(pCleanSession))
-+ if (pCleanSession.IsLong())
- {
- bCleanSession = (byte)PyLong_AsLong(pCleanSession);
- }
-@@ -1743,7 +1757,7 @@ namespace Plugins {
-
- // Will topic
- PyBorrowedRef pTopic = PyDict_GetItemString(WriteMessage->m_Object, "WillTopic");
-- if (pTopic && PyUnicode_Check(pTopic))
-+ if (pTopic.IsString())
- {
- MQTTPushBackStringWLen(std::string(PyUnicode_AsUTF8(pTopic)), vPayload);
- bControlFlags |= 4;
-@@ -1753,14 +1767,14 @@ namespace Plugins {
- if (bControlFlags & 4)
- {
- PyBorrowedRef pQoS = PyDict_GetItemString(WriteMessage->m_Object, "WillQoS");
-- if (pQoS && PyLong_Check(pQoS))
-+ if (pQoS.IsLong())
- {
- byte bQoS = (byte)PyLong_AsLong(pQoS);
- bControlFlags |= (bQoS & 3) << 3; // Set QoS flag
- }
-
- PyBorrowedRef pRetain = PyDict_GetItemString(WriteMessage->m_Object, "WillRetain");
-- if (pRetain && PyLong_Check(pRetain))
-+ if (pRetain.IsLong())
- {
- byte bRetain = (byte)PyLong_AsLong(pRetain);
- bControlFlags |= (bRetain & 1) << 5; // Set retain flag
-@@ -1770,11 +1784,11 @@ namespace Plugins {
- PyBorrowedRef pPayload = PyDict_GetItemString(WriteMessage->m_Object, "WillPayload");
- // Support both string and bytes
- //if (pPayload && PyByteArray_Check(pPayload)) // Gives linker error, why?
-- if (pPayload && pPayload->ob_type->tp_name == std::string("bytearray"))
-+ if (pPayload.IsByteArray())
- {
- sPayload = std::string(PyByteArray_AsString(pPayload), PyByteArray_Size(pPayload));
- }
-- else if (pPayload && PyUnicode_Check(pPayload))
-+ else if (pPayload.IsString())
- {
- sPayload = std::string(PyUnicode_AsUTF8(pPayload));
- }
-@@ -1786,7 +1800,7 @@ namespace Plugins {
- std::string Pass;
- PyObject* pModule = (PyObject*)WriteMessage->m_pConnection->pPlugin->PythonModule();
- PyNewRef pDict = PyObject_GetAttrString(pModule, "Parameters");
-- if (pDict)
-+ if (pDict.IsDict())
- {
- PyBorrowedRef pUser = PyDict_GetItemString(pDict, "Username");
- if (pUser) User = PyUnicode_AsUTF8(pUser);
-@@ -1829,7 +1843,7 @@ namespace Plugins {
- // Connect Reason Code
- pDictEntry = PyDict_GetItemString(WriteMessage->m_Object, "ReasonCode");
- byteValue = 0;
-- if (pDictEntry && PyLong_Check(pDictEntry))
-+ if (pDictEntry.IsLong())
- {
- byteValue = PyLong_AsLong(pDictEntry) & 0xFF;
- }
-@@ -1838,35 +1852,35 @@ namespace Plugins {
- // CONNACK Properties
- std::vector<byte> vProperties;
- pDictEntry = PyDict_GetItemString(WriteMessage->m_Object, "SessionExpiryInterval");
-- if (pDictEntry && PyLong_Check(pDictEntry))
-+ if (pDictEntry.IsLong())
- {
- vProperties.push_back(17);
- MQTTPushBackLong(PyLong_AsLong(pDictEntry), vProperties);
- }
-
- pDictEntry = PyDict_GetItemString(WriteMessage->m_Object, "MaximumQoS");
-- if (pDictEntry && PyLong_Check(pDictEntry))
-+ if (pDictEntry.IsLong())
- {
- vProperties.push_back(36);
- vProperties.push_back((byte)PyLong_AsLong(pDictEntry));
- }
-
- pDictEntry = PyDict_GetItemString(WriteMessage->m_Object, "RetainAvailable");
-- if (pDictEntry && PyLong_Check(pDictEntry))
-+ if (pDictEntry.IsLong())
- {
- vProperties.push_back(37);
- vProperties.push_back((byte)PyLong_AsLong(pDictEntry));
- }
-
- pDictEntry = PyDict_GetItemString(WriteMessage->m_Object, "MaximumPacketSize");
-- if (pDictEntry && PyLong_Check(pDictEntry))
-+ if (pDictEntry.IsLong())
- {
- vProperties.push_back(39);
- MQTTPushBackLong(PyLong_AsLong(pDictEntry), vProperties);
- }
-
- pDictEntry = PyDict_GetItemString(WriteMessage->m_Object, "AssignedClientID");
-- if (pDictEntry && (pDictEntry != Py_None))
-+ if (pDictEntry && !pDictEntry.IsNone())
- {
- PyNewRef pStr = PyObject_Str(pDictEntry);
- vProperties.push_back(18);
-@@ -1874,7 +1888,7 @@ namespace Plugins {
- }
-
- pDictEntry = PyDict_GetItemString(WriteMessage->m_Object, "ReasonString");
-- if (pDictEntry && (pDictEntry != Py_None))
-+ if (pDictEntry && !pDictEntry.IsNone())
- {
- PyNewRef pStr = PyObject_Str(pDictEntry);
- vProperties.push_back(26);
-@@ -1882,7 +1896,7 @@ namespace Plugins {
- }
-
- pDictEntry = PyDict_GetItemString(WriteMessage->m_Object, "ResponseInformation");
-- if (pDictEntry && (pDictEntry != Py_None))
-+ if (pDictEntry && !pDictEntry.IsNone())
- {
- PyNewRef pStr = PyObject_Str(pDictEntry);
- vProperties.push_back(18);
-@@ -1904,7 +1918,7 @@ namespace Plugins {
- // If supplied then use it otherwise create one
- PyBorrowedRef pID = PyDict_GetItemString(WriteMessage->m_Object, "PacketIdentifier");
- long iPacketIdentifier = 0;
-- if (pID && PyLong_Check(pID))
-+ if (pID.IsLong())
- {
- iPacketIdentifier = PyLong_AsLong(pID);
- }
-@@ -1913,25 +1927,25 @@ namespace Plugins {
-
- // Payload is list of topics and QoS numbers
- PyBorrowedRef pTopicList = PyDict_GetItemString(WriteMessage->m_Object, "Topics");
-- if (!pTopicList || !PyList_Check(pTopicList))
-+ if (!pTopicList.IsList())
- {
- _log.Log(LOG_ERROR, "(%s) MQTT Subscribe: No 'Topics' list present, nothing to subscribe to. See Python Plugin wiki page for help.", __func__);
- return retVal;
- }
- for (Py_ssize_t i = 0; i < PyList_Size(pTopicList); i++)
- {
-- PyObject* pTopicDict = PyList_GetItem(pTopicList, i);
-- if (!pTopicDict || !PyDict_Check(pTopicDict))
-+ PyBorrowedRef pTopicDict = PyList_GetItem(pTopicList, i);
-+ if (!pTopicDict.IsDict())
- {
- _log.Log(LOG_ERROR, "(%s) MQTT Subscribe: Topics list entry is not a dictionary (Topic, QoS), nothing to subscribe to. See Python Plugin wiki page for help.", __func__);
- return retVal;
- }
- PyBorrowedRef pTopic = PyDict_GetItemString(pTopicDict, "Topic");
-- if (pTopic && PyUnicode_Check(pTopic))
-+ if (pTopic.IsString())
- {
- MQTTPushBackStringWLen(std::string(PyUnicode_AsUTF8(pTopic)), vPayload);
- PyBorrowedRef pQoS = PyDict_GetItemString(pTopicDict, "QoS");
-- if (pQoS && PyLong_Check(pQoS))
-+ if (pQoS.IsLong())
- {
- vPayload.push_back((byte)PyLong_AsLong(pQoS));
- }
-@@ -1949,7 +1963,7 @@ namespace Plugins {
- // Variable Header
- PyBorrowedRef pID = PyDict_GetItemString(WriteMessage->m_Object, "PacketIdentifier");
- long iPacketIdentifier = 0;
-- if (pID && PyLong_Check(pID))
-+ if (pID.IsLong())
- {
- iPacketIdentifier = PyLong_AsLong(pID);
- MQTTPushBackNumber((int)iPacketIdentifier, vVariableHeader);
-@@ -1961,7 +1975,7 @@ namespace Plugins {
- }
-
- PyBorrowedRef pDictEntry = PyDict_GetItemString(WriteMessage->m_Object, "QoS");
-- if (pDictEntry && PyLong_Check(pDictEntry))
-+ if (pDictEntry.IsLong())
- {
- vPayload.push_back((byte)PyLong_AsLong(pDictEntry));
- }
-@@ -1978,7 +1992,7 @@ namespace Plugins {
- // Variable Header
- PyBorrowedRef pID = PyDict_GetItemString(WriteMessage->m_Object, "PacketIdentifier");
- long iPacketIdentifier = 0;
-- if (pID && PyLong_Check(pID))
-+ if (pID.IsLong())
- {
- iPacketIdentifier = PyLong_AsLong(pID);
- }
-@@ -1987,15 +2001,15 @@ namespace Plugins {
-
- // Payload is a Python list of topics
- PyBorrowedRef pTopicList = PyDict_GetItemString(WriteMessage->m_Object, "Topics");
-- if (!pTopicList || !PyList_Check(pTopicList))
-+ if (!pTopicList.IsList())
- {
- _log.Log(LOG_ERROR, "(%s) MQTT Subscribe: No 'Topics' list present, nothing to unsubscribe from. See Python Plugin wiki page for help.", __func__);
- return retVal;
- }
- for (Py_ssize_t i = 0; i < PyList_Size(pTopicList); i++)
- {
-- PyObject* pTopic = PyList_GetItem(pTopicList, i);
-- if (pTopic && PyUnicode_Check(pTopic))
-+ PyBorrowedRef pTopic = PyList_GetItem(pTopicList, i);
-+ if (pTopic.IsString())
- {
- MQTTPushBackStringWLen(std::string(PyUnicode_AsUTF8(pTopic)), vPayload);
- }
-@@ -2009,7 +2023,7 @@ namespace Plugins {
-
- // Fixed Header
- PyBorrowedRef pDUP = PyDict_GetItemString(WriteMessage->m_Object, "Duplicate");
-- if (pDUP && PyLong_Check(pDUP))
-+ if (pDUP.IsLong())
- {
- long bDUP = PyLong_AsLong(pDUP);
- if (bDUP) bByte0 |= 0x08; // Set duplicate flag
-@@ -2017,14 +2031,14 @@ namespace Plugins {
-
- PyBorrowedRef pQoS = PyDict_GetItemString(WriteMessage->m_Object, "QoS");
- long iQoS = 0;
-- if (pQoS && PyLong_Check(pQoS))
-+ if (pQoS.IsLong())
- {
- iQoS = PyLong_AsLong(pQoS);
- bByte0 |= ((iQoS & 3) << 1); // Set QoS flag
- }
-
- PyBorrowedRef pRetain = PyDict_GetItemString(WriteMessage->m_Object, "Retain");
-- if (pRetain && PyLong_Check(pRetain))
-+ if (pRetain.IsLong())
- {
- long bRetain = PyLong_AsLong(pRetain);
- bByte0 |= (bRetain & 1); // Set retain flag
-@@ -2032,7 +2046,7 @@ namespace Plugins {
-
- // Variable Header
- PyBorrowedRef pTopic = PyDict_GetItemString(WriteMessage->m_Object, "Topic");
-- if (pTopic && PyUnicode_Check(pTopic))
-+ if (pTopic && pTopic.IsString())
- {
- MQTTPushBackStringWLen(std::string(PyUnicode_AsUTF8(pTopic)), vVariableHeader);
- }
-@@ -2046,7 +2060,7 @@ namespace Plugins {
- if (iQoS)
- {
- long iPacketIdentifier = 0;
-- if (pID && PyLong_Check(pID))
-+ if (pID.IsLong())
- {
- iPacketIdentifier = PyLong_AsLong(pID);
- }
-@@ -2062,20 +2076,22 @@ namespace Plugins {
- PyBorrowedRef pPayload = PyDict_GetItemString(WriteMessage->m_Object, "Payload");
- // Support both string and bytes
- //if (pPayload && PyByteArray_Check(pPayload)) // Gives linker error, why?
-- if (pPayload) {
-- _log.Debug(DEBUG_NORM, "(%s) MQTT Publish: payload %p (%s)", __func__, (PyObject*)pPayload, pPayload->ob_type->tp_name);
-+ if (pPayload)
-+ {
-+ PyNewRef pName = PyObject_GetAttrString((PyObject*)pPayload->ob_type, "__name__");
-+ _log.Debug(DEBUG_NORM, "(%s) MQTT Publish: payload %p (%s)", __func__, (PyObject*)pPayload, ((std::string)pName).c_str());
- }
-- if (pPayload && pPayload->ob_type->tp_name == std::string("bytearray"))
-+ if (pPayload.IsByteArray())
- {
- std::string sPayload = std::string(PyByteArray_AsString(pPayload), PyByteArray_Size(pPayload));
- MQTTPushBackString(sPayload, vPayload);
- }
-- else if (pPayload && PyUnicode_Check(pPayload))
-+ else if (pPayload.IsString())
- {
- std::string sPayload = std::string(PyUnicode_AsUTF8(pPayload));
- MQTTPushBackString(sPayload, vPayload);
- }
-- else if (pPayload && PyLong_Check(pPayload))
-+ else if (pPayload.IsLong())
- {
- MQTTPushBackLong(PyLong_AsLong(pPayload), vPayload);
- }
-@@ -2086,7 +2102,7 @@ namespace Plugins {
- // Variable Header
- PyBorrowedRef pID = PyDict_GetItemString(WriteMessage->m_Object, "PacketIdentifier");
- long iPacketIdentifier = 0;
-- if (pID && PyLong_Check(pID))
-+ if (pID.IsLong())
- {
- iPacketIdentifier = PyLong_AsLong(pID);
- MQTTPushBackNumber((int)iPacketIdentifier, vVariableHeader);
-@@ -2104,7 +2120,7 @@ namespace Plugins {
- // Variable Header
- PyBorrowedRef pID = PyDict_GetItemString(WriteMessage->m_Object, "PacketIdentifier");
- long iPacketIdentifier = 0;
-- if (pID && PyLong_Check(pID))
-+ if (pID.IsLong())
- {
- iPacketIdentifier = PyLong_AsLong(pID);
- MQTTPushBackNumber((int)iPacketIdentifier, vVariableHeader);
-@@ -2117,7 +2133,7 @@ namespace Plugins {
-
- // Connect Reason Code
- PyBorrowedRef pDictEntry = PyDict_GetItemString(WriteMessage->m_Object, "ReasonCode");
-- if (pDictEntry && PyLong_Check(pDictEntry))
-+ if (pDictEntry.IsLong())
- {
- vVariableHeader.push_back((byte)PyLong_AsLong(pDictEntry));
- }
-@@ -2381,7 +2397,7 @@ namespace Plugins {
- // Parameters need to be in a dictionary.
- // if a 'URL' key is found message is assumed to be HTTP otherwise WebSocket is assumed
- //
-- if (!WriteMessage->m_Object || !PyDict_Check(WriteMessage->m_Object))
-+ if (!PyBorrowedRef(WriteMessage->m_Object).IsDict())
- {
- _log.Log(LOG_ERROR, "(%s) Dictionary parameter expected.", __func__);
- }
-@@ -2444,7 +2460,7 @@ namespace Plugins {
-
- if (pOperation)
- {
-- if (!PyUnicode_Check(pOperation))
-+ if (!pOperation.IsString())
- {
- _log.Log(LOG_ERROR, "(%s) Expected dictionary 'Operation' key to have a string value.", __func__);
- return retVal;
-@@ -2466,36 +2482,33 @@ namespace Plugins {
- }
-
- // If there is no specific OpCode then set it from the payload datatype
-- if (pPayload)
-+ if (pPayload.IsString())
- {
-- if (PyUnicode_Check(pPayload))
-- {
-- lPayloadLength = PyUnicode_GetLength(pPayload);
-- if (!iOpCode)
-- iOpCode = 0x01; // Text message
-- }
-- else if (PyBytes_Check(pPayload))
-- {
-- lPayloadLength = PyBytes_Size(pPayload);
-- if (!iOpCode)
-- iOpCode = 0x02; // Binary message
-- }
-- else if (pPayload->ob_type->tp_name == std::string("bytearray"))
-- {
-- lPayloadLength = PyByteArray_Size(pPayload);
-- if (!iOpCode)
-- iOpCode = 0x02; // Binary message
-- }
-+ lPayloadLength = PyUnicode_GetLength(pPayload);
-+ if (!iOpCode)
-+ iOpCode = 0x01; // Text message
-+ }
-+ else if (pPayload.IsBytes())
-+ {
-+ lPayloadLength = PyBytes_Size(pPayload);
-+ if (!iOpCode)
-+ iOpCode = 0x02; // Binary message
-+ }
-+ else if (pPayload.IsByteArray())
-+ {
-+ lPayloadLength = PyByteArray_Size(pPayload);
-+ if (!iOpCode)
-+ iOpCode = 0x02; // Binary message
- }
-
- if (pMask)
- {
-- if (PyLong_Check(pMask))
-+ if (pMask.IsLong())
- {
- lMaskingKey = PyLong_AsLong(pMask);
- bMaskBit = 0x80; // Set mask bit in header
- }
-- else if (PyUnicode_Check(pMask))
-+ else if (pMask.IsString())
- {
- std::string sMask = PyUnicode_AsUTF8(pMask);
- lMaskingKey = atoi(sMask.c_str());
-@@ -2503,7 +2516,7 @@ namespace Plugins {
- }
- else
- {
-- _log.Log(LOG_ERROR, "(%s) Invalid mask, expected number (integer or string).", __func__);
-+ _log.Log(LOG_ERROR, "(%s) Invalid mask, expected number (integer or string) but got '%s'.", __func__, pMask.Type().c_str());
- return retVal;
- }
- }
-@@ -2534,31 +2547,28 @@ namespace Plugins {
- retVal.push_back(lMaskingKey & 0xFF); // Encode mask
- }
-
-- if (pPayload)
-+ if (pPayload.IsString())
- {
-- if (PyUnicode_Check(pPayload))
-+ std::string sPayload = PyUnicode_AsUTF8(pPayload);
-+ for (int i = 0; i < lPayloadLength; i++)
- {
-- std::string sPayload = PyUnicode_AsUTF8(pPayload);
-- for (int i = 0; i < lPayloadLength; i++)
-- {
-- retVal.push_back(sPayload[i] ^ pbMask[i % 4]);
-- }
-+ retVal.push_back(sPayload[i] ^ pbMask[i % 4]);
- }
-- else if (PyBytes_Check(pPayload))
-+ }
-+ else if (pPayload.IsBytes())
-+ {
-+ byte *pByte = (byte *)PyBytes_AsString(pPayload);
-+ for (int i = 0; i < lPayloadLength; i++)
- {
-- byte *pByte = (byte *)PyBytes_AsString(pPayload);
-- for (int i = 0; i < lPayloadLength; i++)
-- {
-- retVal.push_back(pByte[i] ^ pbMask[i % 4]);
-- }
-+ retVal.push_back(pByte[i] ^ pbMask[i % 4]);
- }
-- else if (pPayload->ob_type->tp_name == std::string("bytearray"))
-+ }
-+ else if (pPayload.IsByteArray())
-+ {
-+ byte *pByte = (byte *)PyByteArray_AsString(pPayload);
-+ for (int i = 0; i < lPayloadLength; i++)
- {
-- byte *pByte = (byte *)PyByteArray_AsString(pPayload);
-- for (int i = 0; i < lPayloadLength; i++)
-- {
-- retVal.push_back(pByte[i] ^ pbMask[i % 4]);
-- }
-+ retVal.push_back(pByte[i] ^ pbMask[i % 4]);
- }
- }
- }
---- a/hardware/plugins/PluginTransports.cpp
-+++ b/hardware/plugins/PluginTransports.cpp
-@@ -15,6 +15,8 @@
-
- namespace Plugins {
-
-+ extern PyTypeObject* CConnectionType;
-+
- void CPluginTransport::configureTimeout()
- {
- if (m_pConnection->Timeout)
-@@ -198,8 +200,6 @@ namespace Plugins {
- {
- try
- {
-- PyType_Ready(&CConnectionType);
--
- if (!m_Socket)
- {
- if (!m_Acceptor)
-@@ -239,8 +239,21 @@ namespace Plugins {
- std::string sAddress = remote_ep.address().to_string();
- std::string sPort = std::to_string(remote_ep.port());
-
-- CConnection *pConnection
-- = (CConnection *)CConnection_new(&CConnectionType, (PyObject *)nullptr, (PyObject *)nullptr);
-+ PyNewRef nrArgList = Py_BuildValue("(sssss)",
-+ std::string(sAddress+":"+sPort).c_str(),
-+ PyUnicode_AsUTF8(((CConnection*)m_pConnection)->Transport),
-+ PyUnicode_AsUTF8(((CConnection*)m_pConnection)->Protocol),
-+ sAddress.c_str(),
-+ sPort.c_str());
-+ if (!nrArgList)
-+ {
-+ pPlugin->Log(LOG_ERROR, "Building connection argument list failed for TCP %s:%s.", sAddress.c_str(), sPort.c_str());
-+ }
-+ CConnection* pConnection = (CConnection*)PyObject_CallObject((PyObject*)CConnectionType, nrArgList);
-+ if (!pConnection)
-+ {
-+ pPlugin->Log(LOG_ERROR, "Connection object creation failed for TCP %s:%s.", sAddress.c_str(), sPort.c_str());
-+ }
- CPluginTransportTCP* pTcpTransport = new CPluginTransportTCP(m_HwdID, pConnection, sAddress, sPort);
- Py_DECREF(pConnection);
-
-@@ -252,20 +265,10 @@ namespace Plugins {
-
- // Configure Python Connection object
- pConnection->pTransport = pTcpTransport;
-- Py_XDECREF(pConnection->Name);
-- pConnection->Name = PyUnicode_FromString(std::string(sAddress+":"+sPort).c_str());
-- Py_XDECREF(pConnection->Address);
-- pConnection->Address = PyUnicode_FromString(sAddress.c_str());
-- Py_XDECREF(pConnection->Port);
-- pConnection->Port = PyUnicode_FromString(sPort.c_str());
-
- Py_XDECREF(pConnection->Parent);
- pConnection->Parent = (PyObject*)m_pConnection;
- Py_INCREF(m_pConnection);
-- pConnection->Transport = ((CConnection*)m_pConnection)->Transport;
-- Py_INCREF(pConnection->Transport);
-- pConnection->Protocol = ((CConnection*)m_pConnection)->Protocol;
-- Py_INCREF(pConnection->Protocol);
- pConnection->Target = ((CConnection *)m_pConnection)->Target;
- if (pConnection->Target)
- Py_INCREF(pConnection->Target);
-@@ -626,8 +629,6 @@ namespace Plugins {
- {
- try
- {
-- PyType_Ready(&CConnectionType);
--
- if (!m_Socket)
- {
- boost::system::error_code ec;
-@@ -680,21 +681,22 @@ namespace Plugins {
- std::string sAddress = m_remote_endpoint.address().to_string();
- std::string sPort = std::to_string(m_remote_endpoint.port());
-
-- CConnection *pConnection
-- = (CConnection *)CConnection_new(&CConnectionType, (PyObject *)nullptr, (PyObject *)nullptr);
-+ PyNewRef nrArgList = Py_BuildValue("(sssss)",
-+ PyUnicode_AsUTF8(((CConnection*)m_pConnection)->Name),
-+ PyUnicode_AsUTF8(((CConnection*)m_pConnection)->Transport),
-+ PyUnicode_AsUTF8(((CConnection*)m_pConnection)->Protocol),
-+ sAddress.c_str(),
-+ sPort.c_str());
-+ if (!nrArgList)
-+ {
-+ pPlugin->Log(LOG_ERROR, "Building connection argument list failed for UDP %s:%s.", sAddress.c_str(), sPort.c_str());
-+ }
-+ CConnection* pConnection = (CConnection*)PyObject_CallObject((PyObject*)CConnectionType, nrArgList);
-+ if (!pConnection)
-+ {
-+ pPlugin->Log(LOG_ERROR, "Connection object creation failed for UDP %s:%s.", sAddress.c_str(), sPort.c_str());
-+ }
-
-- // Configure temporary Python Connection object
-- Py_XDECREF(pConnection->Name);
-- pConnection->Name = ((CConnection*)m_pConnection)->Name;
-- Py_INCREF(pConnection->Name);
-- Py_XDECREF(pConnection->Address);
-- pConnection->Address = PyUnicode_FromString(sAddress.c_str());
-- Py_XDECREF(pConnection->Port);
-- pConnection->Port = PyUnicode_FromString(sPort.c_str());
-- pConnection->Transport = ((CConnection*)m_pConnection)->Transport;
-- Py_INCREF(pConnection->Transport);
-- pConnection->Protocol = ((CConnection*)m_pConnection)->Protocol;
-- Py_INCREF(pConnection->Protocol);
- pConnection->Target = ((CConnection *)m_pConnection)->Target;
- if (pConnection->Target)
- Py_INCREF(pConnection->Target);
---- a/hardware/plugins/Plugins.cpp
-+++ b/hardware/plugins/Plugins.cpp
-@@ -5,6 +5,8 @@
- //
- #ifdef ENABLE_PYTHON
-
-+#include "../../main/Helper.h"
-+
- #include "Plugins.h"
- #include "PluginMessages.h"
- #include "PluginProtocols.h"
-@@ -41,44 +43,22 @@ extern MainWorker m_mainworker;
-
- namespace Plugins
- {
-- std::mutex AccessPython::PythonMutex;
-- volatile bool AccessPython::m_bHasThreadState = false;
-+ extern PyTypeObject* CDeviceType;
-+ extern PyTypeObject* CConnectionType;
-+ extern PyTypeObject* CImageType;
-
-- AccessPython::AccessPython(CPlugin* pPlugin, const char* sWhat) : m_Python(NULL)
-+ AccessPython::AccessPython(CPlugin* pPlugin, const char* sWhat)
- {
- m_pPlugin = pPlugin;
- m_Text = sWhat;
-
-- m_Lock = new std::unique_lock<std::mutex>(PythonMutex, std::defer_lock);
-- if (!m_Lock->try_lock())
-- {
-- if (m_pPlugin)
-- {
-- if (m_pPlugin->m_bDebug & PDM_LOCKING)
-- {
-- _log.Log(LOG_NORM, "(%s) Requesting lock for '%s', waiting...", m_pPlugin->m_Name.c_str(), m_Text);
-- }
-- }
-- else _log.Log(LOG_NORM, "Python lock requested for '%s' in use, will wait.", m_Text);
-- m_Lock->lock();
-- }
--
-- if (pPlugin)
-+ if (m_pPlugin)
- {
-- if (pPlugin->m_bDebug & PDM_LOCKING)
-- {
-- _log.Log(LOG_NORM, "(%s) Acquiring lock for '%s'", pPlugin->m_Name.c_str(), m_Text);
-- }
-- m_Python = pPlugin->PythonInterpreter();
-- if (m_Python)
-+ if (m_pPlugin->m_bDebug & PDM_LOCKING)
- {
-- PyEval_RestoreThread(m_Python);
-- m_bHasThreadState = true;
-- }
-- else
-- {
-- _log.Log(LOG_ERROR, "Attempt to aquire the GIL with NULL Interpreter details.");
-+ m_pPlugin->Log(LOG_NORM, "Acquiring GIL for '%s'", m_Text.c_str());
- }
-+ m_pPlugin->RestoreThread();
- }
- else
- {
-@@ -88,215 +68,39 @@ namespace Plugins
-
- AccessPython::~AccessPython()
- {
-- if (m_Python && m_pPlugin)
-+ if (m_pPlugin)
- {
- if (PyErr_Occurred())
- {
-- _log.Log(LOG_NORM, "(%s) Python error was set during unlock for '%s'", m_pPlugin->m_Name.c_str(), m_Text);
-+ m_pPlugin->Log(LOG_NORM, "Python error was set during unlock for '%s'", m_Text.c_str());
- m_pPlugin->LogPythonException();
- PyErr_Clear();
- }
--
-- m_bHasThreadState = false;
-- if (m_pPlugin->PythonInterpreter() && !PyEval_SaveThread())
-- {
-- _log.Log(LOG_ERROR, "(%s) Python Save state returned NULL value for '%s'", m_pPlugin->m_Name.c_str(), m_Text);
-- }
-- }
-- if (m_Lock)
-- {
-- if (m_pPlugin && m_pPlugin->m_bDebug & PDM_LOCKING)
-- {
-- _log.Log(LOG_NORM, "(%s) Releasing lock for '%s'", m_pPlugin->m_Name.c_str(), m_Text);
-- }
-- delete m_Lock;
-- }
-- }
--
-- void LogPythonException(CPlugin *pPlugin, const std::string &sHandler)
-- {
-- PyTracebackObject *pTraceback;
-- PyNewRef pExcept;
-- PyNewRef pValue;
-- PyTypeObject *TypeName;
-- PyBytesObject *pErrBytes = nullptr;
-- const char *pTypeText = nullptr;
-- std::string Name = "Unknown";
--
-- if (pPlugin)
-- Name = pPlugin->m_Name;
--
-- PyErr_Fetch(&pExcept, &pValue, (PyObject **)&pTraceback);
--
-- if (pExcept)
-- {
-- TypeName = (PyTypeObject *)pExcept;
-- pTypeText = TypeName->tp_name;
-- }
-- if (pValue)
-- {
-- pErrBytes = (PyBytesObject *)PyUnicode_AsASCIIString(pValue);
-- }
-- if (pTypeText && pErrBytes)
-- {
-- if (pPlugin)
-- pPlugin->Log(LOG_ERROR, "'%s' failed '%s':'%s'.", sHandler.c_str(), pTypeText, pErrBytes->ob_sval);
-- else
-- _log.Log(LOG_ERROR, "'%s' failed '%s':'%s'.", sHandler.c_str(), pTypeText, pErrBytes->ob_sval);
-- }
-- if (pTypeText && !pErrBytes)
-- {
-- if (pPlugin)
-- pPlugin->Log(LOG_ERROR, "'%s' failed '%s'.", sHandler.c_str(), pTypeText);
-- else
-- _log.Log(LOG_ERROR, "'%s' failed '%s'.", sHandler.c_str(), pTypeText);
-- }
-- if (!pTypeText && pErrBytes)
-- {
-- if (pPlugin)
-- pPlugin->Log(LOG_ERROR, "'%s' failed '%s'.", sHandler.c_str(), pErrBytes->ob_sval);
-- else
-- _log.Log(LOG_ERROR, "'%s' failed '%s'.", sHandler.c_str(), pErrBytes->ob_sval);
-- }
-- if (!pTypeText && !pErrBytes)
-- {
-- if (pPlugin)
-- pPlugin->Log(LOG_ERROR, "'%s' failed, unable to determine error.", sHandler.c_str());
-- else
-- _log.Log(LOG_ERROR, "'%s' failed, unable to determine error.", sHandler.c_str());
-- }
-- if (pErrBytes)
-- Py_XDECREF(pErrBytes);
--
-- // Log a stack trace if there is one
-- if (pPlugin && pTraceback)
-- pPlugin->LogTraceback(pTraceback);
--
-- if (!pExcept && !pValue && !pTraceback)
-- {
-- if (pPlugin)
-- pPlugin->Log(LOG_ERROR, "Call to message handler '%s' failed, unable to decode exception.", sHandler.c_str());
-- else
-- _log.Log(LOG_ERROR, "Call to message handler '%s' failed, unable to decode exception.", sHandler.c_str());
-- }
--
-- if (pTraceback)
-- Py_XDECREF(pTraceback);
-- }
--
-- int PyDomoticz_ProfileFunc(PyObject *self, PyFrameObject *frame, int what, PyObject *arg)
-- {
-- module_state *pModState = CPlugin::FindModule();
-- if (!pModState)
-- {
-- return 0;
-- }
-- else if (!pModState->pPlugin)
-- {
-- _log.Log(LOG_ERROR, "CPlugin:%s, illegal operation, Plugin has not started yet.", __func__);
-- }
-- else
-- {
-- int lineno = PyFrame_GetLineNumber(frame);
-- std::string sFuncName = "Unknown";
-- PyCodeObject *pCode = frame->f_code;
-- if (pCode && pCode->co_filename)
-- {
-- sFuncName = (std::string)PyBorrowedRef(pCode->co_filename);
-- }
-- if (pCode && pCode->co_name)
-- {
-- if (!sFuncName.empty())
-- sFuncName += "\\";
-- sFuncName += (std::string)PyBorrowedRef(pCode->co_name);
-- }
--
-- switch (what)
-- {
-- case PyTrace_CALL:
-- pModState->pPlugin->Log(LOG_NORM, "Calling function at line %d in '%s'", lineno, sFuncName.c_str());
-- break;
-- case PyTrace_RETURN:
-- pModState->pPlugin->Log(LOG_NORM, "Returning from line %d in '%s'", lineno, sFuncName.c_str());
-- break;
-- case PyTrace_EXCEPTION:
-- pModState->pPlugin->Log(LOG_NORM, "Exception at line %d in '%s'", lineno, sFuncName.c_str());
-- break;
-- }
-- }
--
-- return 0;
-- }
--
-- int PyDomoticz_TraceFunc(PyObject *self, PyFrameObject *frame, int what, PyObject *arg)
-- {
-- module_state *pModState = CPlugin::FindModule();
-- if (!pModState)
-- {
-- return 0;
-- }
-- else if (!pModState->pPlugin)
-- {
-- _log.Log(LOG_ERROR, "CPlugin:%s, illegal operation, Plugin has not started yet.", __func__);
-- }
-- else
-- {
-- int lineno = PyFrame_GetLineNumber(frame);
-- std::string sFuncName = "Unknown";
-- PyCodeObject *pCode = frame->f_code;
-- if (pCode && pCode->co_filename)
-- {
-- sFuncName = (std::string)PyBorrowedRef(pCode->co_filename);
-- }
-- if (pCode && pCode->co_name)
-- {
-- if (!sFuncName.empty())
-- sFuncName += "\\";
-- sFuncName += (std::string)PyBorrowedRef(pCode->co_name);
-- }
--
-- switch (what)
-- {
-- case PyTrace_CALL:
-- pModState->pPlugin->Log(LOG_NORM, "Calling function at line %d in '%s'", lineno, sFuncName.c_str());
-- break;
-- case PyTrace_LINE:
-- pModState->pPlugin->Log(LOG_NORM, "Executing line %d in '%s'", lineno, sFuncName.c_str());
-- break;
-- case PyTrace_EXCEPTION:
-- pModState->pPlugin->Log(LOG_NORM, "Exception at line %d in '%s'", lineno, sFuncName.c_str());
-- break;
-- }
-+ m_pPlugin->ReleaseThread();
- }
--
-- return 0;
- }
-
- static PyObject *PyDomoticz_Debug(PyObject *self, PyObject *args)
- {
-- module_state *pModState = CPlugin::FindModule();
-- if (!pModState)
-+ CPlugin* pPlugin = CPlugin::FindPlugin();
-+ if (!pPlugin)
- {
-- Py_RETURN_NONE;
-- }
-- else if (!pModState->pPlugin)
-- {
-- _log.Log(LOG_ERROR, "CPlugin:%s, illegal operation, Plugin has not started yet.", __func__);
-+ _log.Log(LOG_ERROR, "%s, illegal operation, Plugin has not started yet.", __func__);
- }
- else
- {
-- if (pModState->pPlugin->m_bDebug & PDM_PYTHON)
-+ if (pPlugin->m_bDebug & PDM_PYTHON)
- {
- char *msg;
- if (!PyArg_ParseTuple(args, "s", &msg))
- {
- // TODO: Dump data to aid debugging
-- pModState->pPlugin->Log(LOG_ERROR, "PyDomoticz_Debug failed to parse parameters: string expected.");
-- LogPythonException(pModState->pPlugin, std::string(__func__));
-+ pPlugin->Log(LOG_ERROR, "%s failed to parse parameters: string expected.", __func__);
-+ pPlugin->LogPythonException(std::string(__func__));
- }
- else
- {
-- pModState->pPlugin->Log(LOG_NORM, (std::string)msg);
-+ pPlugin->Log(LOG_NORM, (std::string)msg);
- }
- }
- }
-@@ -306,12 +110,8 @@ namespace Plugins
-
- static PyObject *PyDomoticz_Log(PyObject *self, PyObject *args)
- {
-- module_state *pModState = CPlugin::FindModule();
-- if (!pModState)
-- {
-- Py_RETURN_NONE;
-- }
-- else if (!pModState->pPlugin)
-+ CPlugin* pPlugin = CPlugin::FindPlugin();
-+ if (!pPlugin)
- {
- _log.Log(LOG_ERROR, "CPlugin:%s, illegal operation, Plugin has not started yet.", __func__);
- }
-@@ -320,12 +120,12 @@ namespace Plugins
- char *msg;
- if (!PyArg_ParseTuple(args, "s", &msg))
- {
-- pModState->pPlugin->Log(LOG_ERROR, "PyDomoticz_Log failed to parse parameters: string expected.");
-- LogPythonException(pModState->pPlugin, std::string(__func__));
-+ pPlugin->Log(LOG_ERROR, "%s failed to parse parameters: string expected.", __func__);
-+ pPlugin->LogPythonException(std::string(__func__));
- }
- else
- {
-- pModState->pPlugin->Log(LOG_NORM, (std::string)msg);
-+ pPlugin->Log(LOG_NORM, (std::string)msg);
- }
- }
-
-@@ -334,26 +134,22 @@ namespace Plugins
-
- static PyObject *PyDomoticz_Status(PyObject *self, PyObject *args)
- {
-- module_state *pModState = CPlugin::FindModule();
-- if (!pModState)
-+ CPlugin* pPlugin = CPlugin::FindPlugin();
-+ if (!pPlugin)
- {
-- Py_RETURN_NONE;
-- }
-- else if (!pModState->pPlugin)
-- {
-- _log.Log(LOG_ERROR, "CPlugin:%s, illegal operation, Plugin has not started yet.", __func__);
-+ _log.Log(LOG_ERROR, "%s, illegal operation, Plugin has not started yet.", __func__);
- }
- else
- {
- char *msg;
- if (!PyArg_ParseTuple(args, "s", &msg))
- {
-- pModState->pPlugin->Log(LOG_ERROR, "%s failed to parse parameters: string expected.", std::string(__func__).c_str());
-- LogPythonException(pModState->pPlugin, std::string(__func__));
-+ pPlugin->Log(LOG_ERROR, "%s failed to parse parameters: string expected.", __func__);
-+ pPlugin->LogPythonException(std::string(__func__));
- }
- else
- {
-- pModState->pPlugin->Log(LOG_STATUS, (std::string)msg);
-+ pPlugin->Log(LOG_STATUS, (std::string)msg);
- }
- }
-
-@@ -362,14 +158,10 @@ namespace Plugins
-
- static PyObject *PyDomoticz_Error(PyObject *self, PyObject *args)
- {
-- module_state *pModState = CPlugin::FindModule();
-- if (!pModState)
-- {
-- Py_RETURN_NONE;
-- }
-- else if (!pModState->pPlugin)
-+ CPlugin* pPlugin = CPlugin::FindPlugin();
-+ if (!pPlugin)
- {
-- _log.Log(LOG_ERROR, "CPlugin:%s, illegal operation, Plugin has not started yet.", __func__);
-+ _log.Log(LOG_ERROR, "%s, illegal operation, Plugin has not started yet.", __func__);
- }
- else
- {
-@@ -377,12 +169,12 @@ namespace Plugins
- if ((PyTuple_Size(args) != 1) || !PyArg_ParseTuple(args, "s", &msg))
- {
- // TODO: Dump data to aid debugging
-- pModState->pPlugin->Log(LOG_ERROR, "PyDomoticz_Error failed to parse parameters: string expected.");
-- LogPythonException(pModState->pPlugin, std::string(__func__));
-+ pPlugin->Log(LOG_ERROR, "%s failed to parse parameters: string expected.", __func__);
-+ pPlugin->LogPythonException(std::string(__func__));
- }
- else
- {
-- pModState->pPlugin->Log(LOG_ERROR, (std::string)msg);
-+ pPlugin->Log(LOG_ERROR, (std::string)msg);
- }
- }
-
-@@ -406,7 +198,7 @@ namespace Plugins
- if (!PyArg_ParseTuple(args, "i", &type))
- {
- pModState->pPlugin->Log(LOG_ERROR, "Failed to parse parameters, integer expected.");
-- LogPythonException(pModState->pPlugin, std::string(__func__));
-+ pModState->pPlugin->LogPythonException(std::string(__func__));
- }
- else
- {
-@@ -440,12 +232,12 @@ namespace Plugins
- else
- {
- iPollinterval = pModState->pPlugin->PollInterval(0);
-- if (PyTuple_Check(args) && PyTuple_Size(args))
-+ if (PyBorrowedRef(args).IsTuple() && PyTuple_Size(args))
- {
- if (!PyArg_ParseTuple(args, "i", &iPollinterval))
- {
- pModState->pPlugin->Log(LOG_ERROR, "failed to parse parameters, integer expected.");
-- LogPythonException(pModState->pPlugin, std::string(__func__));
-+ pModState->pPlugin->LogPythonException(std::string(__func__));
- }
- else
- {
-@@ -475,7 +267,7 @@ namespace Plugins
- if (!PyArg_ParseTuple(args, "s", &szNotifier))
- {
- pModState->pPlugin->Log(LOG_ERROR, "Failed to parse parameters, Notifier Name expected.");
-- LogPythonException(pModState->pPlugin, std::string(__func__));
-+ pModState->pPlugin->LogPythonException(std::string(__func__));
- }
- else
- {
-@@ -508,28 +300,7 @@ namespace Plugins
- }
- else
- {
-- int bTrace = 0;
-- if (!PyArg_ParseTuple(args, "p", &bTrace))
-- {
-- pModState->pPlugin->Log(LOG_ERROR, "Failed to parse parameter, True/False expected.");
-- LogPythonException(pModState->pPlugin, std::string(__func__));
-- }
-- else
-- {
-- pModState->pPlugin->m_bTracing = (bool)bTrace;
-- pModState->pPlugin->Log(LOG_NORM, "Low level Python tracing %s.", (pModState->pPlugin->m_bTracing ? "ENABLED" : "DISABLED"));
--
-- if (pModState->pPlugin->m_bTracing)
-- {
-- PyEval_SetProfile(PyDomoticz_ProfileFunc, self);
-- PyEval_SetTrace(PyDomoticz_TraceFunc, self);
-- }
-- else
-- {
-- PyEval_SetProfile(nullptr, nullptr);
-- PyEval_SetTrace(nullptr, nullptr);
-- }
-- }
-+ pModState->pPlugin->Log(LOG_ERROR, "CPlugin:%s, Low level trace functions have been removed.", __func__);
- }
-
- Py_RETURN_NONE;
-@@ -554,7 +325,7 @@ namespace Plugins
- if (PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, &pNewConfig))
- {
- // Python object supplied if it is not a dictionary
-- if (!PyDict_Check(pNewConfig))
-+ if (!PyBorrowedRef(pNewConfig).IsDict())
- {
- pModState->pPlugin->Log(LOG_ERROR, "CPlugin:%s, Function expects no parameter or a Dictionary.", __func__);
- Py_RETURN_NONE;
-@@ -603,46 +374,26 @@ namespace Plugins
- {
- if (pDeviceClass)
- {
-- PyTypeObject *pBaseClass = pDeviceClass->tp_base;
-- while (pBaseClass)
-+ if (!PyType_IsSubtype(pDeviceClass, pModState->pDeviceClass))
- {
-- if (pBaseClass->tp_name == pModState->pDeviceClass->tp_name)
-- {
-- //_log.Log((_eLogLevel)LOG_NORM, "Class '%s' registered to override '%s'.", pDeviceClass->tp_name, pModState->pDeviceClass->tp_name);
-- pModState->pDeviceClass = pDeviceClass;
-- break;
-- }
-- pBaseClass = pBaseClass->tp_base;
-+ pModState->pPlugin->Log(LOG_ERROR, "Device class registration failed, Supplied class is not derived from 'DomoticzEx.Device'");
- }
-- if (pDeviceClass->tp_name != pModState->pDeviceClass->tp_name)
-+ else
- {
-- pModState->pPlugin->Log(LOG_ERROR, "Class '%s' registration failed, Device is not derived from '%s'", pDeviceClass->tp_name, pModState->pDeviceClass->tp_name);
-+ pModState->pDeviceClass = pDeviceClass;
-+ PyType_Ready(pModState->pDeviceClass);
- }
- }
- if (pUnitClass)
- {
-- if (pModState->pUnitClass)
-+ if (!PyType_IsSubtype(pUnitClass, pModState->pUnitClass))
- {
-- PyTypeObject *pBaseClass = pUnitClass->tp_base;
-- while (pBaseClass)
-- {
-- if (pBaseClass->tp_name == pModState->pUnitClass->tp_name)
-- {
-- //_log.Log((_eLogLevel)LOG_NORM, "Class '%s' registered to override '%s'.", pDeviceClass->tp_name, pModState->pUnitClass->tp_name);
-- pModState->pUnitClass = pUnitClass;
-- break;
-- }
-- pBaseClass = pBaseClass->tp_base;
-- }
-- if (pUnitClass->tp_name != pModState->pUnitClass->tp_name)
-- {
-- pModState->pPlugin->Log(LOG_ERROR, "Class '%s' registration failed, Unit is not derived from '%s'", pUnitClass->tp_name,
-- pModState->pDeviceClass->tp_name);
-- }
-+ pModState->pPlugin->Log(LOG_ERROR, "Unit class registration failed, Supplied class is not derived from 'DomoticzEx.Unit'");
- }
- else
- {
-- pModState->pPlugin->Log(LOG_ERROR, "Class '%s' registration failed, imported Domoticz module does not support Unit objects", pUnitClass->tp_name);
-+ pModState->pUnitClass = pUnitClass;
-+ PyType_Ready(pModState->pUnitClass);
- }
- }
- }
-@@ -669,12 +420,12 @@ namespace Plugins
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O", kwlist, &pTarget))
- {
- pModState->pPlugin->Log(LOG_ERROR, "%s failed to parse parameters: Object expected (Optional).", __func__);
-- LogPythonException(pModState->pPlugin, std::string(__func__));
-+ pModState->pPlugin->LogPythonException(std::string(__func__));
- }
- else
- {
- PyNewRef pLocals = PyObject_Dir(pModState->lastCallback);
-- if (PyList_Check(pLocals)) // && PyIter_Check(pLocals)) // Check fails but iteration works??!?
-+ if (pLocals.IsList()) // && PyIter_Check(pLocals)) // Check fails but iteration works??!?
- {
- pModState->pPlugin->Log(LOG_NORM, "Context dump:");
- PyNewRef pIter = PyObject_GetIter(pLocals);
-@@ -702,7 +453,7 @@ namespace Plugins
- }
- }
- PyBorrowedRef pLocalVars = PyEval_GetLocals();
-- if (PyDict_Check(pLocalVars))
-+ if (pLocalVars.IsDict())
- {
- pModState->pPlugin->Log(LOG_NORM, "Locals dump:");
- PyBorrowedRef key;
-@@ -717,7 +468,7 @@ namespace Plugins
- }
- }
- PyBorrowedRef pGlobalVars = PyEval_GetGlobals();
-- if (PyDict_Check(pGlobalVars))
-+ if (pGlobalVars.IsDict())
- {
- pModState->pPlugin->Log(LOG_NORM, "Globals dump:");
- PyBorrowedRef key;
-@@ -753,6 +504,30 @@ namespace Plugins
- { "Dump", (PyCFunction)PyDomoticz_Dump, METH_VARARGS | METH_KEYWORDS, "Dump string values of an object or all locals to the log." },
- { nullptr, nullptr, 0, nullptr } };
-
-+ PyType_Slot ConnectionSlots[] = {
-+ { Py_tp_doc, (void*)"Domoticz Connection" },
-+ { Py_tp_new, (void*)CConnection_new },
-+ { Py_tp_init, (void*)CConnection_init },
-+ { Py_tp_dealloc, (void*)CConnection_dealloc },
-+ { Py_tp_members, CConnection_members },
-+ { Py_tp_methods, CConnection_methods },
-+ { Py_tp_str, (void*)CConnection_str },
-+ { 0 },
-+ };
-+ PyType_Spec ConnectionSpec = { "Domoticz.Connection", sizeof(CConnection), 0, Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HEAPTYPE, ConnectionSlots };
-+
-+ PyType_Slot ImageSlots[] = {
-+ { Py_tp_doc, (void*)"Domoticz Image" },
-+ { Py_tp_new, (void*)CImage_new },
-+ { Py_tp_init, (void*)CImage_init },
-+ { Py_tp_dealloc, (void*)CImage_dealloc },
-+ { Py_tp_members, CImage_members },
-+ { Py_tp_methods, CImage_methods },
-+ { Py_tp_str, (void*)CImage_str },
-+ { 0 },
-+ };
-+ PyType_Spec ImageSpec = { "Domoticz.Image", sizeof(CImage), 0, Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HEAPTYPE, ImageSlots };
-+
- static int DomoticzTraverse(PyObject *m, visitproc visit, void *arg)
- {
- Py_VISIT(GETSTATE(m)->error);
-@@ -769,37 +544,46 @@ namespace Plugins
-
- PyMODINIT_FUNC PyInit_Domoticz(void)
- {
--
- // This is called during the import of the plugin module
- // triggered by the "import Domoticz" statement
- PyObject *pModule = PyModule_Create2(&DomoticzModuleDef, PYTHON_API_VERSION);
- module_state *pModState = ((struct module_state *)PyModule_GetState(pModule));
-
-- if (PyType_Ready(&CDeviceType) < 0)
-+ if (!CDeviceType)
- {
-- _log.Log(LOG_ERROR, "%s, Device Type not ready.", __func__);
-- return pModule;
-+ PyType_Slot DeviceSlots[] = {
-+ { Py_tp_doc, (void*)"Domoticz Device" },
-+ { Py_tp_new, (void*)CDevice_new },
-+ { Py_tp_init, (void*)CDevice_init },
-+ { Py_tp_dealloc, (void*)CDevice_dealloc },
-+ { Py_tp_members, CDevice_members },
-+ { Py_tp_methods, CDevice_methods },
-+ { Py_tp_str, (void*)CDevice_str },
-+ { 0 },
-+ };
-+ PyType_Spec DeviceSpec = { "Domoticz.Device", sizeof(CDevice), 0,
-+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HEAPTYPE, DeviceSlots };
-+
-+ CDeviceType = (PyTypeObject*)PyType_FromSpec(&DeviceSpec);
-+ PyType_Ready(CDeviceType);
- }
-- Py_INCREF((PyObject *)&CDeviceType);
-- PyModule_AddObject(pModule, "Device", (PyObject *)&CDeviceType);
-- pModState->pDeviceClass = &CDeviceType;
-+ pModState->pDeviceClass = CDeviceType;
- pModState->pUnitClass = nullptr;
-+ PyModule_AddObject(pModule, "Device", (PyObject*)CDeviceType);
-
-- if (PyType_Ready(&CConnectionType) < 0)
-+ if (!CConnectionType)
- {
-- _log.Log(LOG_ERROR, "%s, Connection Type not ready.", __func__);
-- return pModule;
-+ CConnectionType = (PyTypeObject*)PyType_FromSpec(&ConnectionSpec);
-+ PyType_Ready(CConnectionType);
- }
-- Py_INCREF((PyObject *)&CConnectionType);
-- PyModule_AddObject(pModule, "Connection", (PyObject *)&CConnectionType);
-+ PyModule_AddObject(pModule, "Connection", (PyObject*)CConnectionType);
-
-- if (PyType_Ready(&CImageType) < 0)
-+ if (!CImageType)
- {
-- _log.Log(LOG_ERROR, "%s, Image Type not ready.", __func__);
-- return pModule;
-+ CImageType = (PyTypeObject*)PyType_FromSpec(&ImageSpec);
-+ PyType_Ready(CImageType);
- }
-- Py_INCREF((PyObject *)&CImageType);
-- PyModule_AddObject(pModule, "Image", (PyObject *)&CImageType);
-+ PyModule_AddObject(pModule, "Image", (PyObject*)CImageType);
-
- return pModule;
- }
-@@ -808,45 +592,58 @@ namespace Plugins
-
- PyMODINIT_FUNC PyInit_DomoticzEx(void)
- {
--
- // This is called during the import of the plugin module
-- // triggered by the "import Domoticz" statement
-+ // triggered by the "import DomoticzEx" statement
- PyObject *pModule = PyModule_Create2(&DomoticzExModuleDef, PYTHON_API_VERSION);
- module_state *pModState = ((struct module_state *)PyModule_GetState(pModule));
-
-- if (PyType_Ready(&CDeviceExType) < 0)
-- {
-- _log.Log(LOG_ERROR, "%s, Device Type not ready.", __func__);
-- return pModule;
-- }
-- Py_INCREF((PyObject *)&CDeviceExType);
-- PyModule_AddObject(pModule, "Device", (PyObject *)&CDeviceExType);
-- pModState->pDeviceClass = &CDeviceExType;
--
-- if (PyType_Ready(&CUnitExType) < 0)
-- {
-- _log.Log(LOG_ERROR, "%s, Unit Type not ready.", __func__);
-- return pModule;
-- }
-- Py_INCREF((PyObject *)&CUnitExType);
-- PyModule_AddObject(pModule, "Unit", (PyObject *)&CUnitExType);
-- pModState->pUnitClass = &CUnitExType;
--
-- if (PyType_Ready(&CConnectionType) < 0)
-- {
-- _log.Log(LOG_ERROR, "%s, Connection Type not ready.", __func__);
-- return pModule;
-+ PyType_Slot DeviceExSlots[] = {
-+ { Py_tp_doc, (void*)"DomoticzEx Device" },
-+ { Py_tp_new, (void*)CDeviceEx_new },
-+ { Py_tp_init, (void*)CDeviceEx_init },
-+ { Py_tp_dealloc, (void*)CDeviceEx_dealloc },
-+ { Py_tp_members, CDeviceEx_members },
-+ { Py_tp_methods, CDeviceEx_methods },
-+ { Py_tp_str, (void*)CDeviceEx_str },
-+ { 0 },
-+ };
-+ PyType_Spec DeviceExSpec = { "DomoticzEx.Device", sizeof(CDeviceEx), 0,
-+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HEAPTYPE, DeviceExSlots };
-+
-+ pModState->pDeviceClass = (PyTypeObject*)PyType_FromSpec(&DeviceExSpec); // Calls PyType_Ready internally from, 3.9 onwards
-+ PyModule_AddObject(pModule, "Device", (PyObject *)pModState->pDeviceClass);
-+ PyType_Ready(pModState->pDeviceClass);
-+
-+ PyType_Slot UnitExSlots[] = {
-+ { Py_tp_doc, (void*)"DomoticzEx Unit" },
-+ { Py_tp_new, (void*)CUnitEx_new },
-+ { Py_tp_init, (void*)CUnitEx_init },
-+ { Py_tp_dealloc, (void*)CUnitEx_dealloc },
-+ { Py_tp_members, CUnitEx_members },
-+ { Py_tp_methods, CUnitEx_methods },
-+ { Py_tp_str, (void*)CUnitEx_str },
-+ { 0 },
-+ };
-+ PyType_Spec UnitExSpec = { "DomoticzEx.Unit", sizeof(CUnitEx), 0,
-+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HEAPTYPE, UnitExSlots };
-+
-+ pModState->pUnitClass = (PyTypeObject*)PyType_FromSpec(&UnitExSpec);
-+ PyModule_AddObject(pModule, "Unit", (PyObject*)pModState->pUnitClass);
-+ PyType_Ready(pModState->pUnitClass);
-+
-+ if (!CConnectionType)
-+ {
-+ CConnectionType = (PyTypeObject*)PyType_FromSpec(&ConnectionSpec);
-+ PyType_Ready(CConnectionType);
- }
-- Py_INCREF((PyObject *)&CConnectionType);
-- PyModule_AddObject(pModule, "Connection", (PyObject *)&CConnectionType);
-+ PyModule_AddObject(pModule, "Connection", (PyObject*)CConnectionType);
-
-- if (PyType_Ready(&CImageType) < 0)
-+ if (!CImageType)
- {
-- _log.Log(LOG_ERROR, "%s, Image Type not ready.", __func__);
-- return pModule;
-+ CImageType = (PyTypeObject*)PyType_FromSpec(&ImageSpec);
-+ PyType_Ready(CImageType);
- }
-- Py_INCREF((PyObject *)&CImageType);
-- PyModule_AddObject(pModule, "Image", (PyObject *)&CImageType);
-+ PyModule_AddObject(pModule, "Image", (PyObject*)CImageType);
-
- return pModule;
- }
-@@ -900,8 +697,7 @@ namespace Plugins
- module_state *pModState = ((struct module_state *)PyModule_GetState(brModule));
- if (!pModState)
- {
-- _log.Log(LOG_ERROR, "CPlugin:%s, unable to obtain module state.", __func__);
-- return nullptr;
-+ _log.Log(LOG_ERROR, "%s, unable to obtain module state.", __func__);
- }
-
- return pModState;
-@@ -910,205 +706,76 @@ namespace Plugins
- CPlugin *CPlugin::FindPlugin()
- {
- module_state *pModState = FindModule();
-- if (!pModState)
-- return nullptr;
-- return pModState->pPlugin;
-+ return pModState ? pModState->pPlugin : nullptr;
- }
-
-- void CPlugin::LogTraceback(PyTracebackObject *pTraceback)
-- {
-- if (pTraceback)
-- {
-- Log(LOG_ERROR, "Exception traceback:");
-- }
-- else
-- {
-- Log(LOG_ERROR, "No traceback available");
-- }
--
-- // Log a stack trace if there is one
-- PyTracebackObject *pTraceFrame = pTraceback;
-- while (pTraceFrame)
-- {
-- PyFrameObject *frame = pTraceFrame->tb_frame;
-- if (frame)
-- {
-- int lineno = PyFrame_GetLineNumber(frame);
-- PyCodeObject *pCode = frame->f_code;
-- std::string FileName;
-- if (pCode->co_filename)
-- {
-- FileName = (std::string)PyBorrowedRef(pCode->co_filename);
-- }
-- std::string FuncName = "Unknown";
-- if (pCode->co_name)
-- {
-- FuncName = (std::string)PyBorrowedRef(pCode->co_name);
-- }
-- if (!FileName.empty())
-- Log(LOG_ERROR, " ----> Line %d in '%s', function %s", lineno, FileName.c_str(), FuncName.c_str());
-- else
-- Log(LOG_ERROR, " ----> Line %d in '%s'", lineno, FuncName.c_str());
-- }
-- pTraceFrame = pTraceFrame->tb_next;
-- }
-- }
--
- void CPlugin::LogPythonException()
- {
-- PyTracebackObject *pTraceback;
-+ PyNewRef pTraceback;
- PyNewRef pExcept;
- PyNewRef pValue;
-
-- PyErr_Fetch(&pExcept, &pValue, (PyObject **)&pTraceback);
-- PyErr_NormalizeException(&pExcept, &pValue, (PyObject **)&pTraceback);
-- PyErr_Clear();
-+ PyErr_Fetch(&pExcept, &pValue, &pTraceback);
-+ PyErr_NormalizeException(&pExcept, &pValue, &pTraceback);
-
-- if (pExcept)
-+ if (!pExcept && !pValue && !pTraceback)
- {
-- Log(LOG_ERROR, "Module Import failed, exception: '%s'", ((PyTypeObject *)pExcept)->tp_name);
-+ Log(LOG_ERROR, "Unable to decode exception.");
- }
-- if (pValue)
-+ else
- {
-- std::string sError;
-- PyNewRef pErrBytes = PyUnicode_AsASCIIString(pValue); // Won't normally return text for Import related errors
-- if (!pErrBytes)
-+ std::string sTypeText("Unknown");
-+ if (pExcept)
- {
-- // ImportError has name and path attributes
-- PyErr_Clear();
-- if (PyObject_HasAttrString(pValue, "path"))
-- {
-- std::string sPath = PyNewRef(PyObject_GetAttrString(pValue, "path"));
-- if (sPath.length() && (sPath != "None"))
-- {
-- sError += "Path: " + sPath;
-- }
-- }
-- PyErr_Clear();
-- if (PyObject_HasAttrString(pValue, "name"))
-- {
-- std::string sName = PyNewRef(PyObject_GetAttrString(pValue, "name"));
-- if (sName.length() && (sName != "None"))
-- {
-- sError += " Name: " + sName;
-- }
-- }
-- if (!sError.empty())
-- {
-- Log(LOG_ERROR, "Module Import failed: '%s'", sError.c_str());
-- sError = "";
-- }
--
-- // SyntaxError, IndentationError & TabError have filename, lineno, offset and text attributes
-- PyErr_Clear();
-- if (PyObject_HasAttrString(pValue, "filename"))
-- {
-- std::string sName = PyNewRef(PyObject_GetAttrString(pValue, "name"));
-- sError += "File: " + sName;
-- }
-- long long lineno = -1;
-- long long offset = -1;
-- PyErr_Clear();
-- if (PyObject_HasAttrString(pValue, "lineno"))
-- {
-- PyNewRef pString = PyObject_GetAttrString(pValue, "lineno");
-- lineno = PyLong_AsLongLong(pString);
-- }
-- PyErr_Clear();
-- if (PyObject_HasAttrString(pValue, "offset"))
-- {
-- PyNewRef pString = PyObject_GetAttrString(pValue, "offset");
-- offset = PyLong_AsLongLong(pString);
-- }
-+ PyTypeObject* TypeName = (PyTypeObject*)pExcept;
-+ PyNewRef pName = PyObject_GetAttrString((PyObject*)TypeName, "__name__");
-+ sTypeText = (std::string)pName;
-+ }
-
-- if (!sError.empty())
-- {
-- if ((lineno > 0) && (lineno < 1000))
-+ /* See if we can get a full traceback */
-+ PyNewRef pModule = PyImport_ImportModule("traceback");
-+ if (pModule)
-+ {
-+ PyNewRef pFunc = PyObject_GetAttrString(pModule, "format_exception");
-+ if (pFunc && PyCallable_Check(pFunc)) {
-+ PyNewRef pList = PyObject_CallFunctionObjArgs(pFunc, pExcept, pValue, pTraceback, NULL);
-+ if (pList)
- {
-- Log(LOG_ERROR, "Import detail: %s, Line: %lld, offset: %lld", sError.c_str(), lineno, offset);
-+ for (Py_ssize_t i = 0; i < PyList_Size(pList); i++)
-+ {
-+ PyBorrowedRef pPyStr = PyList_GetItem(pList, i);
-+ std::string pStr(pPyStr);
-+ size_t pos = 0;
-+ std::string token;
-+ while ((pos = pStr.find('\n')) != std::string::npos) {
-+ token = pStr.substr(0, pos);
-+ Log(LOG_ERROR, "%s", token.c_str());
-+ pStr.erase(0, pos + 1);
-+ }
-+ }
- }
- else
- {
-- Log(LOG_ERROR, "Import detail: %s, Line: %lld", sError.c_str(), offset);
-+ Log(LOG_ERROR, "Exception: '%s'. No traceback available.", sTypeText.c_str());
- }
-- sError = "";
-- }
--
-- PyErr_Clear();
-- if (PyObject_HasAttrString(pValue, "text"))
-- {
-- std::string sUTF = PyNewRef(PyObject_GetAttrString(pValue, "text"));
-- Log(LOG_ERROR, "Error Line '%s'", sUTF.c_str());
- }
- else
- {
-- Log(LOG_ERROR, "Error Line details not available.");
-- }
--
-- if (!sError.empty())
-- {
-- Log(LOG_ERROR, "Import detail: %s", sError.c_str());
-+ Log(LOG_ERROR, "'format_exception' lookup failed, exception: '%s'. No traceback available.", sTypeText.c_str());
- }
- }
- else
-- Log(LOG_ERROR, "Module Import failed '%s'", std::string(pErrBytes).c_str());
-- }
--
-- // Log a stack trace if there is one
-- LogTraceback(pTraceback);
--
-- if (!pExcept && !pValue && !pTraceback)
-- {
-- Log(LOG_ERROR, "Call to import module failed, unable to decode exception.");
-+ {
-+ Log(LOG_ERROR, "'Traceback' module import failed, exception: '%s'. No traceback available.", sTypeText.c_str());
-+ }
- }
--
-- if (pTraceback)
-- Py_XDECREF(pTraceback);
-+ PyErr_Clear();
- }
-
- void CPlugin::LogPythonException(const std::string &sHandler)
- {
-- PyTracebackObject *pTraceback;
-- PyNewRef pExcept;
-- PyNewRef pValue;
-- PyTypeObject *TypeName;
-- PyNewRef pErrBytes;
-- const char *pTypeText = nullptr;
--
-- PyErr_Fetch(&pExcept, &pValue, (PyObject **)&pTraceback);
--
-- if (pExcept)
-- {
-- TypeName = (PyTypeObject *)pExcept;
-- pTypeText = TypeName->tp_name;
-- }
-- if (pTypeText && pValue)
-- {
-- Log(LOG_ERROR, "'%s' failed '%s':'%s'.", sHandler.c_str(), pTypeText, std::string(pValue).c_str());
-- }
-- if (pTypeText && !pValue)
-- {
-- Log(LOG_ERROR, "'%s' failed '%s'.", sHandler.c_str(), pTypeText);
-- }
-- if (!pTypeText && pValue)
-- {
-- Log(LOG_ERROR, "'%s' failed '%s'.",sHandler.c_str(), std::string(pValue).c_str());
-- }
-- if (!pTypeText && !pValue)
-- {
-- Log(LOG_ERROR, "'%s' failed, unable to determine error.", sHandler.c_str());
-- }
--
-- // Log a stack trace if there is one
-- LogTraceback(pTraceback);
--
-- if (!pExcept && !pValue && !pTraceback)
-- {
-- Log(LOG_ERROR, "Call to message handler '%s' failed, unable to decode exception.", sHandler.c_str());
-- }
--
-- if (pTraceback)
-- Py_XDECREF(pTraceback);
-+ Log(LOG_ERROR, "Call to function '%s' failed, exception details:", sHandler.c_str());
-+ LogPythonException();
- }
-
- int CPlugin::PollInterval(int Interval)
-@@ -1222,7 +889,6 @@ namespace Plugins
- // Tell transport to disconnect if required
- if (pPluginTransport)
- {
-- // std::lock_guard<std::mutex> l(PythonMutex); // Take mutex to guard access to CPluginTransport::m_pConnection
- MessagePlugin(new DisconnectDirective(pPluginTransport->Connection()));
- }
- }
-@@ -1314,25 +980,26 @@ namespace Plugins
- {
- if (m_bDebug & PDM_QUEUE)
- {
-- Log(LOG_NORM, "(" + m_Name + ") Processing '" + std::string(Message->Name()) + "' message");
-+ Log(LOG_NORM, "Processing '" + std::string(Message->Name()) + "' message");
- }
- Message->Process(this);
- }
- catch (...)
- {
-- Log(LOG_ERROR, "PluginSystem: Exception processing message.");
-+ Log(LOG_ERROR, "Exception processing '%s' message.", Message->Name());
-+ }
-+
-+ // Free the memory for the message
-+ if (!m_PyInterpreter)
-+ {
-+ // Can't lock because there is no interpreter to lock
-+ delete Message;
-+ }
-+ else
-+ {
-+ AccessPython Guard(this, Message->Name());
-+ delete Message;
- }
-- }
-- // Free the memory for the message
-- if (!m_PyInterpreter)
-- {
-- // Can't lock because there is no interpreter to lock
-- delete Message;
-- }
-- else
-- {
-- AccessPython Guard(this, m_Name.c_str());
-- delete Message;
- }
- }
-
-@@ -1351,7 +1018,6 @@ namespace Plugins
- {
- for (const auto &pPluginTransport : m_Transports)
- {
-- // std::lock_guard<std::mutex> l(PythonMutex); // Take mutex to guard access to CPluginTransport::m_pConnection
- pPluginTransport->VerifyConnection();
- }
- }
-@@ -1371,6 +1037,7 @@ namespace Plugins
-
- try
- {
-+ // Only initialise one plugin at a time to prevent issues with module creation
- PyEval_RestoreThread((PyThreadState *)m_mainworker.m_pluginsystem.PythonThread());
- m_PyInterpreter = Py_NewInterpreter();
- if (!m_PyInterpreter)
-@@ -1379,10 +1046,6 @@ namespace Plugins
- goto Error;
- }
-
-- // Get an instance of the single, central Py_None to use in local code
-- PyBorrowedRef globalNone = Py_BuildValue("");
-- Py_None = globalNone;
--
- // Prepend plugin directory to path so that python will search it early when importing
- #ifdef WIN32
- std::wstring sSeparator = L";";
-@@ -1433,7 +1096,7 @@ namespace Plugins
- for (Py_ssize_t i = 0; i < PyList_Size(pSites); i++)
- {
- PyBorrowedRef pSite = PyList_GetItem(pSites, i);
-- if (pSite && PyUnicode_Check(pSite))
-+ if (pSite.IsString())
- {
- std::wstringstream ssPath;
- ssPath << ((std::string)PyBorrowedRef(pSite)).c_str();
-@@ -1501,6 +1164,25 @@ namespace Plugins
- }
- pModState->pPlugin = this;
-
-+ // Get reference to global 'Py_None' instance for comparisons
-+ if (!Py_None)
-+ {
-+ PyBorrowedRef global_dict = PyModule_GetDict(m_PyModule);
-+ PyNewRef local_dict = PyDict_New();
-+ PyNewRef pCode = Py_CompileString("# Eval will return 'None'\n", "<domoticz>", Py_file_input);
-+ if (pCode)
-+ {
-+ PyNewRef pEval = PyEval_EvalCode(pCode, global_dict, local_dict);
-+ Py_None = pEval;
-+ Py_INCREF(Py_None);
-+ }
-+ else
-+ {
-+ Log(LOG_ERROR, "Failed to compile script to set global Py_None");
-+ }
-+ }
-+
-+
- // Add start command to message queue
- MessagePlugin(new onStartCallback());
-
-@@ -1611,7 +1293,7 @@ namespace Plugins
- }
- }
-
-- m_DeviceDict = (PyDictObject*)PyDict_New();
-+ m_DeviceDict = PyDict_New();
- if (PyDict_SetItemString(pModuleDict, "Devices", (PyObject *)m_DeviceDict) == -1)
- {
- Log(LOG_ERROR, "(%s) failed to add Device dictionary.", m_PluginKey.c_str());
-@@ -1647,7 +1329,6 @@ namespace Plugins
- // load associated devices to make them available to python
- if (!result.empty())
- {
-- PyType_Ready(pModState->pDeviceClass);
- // Add device objects into the device dictionary with Unit as the key
- for (const auto &sd : result)
- {
-@@ -1689,7 +1370,7 @@ namespace Plugins
- }
- }
-
-- m_ImageDict = (PyDictObject *)PyDict_New();
-+ m_ImageDict = PyDict_New();
- if (PyDict_SetItemString(pModuleDict, "Images", (PyObject *)m_ImageDict) == -1)
- {
- Log(LOG_ERROR, "(%s) failed to add Image dictionary.", m_PluginKey.c_str());
-@@ -1700,11 +1381,10 @@ namespace Plugins
- result = m_sql.safe_query("SELECT ID, Base, Name, Description FROM CustomImages WHERE Base LIKE '%q%%' ORDER BY ID ASC", m_PluginKey.c_str());
- if (!result.empty())
- {
-- PyType_Ready(&CImageType);
- // Add image objects into the image dictionary with ID as the key
- for (const auto &sd : result)
- {
-- CImage *pImage = (CImage *)CImage_new(&CImageType, (PyObject *)nullptr, (PyObject *)nullptr);
-+ CImage *pImage = (CImage *)CImage_new(CImageType, (PyObject *)nullptr, (PyObject *)nullptr);
-
- PyNewRef pKey = PyUnicode_FromString(sd[1].c_str());
- if (PyDict_SetItem((PyObject *)m_ImageDict, pKey, (PyObject *)pImage) == -1)
-@@ -2098,7 +1778,7 @@ namespace Plugins
- }
- else
- {
-- CDevice *pDevice = (CDevice *)CDevice_new(&CDeviceType, (PyObject *)nullptr, (PyObject *)nullptr);
-+ CDevice *pDevice = (CDevice *)CDevice_new(CDeviceType, (PyObject *)nullptr, (PyObject *)nullptr);
-
- PyNewRef pKey = PyLong_FromLong(Unit);
- if (PyDict_SetItem((PyObject *)m_DeviceDict, pKey, (PyObject *)pDevice) == -1)
-@@ -2250,13 +1930,24 @@ namespace Plugins
- void CPlugin::RestoreThread()
- {
- if (m_PyInterpreter)
-- PyEval_RestoreThread((PyThreadState *)m_PyInterpreter);
-+ {
-+ PyEval_RestoreThread((PyThreadState*)m_PyInterpreter);
-+ }
-+ else
-+ {
-+ Log(LOG_ERROR, "Attempt to aquire the GIL with NULL Interpreter details.");
-+ }
- }
-
- void CPlugin::ReleaseThread()
- {
- if (m_PyInterpreter)
-- PyEval_SaveThread();
-+ {
-+ if (!PyEval_SaveThread())
-+ {
-+ Log(LOG_ERROR, "Attempt to release GIL returned NULL value");
-+ }
-+ }
- }
-
- void CPlugin::Callback(PyObject *pTarget, const std::string &sHandler, PyObject *pParams)
-@@ -2294,7 +1985,11 @@ namespace Plugins
- }
-
- if (m_bDebug & PDM_QUEUE)
-- Log(LOG_NORM, "Calling message handler '%s' on '%s' type object.", sHandler.c_str(), pTarget->ob_type->tp_name);
-+ {
-+ PyNewRef pName = PyObject_GetAttrString((PyObject*)(pTarget->ob_type), "__name__");
-+ if (pName)
-+ Log(LOG_NORM, "Calling message handler '%s' on '%s' type object.", sHandler.c_str(), (std::string(pName).c_str()));
-+ }
-
- PyErr_Clear();
-
-@@ -2315,7 +2010,7 @@ namespace Plugins
- {
- // See if additional information is available
- PyNewRef pLocals = PyObject_Dir(pTarget);
-- if (PyList_Check(pLocals)) // && PyIter_Check(pLocals)) // Check fails but iteration works??!?
-+ if (pLocals.IsList()) // && PyIter_Check(pLocals)) // Check fails but iteration works??!?
- {
- Log(LOG_NORM, "Local context:");
- PyNewRef pIter = PyObject_GetIter(pLocals);
-@@ -2391,7 +2086,7 @@ namespace Plugins
- module_state *pModState = ((struct module_state *)PyModule_GetState(brModule));
- if (!pModState)
- {
-- Log(LOG_ERROR, "CPlugin:%s, unable to obtain module state.", __func__);
-+ Log(LOG_ERROR, "%s, unable to obtain module state.", __func__);
- return;
- }
-
-@@ -2409,7 +2104,8 @@ namespace Plugins
- }
- else if (isDevice == 0)
- {
-- Log(LOG_NORM, "%s: Device dictionary contained non-Device entry '%s'.", __func__, pDevice->ob_type->tp_name);
-+ PyNewRef pName = PyObject_GetAttrString((PyObject*)pDevice->ob_type, "__name__");
-+ Log(LOG_NORM, "%s: Device dictionary contained non-Device entry '%s'.", __func__, ((std::string)pName).c_str());
- }
- else
- {
-@@ -2430,7 +2126,8 @@ namespace Plugins
- }
- else if (isValue == 0)
- {
-- _log.Log(LOG_NORM, "%s: Unit dictionary contained non-Unit entry '%s'.", __func__, pUnit->ob_type->tp_name);
-+ PyNewRef pName = PyObject_GetAttrString((PyObject*)pUnit->ob_type, "__name__");
-+ _log.Log(LOG_NORM, "%s: Unit dictionary contained non-Unit entry '%s'.", __func__, ((std::string)pName).c_str());
- }
- else
- {
-@@ -2520,7 +2217,7 @@ namespace Plugins
- PyBorrowedRef pModuleDict = PyModule_GetDict(PythonModule()); // returns a borrowed referece to the __dict__ object for the module
- if (m_SettingsDict)
- Py_XDECREF(m_SettingsDict);
-- m_SettingsDict = (PyDictObject *)PyDict_New();
-+ m_SettingsDict = PyDict_New();
- if (PyDict_SetItemString(pModuleDict, "Settings", (PyObject *)m_SettingsDict) == -1)
- {
- Log(LOG_ERROR, "(%s) failed to add Settings dictionary.", m_PluginKey.c_str());
-@@ -2532,7 +2229,6 @@ namespace Plugins
- result = m_sql.safe_query("SELECT Key, nValue, sValue FROM Preferences");
- if (!result.empty())
- {
-- PyType_Ready(&CDeviceType);
- // Add settings strings into the settings dictionary with Unit as the key
- for (const auto &sd : result)
- {
-@@ -2617,12 +2313,15 @@ namespace Plugins
- if (!m_DeviceDict)
- return true;
-
-+ return false;
-+
- PyObject *key, *value;
- Py_ssize_t pos = 0;
- while (PyDict_Next((PyObject *)m_DeviceDict, &pos, &key, &value))
- {
- // Handle different Device dictionaries types
-- if (PyUnicode_Check(key))
-+ PyBorrowedRef pKeyType(key);
-+ if (pKeyType.IsString())
- {
- // Version 2+ of the framework, keyed by DeviceID
- std::string sKey = PyUnicode_AsUTF8(key);
-@@ -2632,7 +2331,7 @@ namespace Plugins
- return (pDevice->TimedOut != 0);
- }
- }
-- else
-+ else if (pKeyType.IsLong())
- {
- // Version 1 of the framework, keyed by Unit
- long iKey = PyLong_AsLong(key);
-@@ -2648,6 +2347,10 @@ namespace Plugins
- return (pDevice->TimedOut != 0);
- }
- }
-+ else
-+ {
-+ Log(LOG_ERROR, "'%s' Invalid Node key type.", __func__);
-+ }
- }
-
- return false;
-@@ -2655,7 +2358,7 @@ namespace Plugins
-
- PyBorrowedRef CPlugin::FindDevice(const std::string &Key)
- {
-- if (m_DeviceDict && PyDict_Check(m_DeviceDict))
-+ if (m_DeviceDict && PyBorrowedRef(m_DeviceDict).IsDict())
- {
- return PyDict_GetItemString((PyObject*)m_DeviceDict, Key.c_str());
- }
-@@ -2934,5 +2637,47 @@ namespace Plugins
-
- return true;
- }
-+
-+ bool PyBorrowedRef::TypeCheck(long PyType)
-+ {
-+ if (m_pObject)
-+ {
-+ PyNewRef pType = PyObject_Type(m_pObject);
-+ return pType && (PyType_GetFlags((PyTypeObject*)pType) & PyType);
-+ }
-+ return false;
-+ }
-+
-+ std::string PyBorrowedRef::Attribute(const char* name)
-+ {
-+ std::string sAttr = "";
-+ if (m_pObject)
-+ {
-+ try
-+ {
-+ if (PyObject_HasAttrString(m_pObject, name))
-+ {
-+ PyNewRef pAttr = PyObject_GetAttrString(m_pObject, name);
-+ sAttr = (std::string)pAttr;
-+ }
-+ }
-+ catch (...)
-+ {
-+ _log.Log(LOG_ERROR, "[%s] Exception determining Python object attribute '%s'.", __func__, name);
-+ }
-+ }
-+ return sAttr;
-+ }
-+
-+ std::string PyBorrowedRef::Type()
-+ {
-+ std::string sType = "";
-+ if (m_pObject)
-+ {
-+ PyNewRef pType = PyObject_Type(m_pObject);
-+ sType = pType.Attribute("__name__");
-+ }
-+ return sType;
-+ }
- } // namespace Plugins
- #endif
---- a/hardware/plugins/Plugins.h
-+++ b/hardware/plugins/Plugins.h
-@@ -62,8 +62,6 @@ namespace Plugins {
-
- void Do_Work();
-
-- void LogPythonException(const std::string &);
--
- public:
- CPlugin(int HwdID, const std::string &Name, const std::string &PluginKey);
- ~CPlugin() override;
-@@ -75,7 +73,7 @@ namespace Plugins {
- bool StopHardware() override;
-
- void LogPythonException();
-- void LogTraceback(PyTracebackObject *pTraceback);
-+ void LogPythonException(const std::string&);
-
- int PollInterval(int Interval = -1);
- PyObject* PythonModule() { return m_PyModule; };
-@@ -119,9 +117,9 @@ namespace Plugins {
- PyBorrowedRef FindUnitInDevice(const std::string &deviceKey, const int unitKey);
-
- std::string m_PluginKey;
-- PyDictObject* m_DeviceDict;
-- PyDictObject* m_ImageDict;
-- PyDictObject* m_SettingsDict;
-+ PyObject* m_DeviceDict;
-+ PyObject* m_ImageDict;
-+ PyObject* m_SettingsDict;
- std::string m_HomeFolder;
- PluginDebugMask m_bDebug;
- bool m_bTracing;
-@@ -147,16 +145,29 @@ namespace Plugins {
- //
- class PyBorrowedRef
- {
-- protected:
-+ protected:
- PyObject *m_pObject;
-+ bool TypeCheck(long);
-
-- public:
-+ public:
- PyBorrowedRef()
- : m_pObject(NULL){};
- PyBorrowedRef(PyObject *pObject)
- {
- m_pObject = pObject;
- };
-+ std::string Attribute(const char* name);
-+ std::string Type();
-+ bool IsDict() { return TypeCheck(Py_TPFLAGS_DICT_SUBCLASS); };
-+ bool IsList() { return TypeCheck(Py_TPFLAGS_LIST_SUBCLASS); };
-+ bool IsLong() { return TypeCheck(Py_TPFLAGS_LONG_SUBCLASS); };
-+ bool IsTuple() { return TypeCheck(Py_TPFLAGS_TUPLE_SUBCLASS); };
-+ bool IsString() { return TypeCheck(Py_TPFLAGS_UNICODE_SUBCLASS); };
-+ bool IsBytes() { return TypeCheck(Py_TPFLAGS_BYTES_SUBCLASS); };
-+ bool IsByteArray() { return Type() == "bytearray"; };
-+ bool IsFloat() { return Type() == "float"; };
-+ bool IsBool() { return Type() == "bool"; };
-+ bool IsNone() { return m_pObject && (m_pObject == Py_None); };
- operator PyObject *() const
- {
- return m_pObject;
-@@ -165,10 +176,6 @@ namespace Plugins {
- {
- return (PyTypeObject *)m_pObject;
- }
-- operator PyBytesObject *() const
-- {
-- return (PyBytesObject *)m_pObject;
-- }
- operator bool() const
- {
- return (m_pObject != NULL);
-@@ -283,12 +290,8 @@ namespace Plugins {
- class AccessPython
- {
- private:
-- static std::mutex PythonMutex;
-- static volatile bool m_bHasThreadState;
-- std::unique_lock<std::mutex>* m_Lock;
-- PyThreadState* m_Python;
- CPlugin* m_pPlugin;
-- const char* m_Text;
-+ std::string m_Text;
-
- public:
- AccessPython(CPlugin* pPlugin, const char* sWhat);
---- a/hardware/plugins/PythonObjectEx.cpp
-+++ b/hardware/plugins/PythonObjectEx.cpp
-@@ -8,7 +8,6 @@
- #include "../../main/Logger.h"
- #include "../../main/SQLHelper.h"
- #include "../../hardware/hardwaretypes.h"
--#include "../../main/localtime_r.h"
- #include "../../main/mainstructs.h"
- #include "../../main/mainworker.h"
- #include "../../main/EventSystem.h"
-@@ -23,19 +22,22 @@
- namespace Plugins {
-
- extern struct PyModuleDef DomoticzExModuleDef;
-- extern void LogPythonException(CPlugin *pPlugin, const std::string &sHandler);
- extern void maptypename(const std::string &sTypeName, int &Type, int &SubType, int &SwitchType, std::string &sValue, PyObject *OptionsIn, PyObject *OptionsOut);
-
- void CDeviceEx_dealloc(CDeviceEx *self)
- {
- Py_XDECREF(self->DeviceID);
- Py_XDECREF(self->m_UnitDict);
-- Py_TYPE(self)->tp_free((PyObject *)self);
-+
-+ PyNewRef pType = PyObject_Type((PyObject*)self);
-+ freefunc pFree = (freefunc)PyType_GetSlot(pType, Py_tp_free);
-+ pFree((PyObject*)self);
- }
-
- PyObject *CDeviceEx_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
- {
-- CDeviceEx *self = (CDeviceEx *)type->tp_alloc(type, 0);
-+ allocfunc pAlloc = (allocfunc)PyType_GetSlot(type, Py_tp_alloc);
-+ CDeviceEx* self = (CDeviceEx*)pAlloc(type, 0);
-
- try
- {
-@@ -95,11 +97,8 @@ namespace Plugins {
-
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &DeviceID))
- {
-- CPlugin *pPlugin = nullptr;
-- if (pModState)
-- pPlugin = pModState->pPlugin;
- pModState->pPlugin->Log(LOG_ERROR, R"(Expected: myVar = Domoticz.DeviceEx(DeviceID='xxxx'))");
-- LogPythonException(pPlugin, __func__);
-+ pModState->pPlugin->LogPythonException(__func__);
- }
- else
- {
-@@ -108,7 +107,7 @@ namespace Plugins {
- {
- self->DeviceID = PyUnicode_FromString(DeviceID);
- }
-- self->m_UnitDict = (PyDictObject *)PyDict_New();
-+ self->m_UnitDict = (PyObject *)PyDict_New();
- }
-
- return true;
-@@ -147,7 +146,6 @@ namespace Plugins {
- if (!result.empty())
- {
-
-- PyType_Ready(&CUnitExType);
- // Create Unit objects and add the Units dictionary with Unit number as the key
- for (auto itt = result.begin(); itt != result.end(); ++itt)
- {
-@@ -236,12 +234,16 @@ namespace Plugins {
- Py_XDECREF(self->Options);
- Py_XDECREF(self->Color);
- Py_XDECREF(self->Parent);
-- Py_TYPE(self)->tp_free((PyObject *)self);
-+
-+ PyNewRef pType = PyObject_Type((PyObject*)self);
-+ freefunc pFree = (freefunc)PyType_GetSlot(pType, Py_tp_free);
-+ pFree((PyObject*)self);
- }
-
- PyObject *CUnitEx_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
- {
-- CUnitEx *self = (CUnitEx *)type->tp_alloc(type, 0);
-+ allocfunc pAlloc = (allocfunc)PyType_GetSlot(type, Py_tp_alloc);
-+ CUnitEx *self = (CUnitEx*)pAlloc(type, 0);
-
- try
- {
-@@ -380,7 +382,6 @@ namespace Plugins {
- else
- {
- // Create a temporary one
-- PyType_Ready(pModState->pDeviceClass);
- PyNewRef nrArgList = Py_BuildValue("(s)", DeviceID);
- if (!nrArgList)
- {
-@@ -411,43 +412,40 @@ namespace Plugins {
- self->Image = Image;
- if (Used == 1)
- self->Used = Used;
-- if (Options && PyDict_Check(Options) && PyDict_Size(Options) > 0)
-+ if (Options && PyBorrowedRef(Options).IsDict() && PyDict_Size(Options) > 0)
- {
- PyObject *pKey, *pValue;
- Py_ssize_t pos = 0;
- PyDict_Clear(self->Options);
- while (PyDict_Next(Options, &pos, &pKey, &pValue))
- {
-- if (PyUnicode_Check(pValue))
-+ PyNewRef pKeyDict = PyObject_Str(pKey);
-+ PyNewRef pValueDict = PyObject_Str(pValue);
-+
-+ if (pKeyDict && pValueDict)
- {
-- PyNewRef pKeyDict = PyUnicode_FromKindAndData(PyUnicode_KIND(pKey), PyUnicode_DATA(pKey), PyUnicode_GET_LENGTH(pKey));
-- PyNewRef pValueDict = PyUnicode_FromKindAndData(PyUnicode_KIND(pValue), PyUnicode_DATA(pValue), PyUnicode_GET_LENGTH(pValue));
- if (PyDict_SetItem(self->Options, pKeyDict, pValueDict) == -1)
- {
-- _log.Log(LOG_ERROR, "(%s) Failed to initialize Options dictionary for Hardware/Unit combination (%d:%d).",
-- pModState->pPlugin->m_Name.c_str(), pModState->pPlugin->m_HwdID, self->Unit);
-+ pModState->pPlugin->Log(LOG_ERROR, "(%s) Failed to initialize Options dictionary for Hardware/Unit combination (%d:%d).",
-+ pModState->pPlugin->m_Name.c_str(), pModState->pPlugin->m_HwdID, self->Unit);
- break;
- }
- }
- else
- {
-- _log.Log(
-+ PyNewRef pName = PyObject_GetAttrString((PyObject*)pValue->ob_type, "__name__");
-+ pModState->pPlugin->Log(
- LOG_ERROR,
-- R"((%s) Failed to initialize Options dictionary for Hardware/Unit combination (%d:%d): Only "string" type dictionary entries supported, but entry has type "%s")",
-- pModState->pPlugin->m_Name.c_str(), pModState->pPlugin->m_HwdID, self->Unit, pValue->ob_type->tp_name);
-+ "(%s) Failed to initialize Options dictionary for Hardware / Unit combination(%d:%d): Unable to convert to string.)",
-+ pModState->pPlugin->m_Name.c_str(), pModState->pPlugin->m_HwdID, self->Unit);
- }
- }
- }
- }
- else
- {
-- CPlugin *pPlugin = nullptr;
-- if (pModState)
-- {
-- pPlugin = pModState->pPlugin;
-- _log.Log(LOG_ERROR, R"(Expected: myVar = DomoticzEx.Unit(Name="myDevice", DeviceID="", Unit=0, TypeName="", Type=0, Subtype=0, Switchtype=0, Image=0, Options={}, Used=1, Description=""))");
-- LogPythonException(pPlugin, __func__);
-- }
-+ pModState->pPlugin->Log(LOG_ERROR, R"(Expected: myVar = DomoticzEx.Unit(Name="myDevice", DeviceID="", Unit=0, TypeName="", Type=0, Subtype=0, Switchtype=0, Image=0, Options={}, Used=1, Description=""))");
-+ pModState->pPlugin->LogPythonException(__func__);
- }
- }
- catch (std::exception *e)
-@@ -756,7 +754,7 @@ namespace Plugins {
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "|ps", kwlist, &bWriteLog, &TypeName))
- {
- pModState->pPlugin->Log(LOG_ERROR, "(%s) Failed to parse parameters: 'Log' and/or 'TypeName' expected.", __func__);
-- LogPythonException(pModState->pPlugin, __func__);
-+ pModState->pPlugin->LogPythonException(__func__);
- Py_RETURN_NONE;
- }
-
-@@ -789,7 +787,7 @@ namespace Plugins {
-
- // Options provided, assume change
- std::string sOptionValue;
-- if (pOptionsDict && PyDict_Check(pOptionsDict))
-+ if (pOptionsDict && pOptionsDict.IsDict())
- {
- if (self->SubType != sTypeCustom)
- {
---- a/hardware/plugins/PythonObjectEx.h
-+++ b/hardware/plugins/PythonObjectEx.h
-@@ -12,7 +12,7 @@ namespace Plugins {
- PyObject_HEAD
- PyObject* DeviceID;
- int TimedOut;
-- PyDictObject* m_UnitDict;
-+ PyObject* m_UnitDict;
-
- static bool isInstance(PyObject *pObject);
- };
-@@ -36,46 +36,6 @@ namespace Plugins {
- { nullptr } /* Sentinel */
- };
-
-- static PyTypeObject CDeviceExType = {
-- PyVarObject_HEAD_INIT(nullptr, 0) "DomoticzEx.Device", /* tp_name */
-- sizeof(CDeviceEx), /* tp_basicsize */
-- 0, /* tp_itemsize */
-- (destructor)CDeviceEx_dealloc, /* tp_dealloc */
-- 0, /* tp_print */
-- nullptr, /* tp_getattr */
-- nullptr, /* tp_setattr */
-- nullptr, /* tp_reserved */
-- nullptr, /* tp_repr */
-- nullptr, /* tp_as_number */
-- nullptr, /* tp_as_sequence */
-- nullptr, /* tp_as_mapping */
-- nullptr, /* tp_hash */
-- nullptr, /* tp_call */
-- (reprfunc)CDeviceEx_str, /* tp_str */
-- nullptr, /* tp_getattro */
-- nullptr, /* tp_setattro */
-- nullptr, /* tp_as_buffer */
-- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
-- "DomoticzEx Device", /* tp_doc */
-- nullptr, /* tp_traverse */
-- nullptr, /* tp_clear */
-- nullptr, /* tp_richcompare */
-- 0, /* tp_weaklistoffset */
-- nullptr, /* tp_iter */
-- nullptr, /* tp_iternext */
-- CDeviceEx_methods, /* tp_methods */
-- CDeviceEx_members, /* tp_members */
-- nullptr, /* tp_getset */
-- nullptr, /* tp_base */
-- nullptr, /* tp_dict */
-- nullptr, /* tp_descr_get */
-- nullptr, /* tp_descr_set */
-- 0, /* tp_dictoffset */
-- (initproc)CDeviceEx_init, /* tp_init */
-- nullptr, /* tp_alloc */
-- CDeviceEx_new /* tp_new */
-- };
--
- class CUnitEx
- {
- public:
-@@ -146,44 +106,5 @@ namespace Plugins {
- { "Touch", (PyCFunction)CUnitEx_touch, METH_NOARGS, "Notify Domoticz that device has been seen." },
- { nullptr } /* Sentinel */
- };
--
-- static PyTypeObject CUnitExType = {
-- PyVarObject_HEAD_INIT(nullptr, 0) "DomoticzEx.Unit", /* tp_name */
-- sizeof(CUnitEx), /* tp_basicsize */
-- 0, /* tp_itemsize */
-- (destructor)CUnitEx_dealloc, /* tp_dealloc */
-- 0, /* tp_print */
-- nullptr, /* tp_getattr */
-- nullptr, /* tp_setattr */
-- nullptr, /* tp_reserved */
-- nullptr, /* tp_repr */
-- nullptr, /* tp_as_number */
-- nullptr, /* tp_as_sequence */
-- nullptr, /* tp_as_mapping */
-- nullptr, /* tp_hash */
-- nullptr, /* tp_call */
-- (reprfunc)CUnitEx_str, /* tp_str */
-- nullptr, /* tp_getattro */
-- nullptr, /* tp_setattro */
-- nullptr, /* tp_as_buffer */
-- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
-- "DomoticzEx Unit", /* tp_doc */
-- nullptr, /* tp_traverse */
-- nullptr, /* tp_clear */
-- nullptr, /* tp_richcompare */
-- 0, /* tp_weaklistoffset */
-- nullptr, /* tp_iter */
-- nullptr, /* tp_iternext */
-- CUnitEx_methods, /* tp_methods */
-- CUnitEx_members, /* tp_members */
-- nullptr, /* tp_getset */
-- nullptr, /* tp_base */
-- nullptr, /* tp_dict */
-- nullptr, /* tp_descr_get */
-- nullptr, /* tp_descr_set */
-- 0, /* tp_dictoffset */
-- (initproc)CUnitEx_init, /* tp_init */
-- nullptr, /* tp_alloc */
-- CUnitEx_new /* tp_new */
-- };
-+
- } // namespace Plugins
---- a/hardware/plugins/PythonObjects.cpp
-+++ b/hardware/plugins/PythonObjects.cpp
-@@ -8,7 +8,6 @@
- #include "../../main/Logger.h"
- #include "../../main/SQLHelper.h"
- #include "../../hardware/hardwaretypes.h"
--#include "../../main/localtime_r.h"
- #include "../../main/mainstructs.h"
- #include "../../main/mainworker.h"
- #include "../../main/EventSystem.h"
-@@ -22,21 +21,28 @@
-
- namespace Plugins {
-
-+ PyTypeObject* CDeviceType = nullptr;
-+ PyTypeObject* CConnectionType = nullptr;
-+ PyTypeObject* CImageType = nullptr;
-+
- extern struct PyModuleDef DomoticzModuleDef;
- extern struct PyModuleDef DomoticzExModuleDef;
-- extern void LogPythonException(CPlugin *pPlugin, const std::string &sHandler);
-
- void CImage_dealloc(CImage* self)
- {
- Py_XDECREF(self->Base);
- Py_XDECREF(self->Name);
- Py_XDECREF(self->Description);
-- Py_TYPE(self)->tp_free((PyObject*)self);
-+
-+ PyNewRef pType = PyObject_Type((PyObject*)self);
-+ freefunc pFree = (freefunc)PyType_GetSlot(pType, Py_tp_free);
-+ pFree((PyObject*)self);
- }
-
- PyObject* CImage_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
- {
-- CImage *self = (CImage *)type->tp_alloc(type, 0);
-+ allocfunc pAlloc = (allocfunc)PyType_GetSlot(type, Py_tp_alloc);
-+ CImage *self = (CImage *)pAlloc(type, 0);
-
- try
- {
-@@ -130,10 +136,8 @@ namespace Plugins {
- }
- else
- {
-- CPlugin *pPlugin = nullptr;
-- if (pModState) pPlugin = pModState->pPlugin;
-- _log.Log(LOG_ERROR, "Expected: myVar = Domoticz.Image(Filename=\"MyImages.zip\")");
-- LogPythonException(pPlugin, __func__);
-+ pModState->pPlugin->Log(LOG_ERROR, "Expected: myVar = Domoticz.Image(Filename=\"MyImages.zip\")");
-+ pModState->pPlugin->LogPythonException(__func__);
- }
- }
- catch (std::exception *e)
-@@ -177,11 +181,10 @@ namespace Plugins {
- std::vector<std::vector<std::string> > result = m_sql.safe_query("SELECT max(ID), Base, Name, Description FROM CustomImages");
- if (!result.empty())
- {
-- PyType_Ready(&CImageType);
- // Add image objects into the image dictionary with ID as the key
- for (const auto &sd : result)
- {
-- CImage *pImage = (CImage *)CImage_new(&CImageType, (PyObject *)nullptr,
-+ CImage *pImage = (CImage *)CImage_new(CImageType, (PyObject *)nullptr,
- (PyObject *)nullptr);
-
- PyObject* pKey = PyUnicode_FromString(sd[1].c_str());
-@@ -226,7 +229,7 @@ namespace Plugins {
- {
- if (self->pPlugin->m_bDebug & PDM_IMAGE)
- {
-- _log.Log(LOG_NORM, "(%s) Deleting Image '%s'.", self->pPlugin->m_Name.c_str(), sName.c_str());
-+ _log.Log(LOG_NORM, "Deleting Image '%s'.", sName.c_str());
- }
-
- std::vector<std::vector<std::string> > result;
-@@ -238,19 +241,18 @@ namespace Plugins {
- PyNewRef pKey = PyLong_FromLong(self->ImageID);
- if (PyDict_DelItem((PyObject*)self->pPlugin->m_ImageDict, pKey) == -1)
- {
-- _log.Log(LOG_ERROR, "(%s) failed to delete image '%d' from images dictionary.", self->pPlugin->m_Name.c_str(), self->ImageID);
-- Py_INCREF(Py_None);
-- return Py_None;
-+ self->pPlugin->Log(LOG_ERROR, "Failed to delete image '%d' from images dictionary.", self->ImageID);
-+ Py_RETURN_NONE;
- }
- }
- else
- {
-- _log.Log(LOG_ERROR, "(%s) Image deletion failed, Image %d not found in Domoticz.", self->pPlugin->m_Name.c_str(), self->ImageID);
-+ self->pPlugin->Log(LOG_ERROR, "Image deletion failed, Image %d not found in Domoticz.", self->ImageID);
- }
- }
- else
- {
-- _log.Log(LOG_ERROR, "(%s) Image deletion failed, '%s' does not represent a Image in Domoticz.", self->pPlugin->m_Name.c_str(), sName.c_str());
-+ self->pPlugin->Log(LOG_ERROR, "Image deletion failed, '%s' does not represent a Image in Domoticz.", sName.c_str());
- }
- }
- else
-@@ -278,12 +280,16 @@ namespace Plugins {
- PyDict_Clear(self->Options);
- Py_XDECREF(self->Options);
- Py_XDECREF(self->Color);
-- Py_TYPE(self)->tp_free((PyObject*)self);
-+
-+ PyNewRef pType = PyObject_Type((PyObject*)self);
-+ freefunc pFree = (freefunc)PyType_GetSlot(pType, Py_tp_free);
-+ pFree((PyObject*)self);
- }
-
- PyObject* CDevice_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
- {
-- CDevice *self = (CDevice *)type->tp_alloc(type, 0);
-+ allocfunc pAlloc = (allocfunc)PyType_GetSlot(type, Py_tp_alloc);
-+ CDevice *self = (CDevice*)pAlloc(type, 0);
-
- try
- {
-@@ -473,7 +479,7 @@ namespace Plugins {
- }
- else if (sTypeName == "Selector Switch")
- {
-- if (!OptionsIn || !PyDict_Check(OptionsIn)) {
-+ if (!OptionsIn || !PyBorrowedRef(OptionsIn).IsDict()) {
- PyDict_Clear(OptionsOut);
- PyDict_SetItemString(OptionsOut, "LevelActions", PyUnicode_FromString("|||"));
- PyDict_SetItemString(OptionsOut, "LevelNames", PyUnicode_FromString("Off|Level1|Level2|Level3"));
-@@ -517,7 +523,7 @@ namespace Plugins {
- else if (sTypeName == "Custom")
- {
- SubType = sTypeCustom;
-- if (!OptionsIn || !PyDict_Check(OptionsIn)) {
-+ if (!OptionsIn || !PyBorrowedRef(OptionsIn).IsDict()) {
- PyDict_Clear(OptionsOut);
- PyDict_SetItemString(OptionsOut, "Custom", PyUnicode_FromString("1"));
- }
-@@ -615,42 +621,39 @@ namespace Plugins {
- if (SwitchType != -1) self->SwitchType = SwitchType;
- if (Image != -1) self->Image = Image;
- if (Used == 1) self->Used = Used;
-- if (Options && PyDict_Check(Options) && PyDict_Size(Options) > 0) {
-+ if (Options && PyBorrowedRef(Options).IsDict() && PyDict_Size(Options) > 0) {
- PyObject *pKey, *pValue;
- Py_ssize_t pos = 0;
- PyDict_Clear(self->Options);
-- while(PyDict_Next(Options, &pos, &pKey, &pValue))
-+ while (PyDict_Next(Options, &pos, &pKey, &pValue))
- {
-- if (PyUnicode_Check(pValue))
-+ PyNewRef pKeyDict = PyObject_Str(pKey);
-+ PyNewRef pValueDict = PyObject_Str(pValue);
-+
-+ if (pKeyDict && pValueDict)
- {
-- PyObject *pKeyDict = PyUnicode_FromKindAndData(PyUnicode_KIND(pKey), PyUnicode_DATA(pKey), PyUnicode_GET_LENGTH(pKey));
-- PyObject *pValueDict = PyUnicode_FromKindAndData(PyUnicode_KIND(pValue), PyUnicode_DATA(pValue), PyUnicode_GET_LENGTH(pValue));
- if (PyDict_SetItem(self->Options, pKeyDict, pValueDict) == -1)
- {
-- _log.Log(LOG_ERROR, "(%s) Failed to initialize Options dictionary for Hardware/Unit combination (%d:%d).", self->pPlugin->m_Name.c_str(), self->HwdID, self->Unit);
-- Py_XDECREF(pKeyDict);
-- Py_XDECREF(pValueDict);
-+ pModState->pPlugin->Log(LOG_ERROR, "(%s) Failed to initialize Options dictionary for Hardware/Unit combination (%d:%d).",
-+ pModState->pPlugin->m_Name.c_str(), pModState->pPlugin->m_HwdID, self->Unit);
- break;
- }
-- Py_XDECREF(pKeyDict);
-- Py_XDECREF(pValueDict);
- }
- else
- {
-- _log.Log(
-+ PyNewRef pName = PyObject_GetAttrString((PyObject*)pValue->ob_type, "__name__");
-+ pModState->pPlugin->Log(
- LOG_ERROR,
-- R"((%s) Failed to initialize Options dictionary for Hardware/Unit combination (%d:%d): Only "string" type dictionary entries supported, but entry has type "%s")",
-- self->pPlugin->m_Name.c_str(), self->HwdID, self->Unit, pValue->ob_type->tp_name);
-+ "(%s) Failed to initialize Options dictionary for Hardware / Unit combination(%d:%d): Unable to convert to string.)",
-+ pModState->pPlugin->m_Name.c_str(), pModState->pPlugin->m_HwdID, self->Unit);
- }
- }
- }
- }
- else
- {
-- CPlugin *pPlugin = nullptr;
-- if (pModState) pPlugin = pModState->pPlugin;
-- _log.Log(LOG_ERROR, R"(Expected: myVar = Domoticz.Device(Name="myDevice", Unit=0, TypeName="", Type=0, Subtype=0, Switchtype=0, Image=0, Options={}, Used=1))");
-- LogPythonException(pPlugin, __func__);
-+ pModState->pPlugin->Log(LOG_ERROR, R"(Expected: myVar = Domoticz.Device(Name="myDevice", Unit=0, TypeName="", Type=0, Subtype=0, Switchtype=0, Image=0, Options={}, Used=1))");
-+ pModState->pPlugin->LogPythonException(__func__);
- }
- }
- catch (std::exception *e)
-@@ -745,12 +748,12 @@ namespace Plugins {
- {
- if (self->pPlugin->m_bDebug & PDM_DEVICE)
- {
-- _log.Log(LOG_NORM, "(%s) Creating device '%s'.", self->pPlugin->m_Name.c_str(), sName.c_str());
-+ self->pPlugin->Log(LOG_NORM, "Creating device '%s'.", sName.c_str());
- }
-
- if (!m_sql.m_bAcceptNewHardware)
- {
-- _log.Log(LOG_ERROR, "(%s) Device creation failed, Domoticz settings prevent accepting new devices.", self->pPlugin->m_Name.c_str());
-+ self->pPlugin->Log(LOG_ERROR, "Device creation failed, Domoticz settings prevent accepting new devices.");
- }
- else
- {
-@@ -792,9 +795,8 @@ namespace Plugins {
- PyNewRef pKey = PyLong_FromLong(self->Unit);
- if (PyDict_SetItem((PyObject*)self->pPlugin->m_DeviceDict, pKey, (PyObject*)self) == -1)
- {
-- _log.Log(LOG_ERROR, "(%s) failed to add unit '%d' to device dictionary.", self->pPlugin->m_Name.c_str(), self->Unit);
-- Py_INCREF(Py_None);
-- return Py_None;
-+ self->pPlugin->Log(LOG_ERROR, "Failed to add unit '%d' to device dictionary.", self->Unit);
-+ Py_RETURN_NONE;
- }
-
- // Device successfully created, now set the options when supplied
-@@ -817,18 +819,18 @@ namespace Plugins {
- }
- else
- {
-- _log.Log(LOG_ERROR, "(%s) Device creation failed, Hardware/Unit combination (%d:%d) not found in Domoticz.", self->pPlugin->m_Name.c_str(), self->HwdID, self->Unit);
-+ self->pPlugin->Log(LOG_ERROR, "Device creation failed, Hardware/Unit combination (%d:%d) not found in Domoticz.", self->HwdID, self->Unit);
- }
- }
- else
- {
-- _log.Log(LOG_ERROR, "(%s) Device creation failed, Hardware/Unit combination (%d:%d) already exists in Domoticz.", self->pPlugin->m_Name.c_str(), self->HwdID, self->Unit);
-+ self->pPlugin->Log(LOG_ERROR, "Device creation failed, Hardware/Unit combination (%d:%d) already exists in Domoticz.", self->HwdID, self->Unit);
- }
- }
- }
- else
- {
-- _log.Log(LOG_ERROR, "(%s) Device creation failed, '%s' already exists in Domoticz with Device ID '%d'.", self->pPlugin->m_Name.c_str(), sName.c_str(), self->ID);
-+ self->pPlugin->Log(LOG_ERROR, "Device creation failed, '%s' already exists in Domoticz with Device ID '%d'.", sName.c_str(), self->ID);
- }
- }
- else
-@@ -874,11 +876,10 @@ namespace Plugins {
-
- // Try to extract parameters needed to update device settings
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "is|iiiOissiiiissp", kwlist, &nValue, &sValue, &iImage, &iSignalLevel, &iBatteryLevel, &pOptionsDict, &iTimedOut, &Name, &TypeName, &iType, &iSubType, &iSwitchType, &iUsed, &Description, &Color, &SuppressTriggers))
-- {
-- _log.Log(LOG_ERROR, "(%s) %s: Failed to parse parameters: 'nValue', 'sValue', 'Image', 'SignalLevel', 'BatteryLevel', 'Options', 'TimedOut', 'Name', 'TypeName', 'Type', 'Subtype', 'Switchtype', 'Used', 'Description', 'Color' or 'SuppressTriggers' expected.", __func__, sName.c_str());
-- LogPythonException(self->pPlugin, __func__);
-- Py_INCREF(Py_None);
-- return Py_None;
-+ {
-+ self->pPlugin->Log(LOG_ERROR, "(%s) %s: Failed to parse parameters: 'nValue', 'sValue', 'Image', 'SignalLevel', 'BatteryLevel', 'Options', 'TimedOut', 'Name', 'TypeName', 'Type', 'Subtype', 'Switchtype', 'Used', 'Description', 'Color' or 'SuppressTriggers' expected.", __func__, sName.c_str());
-+ self->pPlugin->LogPythonException(__func__);
-+ Py_RETURN_NONE;
- }
-
- std::string sID = std::to_string(self->ID);
-@@ -979,7 +980,7 @@ namespace Plugins {
- }
-
- // Options provided, assume change
-- if (pOptionsDict && PyDict_Check(pOptionsDict))
-+ if (pOptionsDict && PyBorrowedRef(pOptionsDict).IsDict())
- {
- if (self->SubType != sTypeCustom)
- {
-@@ -1094,7 +1095,7 @@ namespace Plugins {
- {
- if (self->pPlugin->m_bDebug & PDM_DEVICE)
- {
-- _log.Log(LOG_NORM, "(%s) Deleting device '%s'.", self->pPlugin->m_Name.c_str(), sName.c_str());
-+ self->pPlugin->Log(LOG_NORM, "Deleting device '%s'.", sName.c_str());
- }
-
- std::vector<std::vector<std::string> > result;
-@@ -1106,19 +1107,18 @@ namespace Plugins {
- PyNewRef pKey = PyLong_FromLong(self->Unit);
- if (PyDict_DelItem((PyObject*)self->pPlugin->m_DeviceDict, pKey) == -1)
- {
-- _log.Log(LOG_ERROR, "(%s) failed to delete unit '%d' from device dictionary.", self->pPlugin->m_Name.c_str(), self->Unit);
-- Py_INCREF(Py_None);
-- return Py_None;
-+ self->pPlugin->Log(LOG_ERROR, "Failed to delete unit '%d' from device dictionary.", self->Unit);
-+ Py_RETURN_NONE;
- }
- }
- else
- {
-- _log.Log(LOG_ERROR, "(%s) Device deletion failed, Hardware/Unit combination (%d:%d) not found in Domoticz.", self->pPlugin->m_Name.c_str(), self->HwdID, self->Unit);
-+ self->pPlugin->Log(LOG_ERROR, "Device deletion failed, Hardware/Unit combination (%d:%d) not found in Domoticz.", self->HwdID, self->Unit);
- }
- }
- else
- {
-- _log.Log(LOG_ERROR, "(%s) Device deletion failed, '%s' does not represent a device in Domoticz.", self->pPlugin->m_Name.c_str(), sName.c_str());
-+ self->pPlugin->Log(LOG_ERROR, "Device deletion failed, '%s' does not represent a device in Domoticz.", sName.c_str());
- }
- }
- else
-@@ -1155,10 +1155,14 @@ namespace Plugins {
-
- void CConnection_dealloc(CConnection * self)
- {
-- CPlugin *pPlugin = CPlugin::FindPlugin();
-+ CPlugin *pPlugin = self->pPlugin;
-+ if (!pPlugin)
-+ {
-+ pPlugin = CPlugin::FindPlugin();
-+ }
- if (pPlugin && (pPlugin->m_bDebug & PDM_CONNECTION))
- {
-- _log.Log(LOG_NORM, "(%s) Deallocating connection object '%s' (%s:%s).", pPlugin->m_Name.c_str(), PyUnicode_AsUTF8(self->Name), PyUnicode_AsUTF8(self->Address), PyUnicode_AsUTF8(self->Port));
-+ pPlugin->Log(LOG_NORM, "Deallocating connection object '%s' (%s:%s).", PyUnicode_AsUTF8(self->Name), PyUnicode_AsUTF8(self->Address), PyUnicode_AsUTF8(self->Port));
- }
-
- Py_XDECREF(self->Target);
-@@ -1180,22 +1184,15 @@ namespace Plugins {
- self->pProtocol = nullptr;
- }
-
-- Py_TYPE(self)->tp_free((PyObject*)self);
-+ PyNewRef pType = PyObject_Type((PyObject*)self);
-+ freefunc pFree = (freefunc)PyType_GetSlot(pType, Py_tp_free);
-+ pFree((PyObject*)self);
- }
-
- PyObject * CConnection_new(PyTypeObject * type, PyObject * args, PyObject * kwds)
- {
-- CConnection *self = nullptr;
-- if ((CConnection *)type->tp_alloc)
-- {
-- self = (CConnection *)type->tp_alloc(type, 0);
-- }
-- else
-- {
-- //!Giz: self = NULL here!!
-- //_log.Log(LOG_ERROR, "(%s) CConnection Type is not ready.", self->pPlugin->m_Name.c_str());
-- _log.Log(LOG_ERROR, "(Python plugin) CConnection Type is not ready!");
-- }
-+ allocfunc pAlloc = (allocfunc)PyType_GetSlot(type, Py_tp_alloc);
-+ CConnection *self = (CConnection*)pAlloc(type, 0);
-
- try
- {
-@@ -1335,19 +1332,19 @@ namespace Plugins {
- if (pPlugin->IsStopRequested(0))
- {
- pPlugin->Log(LOG_NORM, "%s, connect request from '%s' ignored. Plugin is stopping.", __func__, self->pPlugin->m_Name.c_str());
-- return Py_None;
-+ Py_RETURN_NONE;
- }
-
- if (self->pTransport && self->pTransport->IsConnecting())
- {
- pPlugin->Log(LOG_ERROR, "%s, connect request from '%s' ignored. Transport is connecting.", __func__, self->pPlugin->m_Name.c_str());
-- return Py_None;
-+ Py_RETURN_NONE;
- }
-
- if (self->pTransport && self->pTransport->IsConnected())
- {
- pPlugin->Log(LOG_ERROR, "%s, connect request from '%s' ignored. Transport is connected.", __func__, self->pPlugin->m_Name.c_str());
-- return Py_None;
-+ Py_RETURN_NONE;
- }
-
- PyObject *pTarget = NULL;
-@@ -1457,7 +1454,7 @@ namespace Plugins {
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|i", kwlist, &pData, &iDelay))
- {
- pPlugin->Log(LOG_ERROR, "(%s) failed to parse parameters, Message or Message, Delay expected.", pPlugin->m_Name.c_str());
-- LogPythonException(pPlugin, std::string(__func__));
-+ pPlugin->LogPythonException(__func__);
- }
- else
- {
---- a/hardware/plugins/PythonObjects.h
-+++ b/hardware/plugins/PythonObjects.h
-@@ -40,46 +40,6 @@ namespace Plugins {
- { nullptr } /* Sentinel */
- };
-
-- static PyTypeObject CImageType = {
-- PyVarObject_HEAD_INIT(nullptr, 0) "Domoticz.Image", /* tp_name */
-- sizeof(CImage), /* tp_basicsize */
-- 0, /* tp_itemsize */
-- (destructor)CImage_dealloc, /* tp_dealloc */
-- 0, /* tp_print */
-- nullptr, /* tp_getattr */
-- nullptr, /* tp_setattr */
-- nullptr, /* tp_reserved */
-- nullptr, /* tp_repr */
-- nullptr, /* tp_as_number */
-- nullptr, /* tp_as_sequence */
-- nullptr, /* tp_as_mapping */
-- nullptr, /* tp_hash */
-- nullptr, /* tp_call */
-- (reprfunc)CImage_str, /* tp_str */
-- nullptr, /* tp_getattro */
-- nullptr, /* tp_setattro */
-- nullptr, /* tp_as_buffer */
-- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
-- "Domoticz Image", /* tp_doc */
-- nullptr, /* tp_traverse */
-- nullptr, /* tp_clear */
-- nullptr, /* tp_richcompare */
-- 0, /* tp_weaklistoffset */
-- nullptr, /* tp_iter */
-- nullptr, /* tp_iternext */
-- CImage_methods, /* tp_methods */
-- CImage_members, /* tp_members */
-- nullptr, /* tp_getset */
-- nullptr, /* tp_base */
-- nullptr, /* tp_dict */
-- nullptr, /* tp_descr_get */
-- nullptr, /* tp_descr_set */
-- 0, /* tp_dictoffset */
-- (initproc)CImage_init, /* tp_init */
-- nullptr, /* tp_alloc */
-- CImage_new /* tp_new */
-- };
--
- class CDevice
- {
- public:
-@@ -151,46 +111,6 @@ namespace Plugins {
- { nullptr } /* Sentinel */
- };
-
-- static PyTypeObject CDeviceType = {
-- PyVarObject_HEAD_INIT(nullptr, 0) "Domoticz.Device", /* tp_name */
-- sizeof(CDevice), /* tp_basicsize */
-- 0, /* tp_itemsize */
-- (destructor)CDevice_dealloc, /* tp_dealloc */
-- 0, /* tp_print */
-- nullptr, /* tp_getattr */
-- nullptr, /* tp_setattr */
-- nullptr, /* tp_reserved */
-- nullptr, /* tp_repr */
-- nullptr, /* tp_as_number */
-- nullptr, /* tp_as_sequence */
-- nullptr, /* tp_as_mapping */
-- nullptr, /* tp_hash */
-- nullptr, /* tp_call */
-- (reprfunc)CDevice_str, /* tp_str */
-- nullptr, /* tp_getattro */
-- nullptr, /* tp_setattro */
-- nullptr, /* tp_as_buffer */
-- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
-- "Domoticz Device", /* tp_doc */
-- nullptr, /* tp_traverse */
-- nullptr, /* tp_clear */
-- nullptr, /* tp_richcompare */
-- 0, /* tp_weaklistoffset */
-- nullptr, /* tp_iter */
-- nullptr, /* tp_iternext */
-- CDevice_methods, /* tp_methods */
-- CDevice_members, /* tp_members */
-- nullptr, /* tp_getset */
-- nullptr, /* tp_base */
-- nullptr, /* tp_dict */
-- nullptr, /* tp_descr_get */
-- nullptr, /* tp_descr_set */
-- 0, /* tp_dictoffset */
-- (initproc)CDevice_init, /* tp_init */
-- nullptr, /* tp_alloc */
-- CDevice_new /* tp_new */
-- };
--
- class CPluginTransport;
- class CPluginProtocol;
-
-@@ -248,43 +168,4 @@ namespace Plugins {
- { nullptr } /* Sentinel */
- };
-
-- static PyTypeObject CConnectionType = {
-- PyVarObject_HEAD_INIT(nullptr, 0) "Domoticz.Connection", /* tp_name */
-- sizeof(CConnection), /* tp_basicsize */
-- 0, /* tp_itemsize */
-- (destructor)CConnection_dealloc, /* tp_dealloc */
-- 0, /* tp_print */
-- nullptr, /* tp_getattr */
-- nullptr, /* tp_setattr */
-- nullptr, /* tp_reserved */
-- nullptr, /* tp_repr */
-- nullptr, /* tp_as_number */
-- nullptr, /* tp_as_sequence */
-- nullptr, /* tp_as_mapping */
-- nullptr, /* tp_hash */
-- nullptr, /* tp_call */
-- (reprfunc)CConnection_str, /* tp_str */
-- nullptr, /* tp_getattro */
-- nullptr, /* tp_setattro */
-- nullptr, /* tp_as_buffer */
-- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
-- "Domoticz Connection", /* tp_doc */
-- nullptr, /* tp_traverse */
-- nullptr, /* tp_clear */
-- nullptr, /* tp_richcompare */
-- 0, /* tp_weaklistoffset */
-- nullptr, /* tp_iter */
-- nullptr, /* tp_iternext */
-- CConnection_methods, /* tp_methods */
-- CConnection_members, /* tp_members */
-- nullptr, /* tp_getset */
-- nullptr, /* tp_base */
-- nullptr, /* tp_dict */
-- nullptr, /* tp_descr_get */
-- nullptr, /* tp_descr_set */
-- 0, /* tp_dictoffset */
-- (initproc)CConnection_init, /* tp_init */
-- nullptr, /* tp_alloc */
-- CConnection_new /* tp_new */
-- };
- } // namespace Plugins
---- a/main/EventSystem.cpp
-+++ b/main/EventSystem.cpp
-@@ -42,7 +42,6 @@ extern http::server::CWebServerHelper m_
- #include "../hardware/plugins/PluginMessages.h"
- #include "EventsPythonModule.h"
- #include "EventsPythonDevice.h"
--extern PyObject * PDevice_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
- #endif
-
- // Helper table for Blockly and SQL name mapping
-@@ -275,7 +274,7 @@ void CEventSystem::LoadEvents()
- {
- s = dzv_Dir + eitem.Name + ".lua";
- _log.Log(LOG_STATUS, "dzVents: Write file: %s", s.c_str());
-- FILE *fOut = fopen(s.c_str(), "wb+");
-+ FILE* fOut = fopen(s.c_str(), "wb+");
- if (fOut)
- {
- fwrite(eitem.Actions.c_str(), 1, eitem.Actions.size(), fOut);
---- a/main/EventsPythonDevice.cpp
-+++ b/main/EventsPythonDevice.cpp
-@@ -14,15 +14,21 @@
- Py_XDECREF(self->n_value_string);
- Py_XDECREF(self->s_value);
- Py_XDECREF(self->last_update_string);
-- Py_TYPE(self)->tp_free((PyObject*)self);
-- }
-+
-+ PyTypeObject* pType = (PyTypeObject*)PyObject_Type((PyObject*)self);
-+ freefunc pFree = (freefunc)PyType_GetSlot(pType, Py_tp_free);
-+ pFree((PyObject*)self);
-+ Py_XDECREF(pType);
-+ }
-
- PyObject *
- PDevice_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
- {
- PDevice *self;
-
-- self = (PDevice *)type->tp_alloc(type, 0);
-+ allocfunc pAlloc = (allocfunc)PyType_GetSlot(type, Py_tp_alloc);
-+ self = (PDevice*)pAlloc(type, 0);
-+
- if (self != nullptr)
- {
- self->name = PyUnicode_FromString("");
---- a/main/EventsPythonDevice.h
-+++ b/main/EventsPythonDevice.h
-@@ -47,7 +47,7 @@
-
- static PyModuleDef PDevicemodule = { PyModuleDef_HEAD_INIT,
- "DomoticzEvents",
-- "Example module that creates an extension type.",
-+ "DomoticzEvents module type.",
- -1,
- nullptr,
- nullptr,
-@@ -55,44 +55,6 @@
- nullptr,
- nullptr };
-
-- static PyTypeObject PDeviceType = {
-- PyVarObject_HEAD_INIT(nullptr, 0) "DomoticzEvents.PDevice", /* tp_name */
-- sizeof(PDevice), /* tp_basicsize */
-- 0, /* tp_itemsize */
-- (destructor)PDevice_dealloc, /* tp_dealloc */
-- 0, /* tp_print */
-- 0, /* tp_getattr */
-- 0, /* tp_setattr */
-- 0, /* tp_reserved */
-- 0, /* tp_repr */
-- 0, /* tp_as_number */
-- 0, /* tp_as_sequence */
-- 0, /* tp_as_mapping */
-- 0, /* tp_hash */
-- 0, /* tp_call */
-- 0, /* tp_str */
-- 0, /* tp_getattro */
-- 0, /* tp_setattro */
-- 0, /* tp_as_buffer */
-- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
-- "PDevice objects", /* tp_doc */
-- 0, /* tp_traverse */
-- 0, /* tp_clear */
-- 0, /* tp_richcompare */
-- 0, /* tp_weaklistoffset */
-- 0, /* tp_iter */
-- 0, /* tp_iternext */
-- PDevice_methods, /* tp_methods */
-- PDevice_members, /* tp_members */
-- 0, /* tp_getset */
-- 0, /* tp_base */
-- 0, /* tp_dict */
-- 0, /* tp_descr_get */
-- 0, /* tp_descr_set */
-- 0, /* tp_dictoffset */
-- (initproc)PDevice_init, /* tp_init */
-- 0, /* tp_alloc */
-- PDevice_new, /* tp_new */
-- };
-+ static PyObject* PDeviceType;
- }
- #endif
---- a/main/EventsPythonModule.cpp
-+++ b/main/EventsPythonModule.cpp
-@@ -6,22 +6,27 @@
- #include "EventSystem.h"
- #include "mainworker.h"
- #include "localtime_r.h"
-+#include "../hardware/plugins/Plugins.h"
-
--#ifdef ENABLE_PYTHON
--
-- namespace Plugins {
-- #define GETSTATE(m) ((struct eventModule_state*)PyModule_GetState(m))
-+#include <fstream>
-
-- void* m_PyInterpreter;
-- bool ModuleInitialized = false;
-+#ifdef ENABLE_PYTHON
-
-- struct eventModule_state {
-- PyObject* error;
-- };
--
-- static PyMethodDef DomoticzEventsMethods[] = { { "Log", PyDomoticz_EventsLog, METH_VARARGS, "Write message to Domoticz log." },
-- { "Command", PyDomoticz_EventsCommand, METH_VARARGS, "Schedule a command." },
-- { nullptr, nullptr, 0, nullptr } };
-+namespace Plugins
-+{
-+#define GETSTATE(m) ((struct eventModule_state*)PyModule_GetState(m))
-+
-+ void* m_PyInterpreter;
-+ bool ModuleInitialized = false;
-+
-+ struct eventModule_state {
-+ PyObject* error;
-+ };
-+
-+ static PyMethodDef DomoticzEventsMethods[] = {
-+ { "Log", PyDomoticz_EventsLog, METH_VARARGS, "Write message to Domoticz log." },
-+ { "Command", PyDomoticz_EventsCommand, METH_VARARGS, "Schedule a command." },
-+ { nullptr, nullptr, 0, nullptr } };
-
- static int DomoticzEventsTraverse(PyObject *m, visitproc visit, void *arg)
- {
-@@ -44,7 +49,6 @@
- if (!PyArg_ParseTuple(args, "s", &msg))
- {
- _log.Log(LOG_ERROR, "Pyhton Event System: Failed to parse parameters: string expected.");
-- // LogPythonException(pModState->pPlugin, std::string(__func__));
- }
- else
- {
-@@ -52,8 +56,7 @@
- _log.Log((_eLogLevel)LOG_NORM, message);
- }
-
-- Py_INCREF(Py_None);
-- return Py_None;
-+ Py_RETURN_NONE;
- }
-
- static PyObject *PyDomoticz_EventsCommand(PyObject *self, PyObject *args)
-@@ -68,7 +71,6 @@
- if (!PyArg_ParseTuple(args, "ss", &device, &action))
- {
- _log.Log(LOG_ERROR, "Pyhton EventSystem: Failed to parse parameters: Two strings expected.");
-- // LogPythonException(pModState->pPlugin, std::string(__func__));
- }
- else
- {
-@@ -78,13 +80,20 @@
- m_mainworker.m_eventsystem.PythonScheduleEvent(device, action, "Test");
- }
-
-- Py_INCREF(Py_None);
-- return Py_None;
-+ Py_RETURN_NONE;
- }
-
-- struct PyModuleDef DomoticzEventsModuleDef
-- = { PyModuleDef_HEAD_INIT, "DomoticzEvents", nullptr, sizeof(struct eventModule_state), DomoticzEventsMethods, nullptr,
-- DomoticzEventsTraverse, DomoticzEventsClear, nullptr };
-+ struct PyModuleDef DomoticzEventsModuleDef = {
-+ PyModuleDef_HEAD_INIT,
-+ "DomoticzEvents",
-+ nullptr,
-+ sizeof(struct eventModule_state),
-+ DomoticzEventsMethods,
-+ nullptr,
-+ DomoticzEventsTraverse,
-+ DomoticzEventsClear,
-+ nullptr
-+ };
-
- PyMODINIT_FUNC PyInit_DomoticzEvents(void)
- {
-@@ -94,6 +103,22 @@
- _log.Log(LOG_STATUS, "Python EventSystem: Initializing event module.");
-
- PyObject *pModule = PyModule_Create2(&DomoticzEventsModuleDef, PYTHON_API_VERSION);
-+
-+ PyType_Slot PDeviceSlots[] = {
-+ { Py_tp_doc, (void*)"PDevice objects" },
-+ { Py_tp_new, (void*)PDevice_new },
-+ { Py_tp_init, (void*)PDevice_init },
-+ { Py_tp_dealloc, (void*)PDevice_dealloc },
-+ { Py_tp_members, PDevice_members },
-+ { Py_tp_methods, PDevice_methods },
-+ { 0, nullptr },
-+ };
-+ PyType_Spec PDeviceSpec = { "DomoticzEvents.PDevice", sizeof(PDevice), 0,
-+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, PDeviceSlots };
-+
-+ PDeviceType = PyType_FromSpec(&PDeviceSpec);
-+ PyModule_AddObject(pModule, "PDevice", (PyObject*)PDeviceType);
-+
- return pModule;
- }
-
-@@ -166,22 +191,21 @@
-
- PyObject *PythonEventsGetModule()
- {
-- PyObject *pModule = PyState_FindModule(&DomoticzEventsModuleDef);
-+ PyBorrowedRef pModule = PyState_FindModule(&DomoticzEventsModuleDef);
-
- if (pModule)
- {
- // _log.Log(LOG_STATUS, "Python Event System: Module found");
- return pModule;
- }
-- Plugins::PyRun_SimpleStringFlags("import DomoticzEvents", nullptr);
-+ PyImport_ImportModule("DomoticzEvents");
- pModule = PyState_FindModule(&DomoticzEventsModuleDef);
-
- if (pModule)
- {
- return pModule;
- }
-- // Py_INCREF(Py_None);
-- // return Py_None;
-+
- return nullptr;
- }
-
-@@ -189,7 +213,70 @@
-
- PyObject *mapToPythonDict(const std::map<std::string, float> &floatMap)
- {
-- return Py_None;
-+ Py_RETURN_NONE;
-+ }
-+
-+ void LogPythonException()
-+ {
-+ PyNewRef pTraceback;
-+ PyNewRef pExcept;
-+ PyNewRef pValue;
-+
-+ PyErr_Fetch(&pExcept, &pValue, &pTraceback);
-+ PyErr_NormalizeException(&pExcept, &pValue, &pTraceback);
-+
-+ if (!pExcept && !pValue && !pTraceback)
-+ {
-+ _log.Log(LOG_ERROR, "Unable to decode exception.");
-+ }
-+ else
-+ {
-+ std::string sTypeText("Unknown");
-+ if (pExcept)
-+ {
-+ PyTypeObject* TypeName = (PyTypeObject*)pExcept;
-+ PyNewRef pName = PyObject_GetAttrString((PyObject*)TypeName, "__name__");
-+ sTypeText = (std::string)pName;
-+ }
-+
-+ /* See if we can get a full traceback */
-+ PyNewRef pModule = PyImport_ImportModule("traceback");
-+ if (pModule)
-+ {
-+ PyNewRef pFunc = PyObject_GetAttrString(pModule, "format_exception");
-+ if (pFunc && PyCallable_Check(pFunc)) {
-+ PyNewRef pList = PyObject_CallFunctionObjArgs(pFunc, pExcept, pValue, pTraceback, NULL);
-+ if (pList)
-+ {
-+ for (Py_ssize_t i = 0; i < PyList_Size(pList); i++)
-+ {
-+ PyBorrowedRef pPyStr = PyList_GetItem(pList, i);
-+ std::string pStr(pPyStr);
-+ size_t pos = 0;
-+ std::string token;
-+ while ((pos = pStr.find('\n')) != std::string::npos) {
-+ token = pStr.substr(0, pos);
-+ _log.Log(LOG_ERROR, "%s", token.c_str());
-+ pStr.erase(0, pos + 1);
-+ }
-+ }
-+ }
-+ else
-+ {
-+ _log.Log(LOG_ERROR, "Exception: '%s'. No traceback available.", sTypeText.c_str());
-+ }
-+ }
-+ else
-+ {
-+ _log.Log(LOG_ERROR, "'format_exception' lookup failed, exception: '%s'. No traceback available.", sTypeText.c_str());
-+ }
-+ }
-+ else
-+ {
-+ _log.Log(LOG_ERROR, "'Traceback' module import failed, exception: '%s'. No traceback available.", sTypeText.c_str());
-+ }
-+ }
-+ PyErr_Clear();
- }
-
- void PythonEventsProcessPython(const std::string &reason, const std::string &filename, const std::string &PyString,
-@@ -202,22 +289,15 @@
- return;
- }
-
-- if (Plugins::Py_IsInitialized())
-+ if (Py_IsInitialized())
- {
--
- if (m_PyInterpreter)
- PyEval_RestoreThread((PyThreadState *)m_PyInterpreter);
-
-- /*{
-- _log.Log(LOG_ERROR, "EventSystem - Python: Failed to attach to interpreter");
-- }*/
--
-- PyObject *pModule = Plugins::PythonEventsGetModule();
-+ PyBorrowedRef pModule = PythonEventsGetModule();
- if (pModule)
- {
--
-- PyObject *pModuleDict = Plugins::PyModule_GetDict((PyObject *)pModule); // borrowed referece
--
-+ PyBorrowedRef pModuleDict = Plugins::PyModule_GetDict(pModule);
- if (!pModuleDict)
- {
- _log.Log(LOG_ERROR, "Python EventSystem: Failed to open module dictionary.");
-@@ -225,26 +305,22 @@
- return;
- }
-
-- if (Plugins::PyDict_SetItemString(
-- pModuleDict, "changed_device_name",
-- Plugins::PyUnicode_FromString(m_devicestates[DeviceID].deviceName.c_str()))
-- == -1)
-+ PyNewRef pStrVal = PyUnicode_FromString(m_devicestates[DeviceID].deviceName.c_str());
-+ if (PyDict_SetItemString(pModuleDict, "changed_device_name", pStrVal) == -1)
- {
- _log.Log(LOG_ERROR, "Python EventSystem: Failed to set changed_device_name.");
- return;
- }
-
-- PyObject *m_DeviceDict = Plugins::PyDict_New();
--
-- if (Plugins::PyDict_SetItemString(pModuleDict, "Devices", (PyObject *)m_DeviceDict) == -1)
-+ PyNewRef pDeviceDict = Plugins::PyDict_New();
-+ if (PyDict_SetItemString(pModuleDict, "Devices", pDeviceDict) == -1)
- {
- _log.Log(LOG_ERROR, "Python EventSystem: Failed to add Device dictionary.");
- PyEval_SaveThread();
- return;
- }
-- Py_DECREF(m_DeviceDict);
-
-- if (Plugins::PyType_Ready(&Plugins::PDeviceType) < 0)
-+ if (PyType_Ready((PyTypeObject*)Plugins::PDeviceType) < 0)
- {
- _log.Log(LOG_ERROR, "Python EventSystem: Unable to ready DeviceType Object.");
- PyEval_SaveThread();
-@@ -261,13 +337,12 @@
- // sitem.subType, sitem.switchtype, sitem.nValue, sitem.nValueWording, sitem.sValue,
- // sitem.lastUpdate); devices[sitem.deviceName] = deviceStatus;
-
-- Plugins::PDevice *aDevice = (Plugins::PDevice *)Plugins::PDevice_new(
-- &Plugins::PDeviceType, (PyObject *)nullptr, (PyObject *)nullptr);
-- PyObject *pKey = Plugins::PyUnicode_FromString(sitem.deviceName.c_str());
-+ PDevice *aDevice = (PDevice *)PDevice_new((PyTypeObject*)PDeviceType, (PyObject *)nullptr, (PyObject *)nullptr);
-+ PyNewRef pKey = PyUnicode_FromString(sitem.deviceName.c_str());
-
- if (sitem.ID == DeviceID)
- {
-- if (Plugins::PyDict_SetItemString(pModuleDict, "changed_device", (PyObject *)aDevice) == -1)
-+ if (PyDict_SetItemString(pModuleDict, "changed_device", (PyObject *)aDevice) == -1)
- {
- _log.Log(LOG_ERROR,
- "Python EventSystem: Failed to add device '%s' as changed_device.",
-@@ -275,7 +350,7 @@
- }
- }
-
-- if (Plugins::PyDict_SetItem((PyObject *)m_DeviceDict, pKey, (PyObject *)aDevice) == -1)
-+ if (PyDict_SetItem(pDeviceDict, pKey, (PyObject *)aDevice) == -1)
- {
- _log.Log(LOG_ERROR, "Python EventSystem: Failed to add device '%s' to device dictionary.",
- sitem.deviceName.c_str());
-@@ -291,19 +366,18 @@
- // If nValueWording contains %, unicode fails?
-
- aDevice->id = static_cast<int>(sitem.ID);
-- aDevice->name = Plugins::PyUnicode_FromString(sitem.deviceName.c_str());
-+ aDevice->name = PyUnicode_FromString(sitem.deviceName.c_str());
- aDevice->type = sitem.devType;
- aDevice->sub_type = sitem.subType;
- aDevice->switch_type = sitem.switchtype;
- aDevice->n_value = sitem.nValue;
-- aDevice->n_value_string = Plugins::PyUnicode_FromString(temp_n_value_string.c_str());
-+ aDevice->n_value_string = PyUnicode_FromString(temp_n_value_string.c_str());
- aDevice->s_value = Plugins::PyUnicode_FromString(sitem.sValue.c_str());
-- aDevice->last_update_string = Plugins::PyUnicode_FromString(sitem.lastUpdate.c_str());
-+ aDevice->last_update_string = PyUnicode_FromString(sitem.lastUpdate.c_str());
- // _log.Log(LOG_STATUS, "Python EventSystem: deviceName %s added to device dictionary",
- // sitem.deviceName.c_str());
- }
- Py_DECREF(aDevice);
-- Py_DECREF(pKey);
- }
- // devicestatesMutexLock1.unlock();
-
-@@ -315,28 +389,24 @@
- localtime_r(&now, <ime);
- int minutesSinceMidnight = (ltime.tm_hour * 60) + ltime.tm_min;
-
-- if (Plugins::PyDict_SetItemString(pModuleDict, "minutes_since_midnight",
-- Plugins::PyLong_FromLong(minutesSinceMidnight))
-- == -1)
-+ PyNewRef pPyLong = PyLong_FromLong(minutesSinceMidnight);
-+ if (PyDict_SetItemString(pModuleDict, "minutes_since_midnight", pPyLong) == -1)
- {
- _log.Log(LOG_ERROR, "Python EventSystem: Failed to add 'minutesSinceMidnight' to module_dict");
- }
-
-- if (Plugins::PyDict_SetItemString(pModuleDict, "sunrise_in_minutes", Plugins::PyLong_FromLong(intSunRise))
-- == -1)
-+ pPyLong = PyLong_FromLong(intSunRise);
-+ if (PyDict_SetItemString(pModuleDict, "sunrise_in_minutes", pPyLong) == -1)
- {
- _log.Log(LOG_ERROR, "Python EventSystem: Failed to add 'sunrise_in_minutes' to module_dict");
- }
-
-- if (Plugins::PyDict_SetItemString(pModuleDict, "sunset_in_minutes", Plugins::PyLong_FromLong(intSunSet))
-- == -1)
-+ pPyLong = PyLong_FromLong(intSunSet);
-+ if (PyDict_SetItemString(pModuleDict, "sunset_in_minutes", pPyLong) == -1)
- {
- _log.Log(LOG_ERROR, "Python EventSystem: Failed to add 'sunset_in_minutes' to module_dict");
- }
--
-- // PyObject* dayTimeBool = Py_False;
-- // PyObject* nightTimeBool = Py_False;
--
-+
- bool isDaytime = false;
- bool isNightime = false;
-
-@@ -349,75 +419,121 @@
- isNightime = true;
- }
-
-- if (Plugins::PyDict_SetItemString(pModuleDict, "is_daytime", Plugins::PyBool_FromLong(isDaytime)) == -1)
-+ PyNewRef pPyBool = PyBool_FromLong(isDaytime);
-+ if (PyDict_SetItemString(pModuleDict, "is_daytime", pPyBool) == -1)
- {
- _log.Log(LOG_ERROR, "Python EventSystem: Failed to add 'is_daytime' to module_dict");
- }
-
-- if (Plugins::PyDict_SetItemString(pModuleDict, "is_nighttime", Plugins::PyBool_FromLong(isNightime)) == -1)
-+ pPyBool = PyBool_FromLong(isNightime);
-+ if (PyDict_SetItemString(pModuleDict, "is_nighttime", pPyBool) == -1)
- {
- _log.Log(LOG_ERROR, "Python EventSystem: Failed to add 'is_daytime' to module_dict");
- }
-
- // UserVariables
-- PyObject *m_uservariablesDict = Plugins::PyDict_New();
--
-- if (Plugins::PyDict_SetItemString(pModuleDict, "user_variables", (PyObject *)m_uservariablesDict) == -1)
-+ PyNewRef userVariablesDict = PyDict_New();
-+ if (PyDict_SetItemString(pModuleDict, "user_variables", userVariablesDict) == -1)
- {
- _log.Log(LOG_ERROR, "Python EventSystem: Failed to add uservariables dictionary.");
- PyEval_SaveThread();
- return;
- }
-- Py_DECREF(m_uservariablesDict);
--
-- // This doesn't work
-- // boost::unique_lock<boost::shared_mutex> uservariablesMutexLock2 (m_uservariablesMutex);
-
- for (auto it_var = m_uservariables.begin(); it_var != m_uservariables.end(); ++it_var)
- {
- CEventSystem::_tUserVariable uvitem = it_var->second;
-- Plugins::PyDict_SetItemString(m_uservariablesDict, uvitem.variableName.c_str(),
-- Plugins::PyUnicode_FromString(uvitem.variableValue.c_str()));
-+ PyDict_SetItemString(userVariablesDict, uvitem.variableName.c_str(),
-+ PyUnicode_FromString(uvitem.variableValue.c_str()));
- }
-
-- // uservariablesMutexLock2.unlock();
--
- // Add __main__ module
-- PyObject *pModule = Plugins::PyImport_AddModule("__main__");
-- Py_INCREF(pModule);
-+ PyBorrowedRef pMainModule = PyImport_AddModule("__main__");
-+ PyBorrowedRef global_dict = PyModule_GetDict(pMainModule);
-+ PyNewRef local_dict = PyDict_New();
-
- // Override sys.stderr
-- Plugins::PyRun_SimpleStringFlags("import sys\nclass StdErrRedirect:\n def __init__(self):\n "
-- "self.buffer = ''\n def write(self, "
-- "msg):\n self.buffer += msg\nstdErrRedirect = "
-- "StdErrRedirect()\nsys.stderr = stdErrRedirect\n",
-- nullptr);
-+ {
-+ PyNewRef pCode = Py_CompileString("import sys\nclass StdErrRedirect:\n def __init__(self):\n "
-+ "self.buffer = ''\n def write(self, "
-+ "msg):\n self.buffer += msg\nstdErrRedirect = "
-+ "StdErrRedirect()\nsys.stderr = stdErrRedirect\n",
-+ filename.c_str(), Py_file_input);
-+ if (pCode)
-+ {
-+ PyNewRef pEval = PyEval_EvalCode(pCode, global_dict, local_dict);
-+ }
-+ else
-+ {
-+ _log.Log(LOG_ERROR, "EventSystem: Failed to compile stderror redirection for event script '%s'", reason.c_str());
-+ }
-+ }
-
-- if (PyString.length() > 0)
-+ if (!PyErr_Occurred() && (PyString.length() > 0))
- {
- // Python-string from WebEditor
-- Plugins::PyRun_SimpleStringFlags(PyString.c_str(), nullptr);
-+ PyNewRef pCode = Py_CompileString(PyString.c_str(), filename.c_str(), Py_file_input);
-+ if (pCode)
-+ {
-+ PyNewRef pEval = PyEval_EvalCode(pCode, global_dict, local_dict);
-+ }
-+ else
-+ {
-+ _log.Log(LOG_ERROR, "EventSystem: Failed to compile python '%s' event script '%s'", reason.c_str(), filename.c_str());
-+ }
- }
- else
- {
- // Script-file
-- FILE *PythonScriptFile = fopen(filename.c_str(), "r");
-- Plugins::PyRun_SimpleFileExFlags(PythonScriptFile, filename.c_str(), 0, nullptr);
-+ std::ifstream PythonScriptFile(filename.c_str());
-+ if (PythonScriptFile.is_open())
-+ {
-+ char PyLine[256];
-+ std::string PyString;
-+ while (PythonScriptFile.getline(PyLine, sizeof(PyLine), '\n'))
-+ {
-+ PyString.append(PyLine);
-+ PyString += '\n';
-+ }
-+ PythonScriptFile.close();
-+
-+ PyNewRef pCode = Py_CompileString(PyString.c_str(), filename.c_str(), Py_file_input);
-+ if (pCode)
-+ {
-+ PyNewRef pEval = PyEval_EvalCode(pCode, global_dict, local_dict);
-+ }
-+ else
-+ {
-+ _log.Log(LOG_ERROR, "EventSystem: Failed to compile python '%s' event script file '%s'", reason.c_str(), filename.c_str());
-+ }
-+ }
-+ else
-+ {
-+ _log.Log(LOG_ERROR, "EventSystem: Failed to open python script file '%s'", filename.c_str());
-+ }
-+ }
-
-- if (PythonScriptFile != nullptr)
-- fclose(PythonScriptFile);
-+ // Log any exceptions
-+ if (PyErr_Occurred())
-+ {
-+ LogPythonException();
- }
-
- // Get message from stderr redirect
-- PyObject *stdErrRedirect = nullptr, *logBuffer = nullptr, *logBytes = nullptr;
- std::string logString;
-- if ((stdErrRedirect = Plugins::PyObject_GetAttrString(pModule, "stdErrRedirect")) == nullptr)
-- goto free_module;
-- if ((logBuffer = Plugins::PyObject_GetAttrString(stdErrRedirect, "buffer")) == nullptr)
-- goto free_stderrredirect;
-- if ((logBytes = PyUnicode_AsUTF8String(logBuffer)) == nullptr)
-- goto free_logbuffer;
-- logString.append(PyBytes_AsString(logBytes));
-+ if (PyObject_HasAttrString(pModule, "stdErrRedirect"))
-+ {
-+ PyNewRef stdErrRedirect = PyObject_GetAttrString(pModule, "stdErrRedirect");
-+ if (PyObject_HasAttrString(stdErrRedirect, "buffer"))
-+ {
-+ PyNewRef logBuffer = PyObject_GetAttrString(stdErrRedirect, "buffer");
-+ PyNewRef logBytes = PyUnicode_AsUTF8String(logBuffer);
-+ if (logBytes)
-+ {
-+ logString.append(PyBytes_AsString(logBytes));
-+ }
-+ }
-+ }
-
- // Check if there were some errors written to stderr
- if (logString.length() > 0)
-@@ -436,15 +552,6 @@
- logString = logString.substr(lineBreakPos + 1);
- }
- }
--
-- // Cleanup
-- Py_DECREF(logBytes);
-- free_logbuffer:
-- Py_DECREF(logBuffer);
-- free_stderrredirect:
-- Py_DECREF(stdErrRedirect);
-- free_module:
-- Py_DECREF(pModule);
- }
- else
- {
-@@ -458,5 +565,5 @@
- _log.Log(LOG_ERROR, "EventSystem: Python not Initialized");
- }
- }
-- } // namespace Plugins
-+} // namespace Plugins
- #endif
---- a/main/SQLHelper.cpp
-+++ b/main/SQLHelper.cpp
-@@ -5226,7 +5226,7 @@ uint64_t CSQLHelper::UpdateValueInt(
- )
- {
- if (
-- (pHardware->HwdType != HTYPE_MQTTAutoDiscovery)
-+ (HWtype != HTYPE_MQTTAutoDiscovery)
- &&
- (switchtype == STYPE_BlindsPercentage
- || switchtype == STYPE_BlindsPercentageWithStop
+++ /dev/null
-From a9df45497dc79023ed1864dd9b8e435935220171 Mon Sep 17 00:00:00 2001
-From: dnpwwo <kendel.boul@gmail.com>
-Date: Tue, 1 Mar 2022 13:09:01 +1100
-Subject: [PATCH] BugFix: Linux crash when formating Python exceptions Other:
- Continue code cleanup
-
----
- hardware/plugins/Plugins.cpp | 45 +++++++++++-------------------------
- hardware/plugins/Plugins.h | 3 ++-
- main/EventsPythonModule.cpp | 6 ++---
- 3 files changed, 18 insertions(+), 36 deletions(-)
-
---- a/hardware/plugins/Plugins.cpp
-+++ b/hardware/plugins/Plugins.cpp
-@@ -724,13 +724,7 @@ namespace Plugins
- }
- else
- {
-- std::string sTypeText("Unknown");
-- if (pExcept)
-- {
-- PyTypeObject* TypeName = (PyTypeObject*)pExcept;
-- PyNewRef pName = PyObject_GetAttrString((PyObject*)TypeName, "__name__");
-- sTypeText = (std::string)pName;
-- }
-+ std::string sTypeText("Unknown Error");
-
- /* See if we can get a full traceback */
- PyNewRef pModule = PyImport_ImportModule("traceback");
-@@ -738,7 +732,7 @@ namespace Plugins
- {
- PyNewRef pFunc = PyObject_GetAttrString(pModule, "format_exception");
- if (pFunc && PyCallable_Check(pFunc)) {
-- PyNewRef pList = PyObject_CallFunctionObjArgs(pFunc, pExcept, pValue, pTraceback, NULL);
-+ PyNewRef pList = PyObject_CallFunctionObjArgs(pFunc, (PyObject*)pExcept, (PyObject*)pValue, (PyObject*)pTraceback, NULL);
- if (pList)
- {
- for (Py_ssize_t i = 0; i < PyList_Size(pList); i++)
-@@ -756,16 +750,19 @@ namespace Plugins
- }
- else
- {
-+ if (pExcept) sTypeText = pExcept.Attribute("__name__");
- Log(LOG_ERROR, "Exception: '%s'. No traceback available.", sTypeText.c_str());
- }
- }
- else
- {
-+ if (pExcept) sTypeText = pExcept.Attribute("__name__");
- Log(LOG_ERROR, "'format_exception' lookup failed, exception: '%s'. No traceback available.", sTypeText.c_str());
- }
- }
- else
- {
-+ if (pExcept) sTypeText = pExcept.Attribute("__name__");
- Log(LOG_ERROR, "'Traceback' module import failed, exception: '%s'. No traceback available.", sTypeText.c_str());
- }
- }
-@@ -1950,7 +1947,7 @@ namespace Plugins
- }
- }
-
-- void CPlugin::Callback(PyObject *pTarget, const std::string &sHandler, PyObject *pParams)
-+ void CPlugin::Callback(PyBorrowedRef& pTarget, const std::string &sHandler, PyObject *pParams)
- {
- try
- {
-@@ -1966,19 +1963,8 @@ namespace Plugins
- PyNewRef pFunc = PyObject_GetAttrString(pTarget, sHandler.c_str());
- if (pFunc && PyCallable_Check(pFunc))
- {
-- module_state *pModState = nullptr;
-- PyBorrowedRef brModule = PyState_FindModule(&DomoticzModuleDef);
-- if (!brModule)
-- {
-- brModule = PyState_FindModule(&DomoticzExModuleDef);
-- }
--
-- if (brModule)
-- {
-- pModState = ((struct module_state *)PyModule_GetState(brModule));
-- }
--
- // Store the callback object so the Dump function has context if invoked
-+ module_state* pModState = FindModule();
- if (pModState)
- {
- pModState->lastCallback = pTarget;
-@@ -1986,14 +1972,12 @@ namespace Plugins
-
- if (m_bDebug & PDM_QUEUE)
- {
-- PyNewRef pName = PyObject_GetAttrString((PyObject*)(pTarget->ob_type), "__name__");
-- if (pName)
-- Log(LOG_NORM, "Calling message handler '%s' on '%s' type object.", sHandler.c_str(), (std::string(pName).c_str()));
-+ Log(LOG_NORM, "Calling message handler '%s' on '%s' type object.", sHandler.c_str(), pTarget.Type().c_str());
- }
-
- PyErr_Clear();
-
-- // Invokde the callback function
-+ // Invoke the callback function
- PyNewRef pReturnValue = PyObject_CallObject(pFunc, pParams);
-
- if (pModState)
-@@ -2020,17 +2004,14 @@ namespace Plugins
- std::string sAttrName = pItem;
- if (sAttrName.substr(0, 2) != "__") // ignore system stuff
- {
-- if (PyObject_HasAttrString(pTarget, sAttrName.c_str()))
-+ std::string strValue = pTarget.Attribute(sAttrName);
-+ if (strValue.length())
- {
- PyNewRef pValue = PyObject_GetAttrString(pTarget, sAttrName.c_str());
- if (!PyCallable_Check(pValue)) // Filter out methods
- {
-- std::string strValue = pValue;
-- if (strValue.length())
-- {
-- std::string sBlank((sAttrName.length() < 20) ? 20 - sAttrName.length() : 0, ' ');
-- Log(LOG_NORM, " ----> '%s'%s '%s'", sAttrName.c_str(), sBlank.c_str(), strValue.c_str());
-- }
-+ std::string sBlank((sAttrName.length() < 20) ? 20 - sAttrName.length() : 0, ' ');
-+ Log(LOG_NORM, " ----> '%s'%s '%s'", sAttrName.c_str(), sBlank.c_str(), strValue.c_str());
- }
- }
- }
---- a/hardware/plugins/Plugins.h
-+++ b/hardware/plugins/Plugins.h
-@@ -92,7 +92,7 @@ namespace Plugins {
- void ConnectionWrite(CDirectiveBase *);
- void ConnectionDisconnect(CDirectiveBase *);
- void DisconnectEvent(CEventBase *);
-- void Callback(PyObject* pTarget, const std::string &sHandler, PyObject *pParams);
-+ void Callback(PyBorrowedRef& pTarget, const std::string &sHandler, PyObject *pParams);
- void RestoreThread();
- void ReleaseThread();
- void Stop();
-@@ -157,6 +157,7 @@ namespace Plugins {
- m_pObject = pObject;
- };
- std::string Attribute(const char* name);
-+ std::string Attribute(std::string& name) { return Attribute(name.c_str()); };
- std::string Type();
- bool IsDict() { return TypeCheck(Py_TPFLAGS_DICT_SUBCLASS); };
- bool IsList() { return TypeCheck(Py_TPFLAGS_LIST_SUBCLASS); };
---- a/main/EventsPythonModule.cpp
-+++ b/main/EventsPythonModule.cpp
-@@ -297,7 +297,7 @@ namespace Plugins
- PyBorrowedRef pModule = PythonEventsGetModule();
- if (pModule)
- {
-- PyBorrowedRef pModuleDict = Plugins::PyModule_GetDict(pModule);
-+ PyBorrowedRef pModuleDict = PyModule_GetDict(pModule);
- if (!pModuleDict)
- {
- _log.Log(LOG_ERROR, "Python EventSystem: Failed to open module dictionary.");
-@@ -312,7 +312,7 @@ namespace Plugins
- return;
- }
-
-- PyNewRef pDeviceDict = Plugins::PyDict_New();
-+ PyNewRef pDeviceDict = PyDict_New();
- if (PyDict_SetItemString(pModuleDict, "Devices", pDeviceDict) == -1)
- {
- _log.Log(LOG_ERROR, "Python EventSystem: Failed to add Device dictionary.");
-@@ -320,7 +320,7 @@ namespace Plugins
- return;
- }
-
-- if (PyType_Ready((PyTypeObject*)Plugins::PDeviceType) < 0)
-+ if (PyType_Ready((PyTypeObject*)PDeviceType) < 0)
- {
- _log.Log(LOG_ERROR, "Python EventSystem: Unable to ready DeviceType Object.");
- PyEval_SaveThread();
+++ /dev/null
-From 90e683a16ec1f267d3efd1b3fd1bff0b9ac9691e Mon Sep 17 00:00:00 2001
-From: dnpwwo <kendel.boul@gmail.com>
-Date: Tue, 1 Mar 2022 22:01:14 +1100
-Subject: [PATCH] BugFix: Prevent crash processing Python exceptions on Linux.
- Uplift: Create Device objects using Python rather than C++
-
----
- main/EventsPythonDevice.h | 2 +-
- main/EventsPythonModule.cpp | 92 ++++++++++++++++---------------------
- 2 files changed, 40 insertions(+), 54 deletions(-)
-
---- a/main/EventsPythonDevice.h
-+++ b/main/EventsPythonDevice.h
-@@ -55,6 +55,6 @@
- nullptr,
- nullptr };
-
-- static PyObject* PDeviceType;
-+ static PyTypeObject* PDeviceType;
- }
- #endif
---- a/main/EventsPythonModule.cpp
-+++ b/main/EventsPythonModule.cpp
-@@ -16,11 +16,11 @@ namespace Plugins
- {
- #define GETSTATE(m) ((struct eventModule_state*)PyModule_GetState(m))
-
-- void* m_PyInterpreter;
-- bool ModuleInitialized = false;
-+ PyThreadState* m_PyInterpreter;
-+ bool m_ModuleInitialized = false;
-
- struct eventModule_state {
-- PyObject* error;
-+ PyObject* error;
- };
-
- static PyMethodDef DomoticzEventsMethods[] = {
-@@ -116,7 +116,7 @@ namespace Plugins
- PyType_Spec PDeviceSpec = { "DomoticzEvents.PDevice", sizeof(PDevice), 0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, PDeviceSlots };
-
-- PDeviceType = PyType_FromSpec(&PDeviceSpec);
-+ PDeviceType = (PyTypeObject*)PyType_FromSpec(&PDeviceSpec);
- PyModule_AddObject(pModule, "PDevice", (PyObject*)PDeviceType);
-
- return pModule;
-@@ -169,7 +169,7 @@ namespace Plugins
- _log.Log(LOG_ERROR, "EventSystem - Python: Failed to initialize module.");
- return false;
- }
-- ModuleInitialized = true;
-+ m_ModuleInitialized = true;
- return true;
- }
-
-@@ -232,12 +232,6 @@ namespace Plugins
- else
- {
- std::string sTypeText("Unknown");
-- if (pExcept)
-- {
-- PyTypeObject* TypeName = (PyTypeObject*)pExcept;
-- PyNewRef pName = PyObject_GetAttrString((PyObject*)TypeName, "__name__");
-- sTypeText = (std::string)pName;
-- }
-
- /* See if we can get a full traceback */
- PyNewRef pModule = PyImport_ImportModule("traceback");
-@@ -245,7 +239,7 @@ namespace Plugins
- {
- PyNewRef pFunc = PyObject_GetAttrString(pModule, "format_exception");
- if (pFunc && PyCallable_Check(pFunc)) {
-- PyNewRef pList = PyObject_CallFunctionObjArgs(pFunc, pExcept, pValue, pTraceback, NULL);
-+ PyNewRef pList = PyObject_CallFunctionObjArgs(pFunc, (PyObject*)pExcept, (PyObject*)pValue, (PyObject*)pTraceback, NULL);
- if (pList)
- {
- for (Py_ssize_t i = 0; i < PyList_Size(pList); i++)
-@@ -263,16 +257,19 @@ namespace Plugins
- }
- else
- {
-+ if (pExcept) sTypeText = pExcept.Attribute("__name__");
- _log.Log(LOG_ERROR, "Exception: '%s'. No traceback available.", sTypeText.c_str());
- }
- }
- else
- {
-+ if (pExcept) sTypeText = pExcept.Attribute("__name__");
- _log.Log(LOG_ERROR, "'format_exception' lookup failed, exception: '%s'. No traceback available.", sTypeText.c_str());
- }
- }
- else
- {
-+ if (pExcept) sTypeText = pExcept.Attribute("__name__");
- _log.Log(LOG_ERROR, "'Traceback' module import failed, exception: '%s'. No traceback available.", sTypeText.c_str());
- }
- }
-@@ -280,11 +277,11 @@ namespace Plugins
- }
-
- void PythonEventsProcessPython(const std::string &reason, const std::string &filename, const std::string &PyString,
-- const uint64_t DeviceID, std::map<uint64_t, CEventSystem::_tDeviceStatus> m_devicestates,
-- std::map<uint64_t, CEventSystem::_tUserVariable> m_uservariables, int intSunRise, int intSunSet)
-+ const uint64_t DeviceID, std::map<uint64_t, CEventSystem::_tDeviceStatus> deviceStates,
-+ std::map<uint64_t, CEventSystem::_tUserVariable> userVariables, int intSunRise, int intSunSet)
- {
-
-- if (!ModuleInitialized)
-+ if (!m_ModuleInitialized)
- {
- return;
- }
-@@ -292,7 +289,7 @@ namespace Plugins
- if (Py_IsInitialized())
- {
- if (m_PyInterpreter)
-- PyEval_RestoreThread((PyThreadState *)m_PyInterpreter);
-+ PyEval_RestoreThread(m_PyInterpreter);
-
- PyBorrowedRef pModule = PythonEventsGetModule();
- if (pModule)
-@@ -305,7 +302,7 @@ namespace Plugins
- return;
- }
-
-- PyNewRef pStrVal = PyUnicode_FromString(m_devicestates[DeviceID].deviceName.c_str());
-+ PyNewRef pStrVal = PyUnicode_FromString(deviceStates[DeviceID].deviceName.c_str());
- if (PyDict_SetItemString(pModuleDict, "changed_device_name", pStrVal) == -1)
- {
- _log.Log(LOG_ERROR, "Python EventSystem: Failed to set changed_device_name.");
-@@ -327,22 +324,34 @@ namespace Plugins
- return;
- }
-
-- // Mutex
-- // boost::shared_lock<boost::shared_mutex> devicestatesMutexLock1(m_devicestatesMutex);
--
-- for (auto it_type = m_devicestates.begin(); it_type != m_devicestates.end(); ++it_type)
-+ for (auto it_type = deviceStates.begin(); it_type != deviceStates.end(); ++it_type)
- {
- CEventSystem::_tDeviceStatus sitem = it_type->second;
-- // object deviceStatus = domoticz_module.attr("Device")(sitem.ID, sitem.deviceName, sitem.devType,
-- // sitem.subType, sitem.switchtype, sitem.nValue, sitem.nValueWording, sitem.sValue,
-- // sitem.lastUpdate); devices[sitem.deviceName] = deviceStatus;
-
-- PDevice *aDevice = (PDevice *)PDevice_new((PyTypeObject*)PDeviceType, (PyObject *)nullptr, (PyObject *)nullptr);
-- PyNewRef pKey = PyUnicode_FromString(sitem.deviceName.c_str());
-+ PyNewRef nrArgList = Py_BuildValue("(iOiiiOiOO)", static_cast<int>(sitem.ID),
-+ PyUnicode_FromString(sitem.deviceName.c_str()),
-+ sitem.devType,
-+ sitem.subType,
-+ sitem.switchtype,
-+ PyUnicode_FromString(sitem.sValue.c_str()),
-+ sitem.nValue,
-+ PyUnicode_FromString(sitem.nValueWording.c_str()),
-+ PyUnicode_FromString(sitem.lastUpdate.c_str()));
-+ if (!nrArgList)
-+ {
-+ _log.Log(LOG_ERROR, "Python EventSystem: Building device argument list failed for key %s.", sitem.deviceName.c_str());
-+ continue;
-+ }
-+ PyNewRef pDevice = PyObject_CallObject((PyObject*)PDeviceType, nrArgList);
-+ if (!pDevice)
-+ {
-+ _log.Log(LOG_ERROR, "Python EventSystem: Event Device object creation failed for key %s.", sitem.deviceName.c_str());
-+ continue;
-+ }
-
- if (sitem.ID == DeviceID)
- {
-- if (PyDict_SetItemString(pModuleDict, "changed_device", (PyObject *)aDevice) == -1)
-+ if (PyDict_SetItemString(pModuleDict, "changed_device", (PyObject *)pDevice) == -1)
- {
- _log.Log(LOG_ERROR,
- "Python EventSystem: Failed to add device '%s' as changed_device.",
-@@ -350,36 +359,13 @@ namespace Plugins
- }
- }
-
-- if (PyDict_SetItem(pDeviceDict, pKey, (PyObject *)aDevice) == -1)
-+ PyNewRef pKey = PyUnicode_FromString(sitem.deviceName.c_str());
-+ if (PyDict_SetItem(pDeviceDict, pKey, (PyObject *)pDevice) == -1)
- {
- _log.Log(LOG_ERROR, "Python EventSystem: Failed to add device '%s' to device dictionary.",
- sitem.deviceName.c_str());
- }
-- else
-- {
--
-- // _log.Log(LOG_ERROR, "Python EventSystem: nValueWording '%s' - done. ",
-- // sitem.nValueWording.c_str());
--
-- std::string temp_n_value_string = sitem.nValueWording;
--
-- // If nValueWording contains %, unicode fails?
--
-- aDevice->id = static_cast<int>(sitem.ID);
-- aDevice->name = PyUnicode_FromString(sitem.deviceName.c_str());
-- aDevice->type = sitem.devType;
-- aDevice->sub_type = sitem.subType;
-- aDevice->switch_type = sitem.switchtype;
-- aDevice->n_value = sitem.nValue;
-- aDevice->n_value_string = PyUnicode_FromString(temp_n_value_string.c_str());
-- aDevice->s_value = Plugins::PyUnicode_FromString(sitem.sValue.c_str());
-- aDevice->last_update_string = PyUnicode_FromString(sitem.lastUpdate.c_str());
-- // _log.Log(LOG_STATUS, "Python EventSystem: deviceName %s added to device dictionary",
-- // sitem.deviceName.c_str());
-- }
-- Py_DECREF(aDevice);
- }
-- // devicestatesMutexLock1.unlock();
-
- // Time related
-
-@@ -440,7 +426,7 @@ namespace Plugins
- return;
- }
-
-- for (auto it_var = m_uservariables.begin(); it_var != m_uservariables.end(); ++it_var)
-+ for (auto it_var = userVariables.begin(); it_var != userVariables.end(); ++it_var)
- {
- CEventSystem::_tUserVariable uvitem = it_var->second;
- PyDict_SetItemString(userVariablesDict, uvitem.variableName.c_str(),
+++ /dev/null
-From fff4bef553cfd75030d473b3296ade88b3150909 Mon Sep 17 00:00:00 2001
-From: Rob Peters <Info@Domoticz.com>
-Date: Thu, 10 Mar 2022 07:09:18 +0100
-Subject: [PATCH] Fixed compile error when PYTHON was disabled (Fixes #5187)
-
----
- hardware/plugins/DelayedLink.h | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
---- a/hardware/plugins/DelayedLink.h
-+++ b/hardware/plugins/DelayedLink.h
-@@ -1,5 +1,5 @@
- #pragma once
--
-+#ifdef ENABLE_PYTHON
- #ifdef WIN32
- # define MS_NO_COREDLL 1
- #else
-@@ -574,3 +574,4 @@ static inline void py3__Py_XDECREF(PyObj
- #endif
- #pragma pop_macro("_DEBUG")
- } // namespace Plugins
-+#endif //#ifdef ENABLE_PYTHON
+++ /dev/null
-From ca4578980e373543d0561564863718c879fa7743 Mon Sep 17 00:00:00 2001
-From: Rob Peters <Info@Domoticz.com>
-Date: Thu, 10 Mar 2022 12:32:29 +0100
-Subject: [PATCH] Making sure code can be compiled without Python
-
----
- hardware/plugins/Plugins.h | 4 ++++
- hardware/plugins/PythonObjects.h | 1 +
- 2 files changed, 5 insertions(+)
-
---- a/hardware/plugins/Plugins.h
-+++ b/hardware/plugins/Plugins.h
-@@ -1,5 +1,7 @@
- #pragma once
-
-+#ifdef ENABLE_PYTHON
-+
- #include "../DomoticzHardware.h"
- #include "../hardwaretypes.h"
- #include "../../notifications/NotificationBase.h"
-@@ -300,3 +302,5 @@ namespace Plugins {
- };
-
- } // namespace Plugins
-+
-+#endif //#ifdef ENABLE_PYTHON
---- a/hardware/plugins/PythonObjects.h
-+++ b/hardware/plugins/PythonObjects.h
-@@ -169,3 +169,4 @@ namespace Plugins {
- };
-
- } // namespace Plugins
-+
--- /dev/null
+# SPDX-License-Identifier: GPL-3.0-only
+#
+# Copyright (C) 2023 Facundo Acevedo
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=dysk
+PKG_VERSION:=2.8.2
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://codeload.github.com/Canop/dysk/tar.gz/v$(PKG_VERSION)?
+PKG_HASH:=3e0f3a470539721748d7bc1acc867bdddcb824695b2f766e3a1f230ebac28c2c
+
+PKG_MAINTAINER:=Facundo Acevedo <facevedo@disroot.org>
+PKG_LICENSE:=MIT
+PKG_LICENSE_FILES:=LICENCE
+
+PKG_BUILD_DEPENDS:=rust/host
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+include ../../lang/rust/rust-package.mk
+
+define Package/dysk
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Utility for efficient file and directory management
+ DEPENDS:=$(RUST_ARCH_DEPENDS)
+ URL:=https://dystroy.org/dysk
+endef
+
+define Package/dysk/description
+ Dysk is a command-line tool designed for efficient file and
+ directory management in Unix-like environments. It offers a
+ streamlined approach to organizing and manipulating files,
+ potentially simplifying various file-related tasks.
+endef
+
+$(eval $(call RustBinPackage,dysk))
+$(eval $(call BuildPackage,dysk))
include $(INCLUDE_DIR)/kernel.mk
PKG_NAME:=fuse3
-PKG_VERSION:=3.10.5
-PKG_RELEASE:=2
+PKG_VERSION:=3.16.2
+PKG_RELEASE:=1
-PKG_SOURCE:=fuse-$(PKG_VERSION).tar.xz
+PKG_SOURCE:=fuse-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://github.com/libfuse/libfuse/releases/download/fuse-$(PKG_VERSION)
-PKG_HASH:=b2e283485d47404ac896dd0bb7f7ba81e1470838e677e45f659804c3a3b69666
+PKG_HASH:=f797055d9296b275e981f5f62d4e32e089614fc253d1ef2985851025b8a0ce87
PKG_BUILD_DIR:=$(BUILD_DIR)/fuse-$(PKG_VERSION)
PKG_MAINTAINER:=
PKG_CPE_ID:=cpe:/a:fuse_project:fuse
+PKG_CONFIG_DEPENDS:=CONFIG_PACKAGE_fuse3-utils
+
include $(INCLUDE_DIR)/package.mk
include $(INCLUDE_DIR)/meson.mk
--- /dev/null
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=fx
+PKG_VERSION:=31.0.0
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://codeload.github.com/antonmedv/fx/tar.gz/$(PKG_VERSION)?
+PKG_HASH:=8408047ef42506aac44aa805de209dd64ae4fc084e76bee8e24112ffbdc2d5dc
+
+PKG_MAINTAINER:=Fabian Lipken <dynasticorpheus@gmail.com>
+PKG_LICENSE:=MIT
+PKG_LICENSE_FILES:=LICENSE
+
+PKG_BUILD_DEPENDS:=golang/host
+PKG_BUILD_PARALLEL:=1
+PKG_BUILD_FLAGS:=no-mips16
+
+GO_PKG:=github.com/antonmedv/fx
+
+include $(INCLUDE_DIR)/package.mk
+include ../../lang/golang/golang-package.mk
+
+define Package/fx
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Terminal JSON viewer & processor
+ URL:=https://github.com/antonmedv/fx/
+ DEPENDS:=$(GO_ARCH_DEPENDS)
+endef
+
+define Package/fx/description
+ Fx is a dual-purpose command-line tool tailored for JSON, providing
+ both a terminal-based JSON viewer and a JSON processing utility.
+endef
+
+$(eval $(call GoBinPackage,fx))
+$(eval $(call BuildPackage,fx))
--- /dev/null
+choice
+ depends on PACKAGE_gl-puli-mcu
+
+ prompt "GL.iNet target"
+ default GL_PULI_MCU_XE300
+
+ config GL_PULI_MCU_XE300
+ bool "GL.iNet XE300 (Puli)"
+
+ config GL_PULI_MCU_XE3000
+ bool "GL.iNet XE3000 (Puli AX)"
+endchoice
include $(TOPDIR)/rules.mk
PKG_NAME:=gl-puli-mcu
-PKG_VERSION:=1
+PKG_VERSION:=2
PKG_RELEASE:=1
PKG_MAINTAINER:=Nuno Goncalves <nunojpg@gmail.com>
PKG_LICENSE:=GPL-3.0-or-later
+PKG_CONFIG_DEPENDS:= \
+ CONFIG_GL_PULI_MCU_XE300 \
+ CONFIG_GL_PULI_MCU_XE3000
+
include $(INCLUDE_DIR)/package.mk
include $(INCLUDE_DIR)/cmake.mk
+define Package/gl-puli-mcu/config
+ source "$(SOURCE)/Config.in"
+endef
+
define Package/gl-puli-mcu
SECTION:=utils
CATEGORY:=Utilities
- TITLE:=GL.iNet GL-XE300 (Puli) power monitoring support
- DEPENDS:=+kmod-usb-serial-ch341 +libubus +libubox
+ TITLE:=GL.iNet power monitoring support
+ DEPENDS:=+CONFIG_GL_PULI_MCU_XE300:kmod-usb-serial-ch341 +libubus +libubox
+ MENU:=1
endef
+ifeq ($(CONFIG_GL_PULI_MCU_XE300),y)
+ TARGET_CFLAGS+=-DGL_TARGET=1
+endif
+ifeq ($(CONFIG_GL_PULI_MCU_XE3000),y)
+ TARGET_CFLAGS+=-DGL_TARGET=2
+endif
+
define Package/gl-puli-mcu/description
- Interfaces with GL-XE300 (Puli) power monitoring MCU over
+ Interfaces with GL.iNet Puli family power monitoring MCU over
a USB to UART adapter present on the device and provides
battery SOC, temperature, charging state and cycle count at
ubus battery/info.
#include <libubox/uloop.h>
#include <libubus.h>
+#define GL_TARGET_XE300 1
+#define GL_TARGET_XE3000 2
+
+#if GL_TARGET == GL_TARGET_XE300
+#define MCU_PORT "/dev/ttyUSB0"
+#elif GL_TARGET == GL_TARGET_XE3000
+#define MCU_PORT "/dev/ttyS1"
+#else
+#error Please define GL_TARGET!
+#endif /* GL_TARGET */
+
static struct ustream_fd stream;
static struct ubus_auto_conn conn;
static struct blob_buf b;
bool set;
} battery;
+#if GL_TARGET == GL_TARGET_XE300
+// MCU status returns something like:
+// {OK},100,275,1,0
static bool
process(char *read)
{
return false;
return true;
}
+#elif GL_TARGET == GL_TARGET_XE3000
+static bool
+get_int_value(const char *read, const char *key, int *int_value, char **new_end)
+{
+ char *from = NULL;
+
+ from = strstr(read, key);
+ if ((!from) || (from != read))
+ {
+ return false;
+ }
+ from = (char *)read + strlen(key);
+ *int_value = strtol(from, new_end, 10);
+ if (from == *new_end)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// MCU status returns something like:
+// {"code":0,"capacity":100,"temp":28,"chg_state":1,"charge_cycle":0}
+static bool
+process(char *read)
+{
+ int int_value = 0;
+ char *to = NULL;
+
+ if ((read[0] != '{') ||
+ (!get_int_value(&read[1], "\"code\":", &int_value, &to)) ||
+ (int_value != 0))
+ {
+ return false;
+ }
+ if (!get_int_value(to + 1, "\"capacity\":", &int_value, &to))
+ {
+ return false;
+ }
+ battery.soc = int_value;
+ if (!get_int_value(to + 1, "\"temp\":", &int_value, &to))
+ {
+ return false;
+ }
+ battery.temperature = (float) int_value;
+ if (!get_int_value(to + 1, "\"chg_state\":", &int_value, &to))
+ {
+ return false;
+ }
+ battery.charging = (bool) int_value;
+ if (!get_int_value(to + 1, "\"charge_cycle\":", &int_value, &to))
+ {
+ return false;
+ }
+ battery.cycles = (uint16_t) int_value;
+
+ return true;
+}
+#endif /* GL_TARGET */
static int
consume(struct ustream *s, char **a)
battery.set = process(*a);
if (!battery.set)
- ULOG_ERR("failed to parse message from serial: %s", a);
+ ULOG_ERR("failed to parse message from serial: %s", *a);
ustream_consume(s, eol - *a);
*a = eol;
conn.cb = ubus_connect_handler;
ubus_auto_connect(&conn);
- if (serial_open("/dev/ttyUSB0") < 0)
+ if (serial_open(MCU_PORT) < 0)
return -1;
serial_query_timer.cb = serial_query_handler;
PKG_NAME:=gummiboot
PKG_VERSION:=48.1
-PKG_RELEASE:=1
+PKG_RELEASE:=2
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://dev.alpinelinux.org/archive/gummiboot/
--- /dev/null
+--- a/src/efi/console.c
++++ b/src/efi/console.c
+@@ -21,63 +21,10 @@
+ #include "util.h"
+ #include "console.h"
+
+-#define EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID \
+- { 0xdd9e7534, 0x7762, 0x4698, { 0x8c, 0x14, 0xf5, 0x85, 0x17, 0xa6, 0x25, 0xaa } }
+-
+ struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL;
+
+-typedef EFI_STATUS (EFIAPI *EFI_INPUT_RESET_EX)(
+- struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This;
+- BOOLEAN ExtendedVerification;
+-);
+-
+ typedef UINT8 EFI_KEY_TOGGLE_STATE;
+
+-typedef struct {
+- UINT32 KeyShiftState;
+- EFI_KEY_TOGGLE_STATE KeyToggleState;
+-} EFI_KEY_STATE;
+-
+-typedef struct {
+- EFI_INPUT_KEY Key;
+- EFI_KEY_STATE KeyState;
+-} EFI_KEY_DATA;
+-
+-typedef EFI_STATUS (EFIAPI *EFI_INPUT_READ_KEY_EX)(
+- struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This;
+- EFI_KEY_DATA *KeyData;
+-);
+-
+-typedef EFI_STATUS (EFIAPI *EFI_SET_STATE)(
+- struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This;
+- EFI_KEY_TOGGLE_STATE *KeyToggleState;
+-);
+-
+-typedef EFI_STATUS (EFIAPI *EFI_KEY_NOTIFY_FUNCTION)(
+- EFI_KEY_DATA *KeyData;
+-);
+-
+-typedef EFI_STATUS (EFIAPI *EFI_REGISTER_KEYSTROKE_NOTIFY)(
+- struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This;
+- EFI_KEY_DATA KeyData;
+- EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction;
+- VOID **NotifyHandle;
+-);
+-
+-typedef EFI_STATUS (EFIAPI *EFI_UNREGISTER_KEYSTROKE_NOTIFY)(
+- struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This;
+- VOID *NotificationHandle;
+-);
+-
+-typedef struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL {
+- EFI_INPUT_RESET_EX Reset;
+- EFI_INPUT_READ_KEY_EX ReadKeyStrokeEx;
+- EFI_EVENT WaitForKeyEx;
+- EFI_SET_STATE SetState;
+- EFI_REGISTER_KEYSTROKE_NOTIFY RegisterKeyNotify;
+- EFI_UNREGISTER_KEYSTROKE_NOTIFY UnregisterKeyNotify;
+-} EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL;
+-
+ EFI_STATUS console_key_read(UINT64 *key, BOOLEAN wait) {
+ EFI_GUID EfiSimpleTextInputExProtocolGuid = EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID;
+ static EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TextInputEx;
include $(TOPDIR)/rules.mk
PKG_NAME:=irqbalance
-PKG_VERSION:=1.9.2
-PKG_RELEASE:=3
+PKG_VERSION:=1.9.3
+PKG_RELEASE:=1
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL:=https://github.com/Irqbalance/irqbalance.git
PKG_SOURCE_VERSION:=v$(PKG_VERSION)
-PKG_MIRROR_HASH:=e2c81725e7b6d711a47d68755a222236d7081726d567aca1c1295e6fe1caa865
+PKG_MIRROR_HASH:=ff2936e9b7486e802206cbf9e16aa6cb7e1501bdf502441d31f409d104e757b8
PKG_MAINTAINER:=Hannu Nyman <hannu.nyman@iki.fi>
PKG_LICENSE:=GPL-2.0-or-later
+++ /dev/null
-From bbcd9a42c3cec0935b960b7f2046f1fdfab4f7ef Mon Sep 17 00:00:00 2001
-From: Vignesh Raghavendra <vigneshr@ti.com>
-Date: Wed, 7 Dec 2022 19:46:19 +0530
-Subject: [PATCH] procinterrupts: Fix IRQ name parsing on certain arm64 SoC
-
-On arm64 SoCs like TI's K3 SoC and few other SoCs, IRQ names don't get
-parsed correct due to which they end up being classified into wrong
-class. Fix this by considering last token to contain IRQ name always.
-
-Eg.: /proc/interrupt
-
-cat /proc/interrupts
- CPU0 CPU1 CPU2 CPU3
- 11: 7155 8882 7235 7791 GICv3 30 Level arch_timer
- 14: 0 0 0 0 GICv3 23 Level arm-pmu
- 15: 0 0 0 0 GICv3 208 Level 4b00000.spi
- 16: 0 0 0 0 GICv3 209 Level 4b10000.spi
-116: 0 0 0 0 MSI-INTA 1716234 Level 485c0100.dma-controller chan6
-134: 166 0 0 0 MSI-INTA 1970707 Level 8000000.ethernet-tx0
-224: 149 0 0 0 MSI-INTA 1971731 Level 8000000.ethernet
-
-W/o patch irqbalance -d
-IRQ (11) guessed as class 0
-IRQ (14) guessed as class 0
-IRQ (15) guessed as class 0
-IRQ (16) guessed as class 0
-IRQ 485c0100.dma-controller chan6(116) guessed as class 0
-IRQ (134) guessed as class 0
-IRQ (224) guessed as class 0
-
-W/ this patch
-IRQ arch_timer(11) guessed as class 0
-IRQ arm-pmu(14) guessed as class 0
-IRQ 4b00000.spi(15) guessed as class 0
-IRQ 4b10000.spi(16) guessed as class 0
-IRQ 485c0100.dma-controller chan6(116) guessed as class 0
-IRQ 8000000.ethernet-tx0(134) guessed as class 5
-IRQ 8000000.ethernet(224) guessed as class 5
-IRQ 8000000.ethernet(257) guessed as class 5
-IRQ -davinci_gpio wl18xx(362) guessed as class
-
-Signed-off-by: Vignesh Raghavendra <vigneshr@ti.com>
----
- procinterrupts.c | 12 +++++++-----
- 1 file changed, 7 insertions(+), 5 deletions(-)
-
---- a/procinterrupts.c
-+++ b/procinterrupts.c
-@@ -178,12 +178,14 @@ void init_irq_class_and_type(char *saved
- }
-
- #ifdef AARCH64
-- if (savedptr && strlen(savedptr) > 0) {
-+ if (savedptr && strlen(savedptr) > 0)
- snprintf(irq_fullname, PATH_MAX, "%s %s", last_token, savedptr);
-- tmp = strchr(irq_fullname, '\n');
-- if (tmp)
-- *tmp = 0;
-- }
-+ else
-+ snprintf(irq_fullname, PATH_MAX, "%s", last_token);
-+
-+ tmp = strchr(irq_fullname, '\n');
-+ if (tmp)
-+ *tmp = 0;
- #else
- snprintf(irq_fullname, PATH_MAX, "%s", last_token);
- #endif
include $(TOPDIR)/rules.mk
PKG_NAME:=mc
-PKG_VERSION:=4.8.27
-PKG_RELEASE:=3
+PKG_VERSION:=4.8.30
+PKG_RELEASE:=1
PKG_MAINTAINER:=
PKG_LICENSE:=GPL-3.0-or-later
PKG_CPE_ID:=cpe:/a:midnight_commander:midnight_commander
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
PKG_SOURCE_URL:=http://ftp.midnight-commander.org/
-PKG_HASH:=31be59225ffa9920816e9a8b3be0ab225a16d19e4faf46890f25bdffa02a4ff4
+PKG_HASH:=5ebc3cb2144b970c5149fda556c4ad50b78780494696cdf2d14a53204c95c7df
PKG_BUILD_PARALLEL:=1
PKG_FIXUP:=autoreconf gettext-version
PKG_BUILD_DEPENDS:=MC_VFS:libtirpc
--enable-silent-rules \
--disable-tests \
--disable-doxygen-doc \
- --with-homedir=/etc/mc \
--with-screen=ncurses \
--without-x \
$(INSTALL_BIN) $(PKG_BUILD_DIR)/src/mc $(1)/usr/bin
$(INSTALL_DIR) $(1)/etc/mc
$(INSTALL_DATA) $(PKG_BUILD_DIR)/misc/mc.charsets $(1)/etc/mc
- $(INSTALL_DATA) $(PKG_BUILD_DIR)/misc/mc.ext $(1)/etc/mc
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/misc/mc.ext.ini $(1)/etc/mc
$(INSTALL_DATA) $(PKG_BUILD_DIR)/misc/mc.default.keymap $(1)/etc/mc/mc.keymap
$(INSTALL_DATA) $(PKG_BUILD_DIR)/misc/filehighlight.ini $(1)/etc/mc
$(INSTALL_DIR) $(1)/usr/share/mc/help
--- a/src/subshell/common.c
+++ b/src/subshell/common.c
-@@ -1140,7 +1140,7 @@ init_subshell_precmd (char *precmd, size
+@@ -1143,7 +1143,7 @@ init_subshell_precmd (char *precmd, size
"else "
"[ \"${PWD##$HOME/}\" = \"$PWD\" ] && MC_PWD=\"$PWD\" || MC_PWD=\"~/${PWD##$HOME/}\"; "
"fi; "
--- a/lib/tty/tty.c
+++ b/lib/tty/tty.c
-@@ -402,7 +402,7 @@ tty_init_xterm_support (gboolean is_xter
+@@ -407,7 +407,7 @@ tty_init_xterm_support (gboolean is_xter
if (xmouse_seq != NULL)
{
if (strcmp (xmouse_seq, ESC_STR "[<") == 0)
--- a/lib/shell.c
+++ b/lib/shell.c
-@@ -68,6 +68,8 @@ mc_shell_get_installed_in_system (void)
+@@ -70,6 +70,8 @@ mc_shell_get_installed_in_system (void)
mc_shell->path = g_strdup ("/bin/bash");
else if (access ("/bin/ash", X_OK) == 0)
mc_shell->path = g_strdup ("/bin/ash");
else if (access ("/bin/dash", X_OK) == 0)
mc_shell->path = g_strdup ("/bin/dash");
else if (access ("/bin/busybox", X_OK) == 0)
-@@ -149,6 +151,12 @@ mc_shell_recognize_real_path (mc_shell_t
+@@ -151,6 +153,12 @@ mc_shell_recognize_real_path (mc_shell_t
mc_shell->type = SHELL_ZSH;
mc_shell->name = "zsh";
}
SHELL_FISH
--- a/src/subshell/common.c
+++ b/src/subshell/common.c
-@@ -378,6 +378,11 @@ init_subshell_child (const char *pty_nam
+@@ -380,6 +380,11 @@ init_subshell_child (const char *pty_nam
}
break;
/* TODO: Find a way to pass initfile to TCSH and FISH */
case SHELL_TCSH:
case SHELL_FISH:
-@@ -427,6 +432,7 @@ init_subshell_child (const char *pty_nam
+@@ -429,6 +434,7 @@ init_subshell_child (const char *pty_nam
case SHELL_ASH_BUSYBOX:
case SHELL_DASH:
case SHELL_TCSH:
case SHELL_FISH:
execl (mc_global.shell->path, mc_global.shell->path, (char *) NULL);
-@@ -1091,6 +1097,10 @@ init_subshell_precmd (char *precmd, size
+@@ -1094,6 +1100,10 @@ init_subshell_precmd (char *precmd, size
"PS1='\\u@\\h:\\w\\$ '\n", command_buffer_pipe[WRITE],
command_buffer_pipe[WRITE], subshell_pipe[WRITE]);
break;
PKG_NAME:=nano
PKG_VERSION:=7.2
-PKG_RELEASE:=2
+PKG_RELEASE:=3
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
PKG_SOURCE_URL:=@GNU/nano
$(INSTALL_DIR) $(1)/etc $(1)/usr/share/nano
$(INSTALL_DATA) ./files/nanorc $(1)/etc/nanorc
$(INSTALL_DATA) ./files/uci.nanorc $(1)/usr/share/nano
+ $(INSTALL_DATA) ./files/ucode.nanorc $(1)/usr/share/nano
$(CP) $(PKG_INSTALL_DIR)/usr/share/nano/* $(1)/usr/share/nano
endef
--- /dev/null
+## Syntax highlighting for OpenWrt ucode scripts.
+
+syntax ucode "/ucode/|\.u[ct]$"
+header "^#!.*\<ucode\>"
+comment "//"
+
+# Declarations
+color green "\<(let|const|function|this)\>"
+
+# Arrow functions
+color green "(\<\w+\>|\([[:alnum:][:space:]_,.]*\))[[:space:]]*=>"
+
+# Flow control and keywords
+color brightyellow "\<(while|if|else|elif|switch|case|default|for|in|endif|endfor|endwhile|endfunction)\>"
+color brightyellow "\<(export|import|try|catch|delete)\>"
+
+# Exit points
+color magenta "\<(break|continue|return)\>"
+
+# Numeric literals
+color cyan "\<([0-9]+\.[0-9]+([eE][+-]?[0-9]+)?|[0-9]+[eE][+-]?[0-9]+)\>"
+color cyan "\<0[xX][[:xdigit:]]+(\.[[:xdigit:]]+)?\>"
+color cyan "\<(0[oO][0-7]+|0[bB][01]+|[0-9]+)\>"
+
+# Special values
+color cyan "\<(true|false|null|NaN|Infinity)\>"
+
+# Strings
+color brightmagenta ""([^"\{%#}]|\\.|\{[^"\{%#]|[%#}][^"\}]|[{%#}]\\.)*[{%#}]?""
+color brightmagenta "'([^'\{%#}]|\\.|\{[^'\{%#]|[%#}][^'\}]|[{%#}]\\.)*[{%#}]?'"
+color brightmagenta "`([^`\{%#}]|\\.|\{[^`\{%#]|[%#}][^`\}]|[{%#}]\\.)*[{%#}]?`"
+
+# Template string expressions
+color normal start="\$\{" end="}"
+
+# Comments
+color brightblue "(^|[[:blank:]])//.*"
+color brightblue start="(^|[[:space:]])/\*" end="\*/"
+color brightblue start="\{#" end="#\}"
+
+# Trailing whitespace.
+color ,green "[[:space:]]+$"
+
+# Text outside template directives
+color slate start="[}%#]\}" end="\{[{%#]"
+color slate start="^#!" end="\{[{%#]"
+color slate "^([^{%#}]|\{[^{%#]|[%#}][^}])+\{[{%#]"
+
+# Template tags
+color white "\{[{%][+-]?|-?[%}]\}"
+color brightblue "\{#[+-]?|-?#\}"
PKG_NAME:=pps-tools
PKG_VERSION:=1.0.2
-PKG_RELEASE:=1
+PKG_RELEASE:=2
PKG_SOURCE_URL:=https://codeload.github.com/redlab-i/pps-tools/tar.gz/v$(PKG_VERSION)?
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
--- /dev/null
+--- a/ppstest.c
++++ b/ppstest.c
+@@ -110,13 +110,13 @@ retry:
+ }
+
+ printf("source %d - "
+- "assert %ld.%09ld, sequence: %ld - "
+- "clear %ld.%09ld, sequence: %ld\n",
++ "assert %lld.%09ld, sequence: %ld - "
++ "clear %lld.%09ld, sequence: %ld\n",
+ i,
+- infobuf.assert_timestamp.tv_sec,
++ (long long)infobuf.assert_timestamp.tv_sec,
+ infobuf.assert_timestamp.tv_nsec,
+ infobuf.assert_sequence,
+- infobuf.clear_timestamp.tv_sec,
++ (long long)infobuf.clear_timestamp.tv_sec,
+ infobuf.clear_timestamp.tv_nsec, infobuf.clear_sequence);
+ fflush(stdout);
+
+--- a/ppswatch.c
++++ b/ppswatch.c
+@@ -145,7 +145,7 @@ int fetch_source(pps_handle_t handle, in
+ if (max_divergence < div)
+ max_divergence = div;
+ if (div >= margin) {
+- printf("timestamp: %ld, sequence: %ld, offset: % 6ld\n", ts.tv_sec, seq, ts.tv_nsec);
++ printf("timestamp: %lld, sequence: %ld, offset: % 6ld\n", (long long)ts.tv_sec, seq, ts.tv_nsec);
+ fflush(stdout);
+ overflows++;
+ curr_unsync++;
include $(TOPDIR)/rules.mk
PKG_NAME:=sockread
-PKG_VERSION:=1.0
-PKG_RELEASE:=2
+PKG_VERSION:=1.1
+PKG_RELEASE:=1
PKG_LICENSE:=CC0-1.0
include $(INCLUDE_DIR)/package.mk
define Package/sockread
SECTION:=utils
CATEGORY:=Utilities
- TITLE:=sockread
+ TITLE:=Unix domain sockets utility
MAINTAINER:=Moritz Warning <moritzwarning@web.de>
endef
define Package/sockread/description
- sockread writes and reads data from a Unix domain socket
- represented as a special file on the file system.
+ Command line utility to read and write to Unix domain sockets.
endef
define Build/Prepare
#include <sys/socket.h>
#include <sys/un.h>
-int main(int argc, char *argv[]) {
- char buf[1024];
- ssize_t r;
-
- if (argc != 2) {
- fprintf(stderr, "Write to and read from a Unix domain socket.\n\nUsage: %s <socket>\n", argv[0]);
- return 1;
- }
-
- size_t addrlen = strlen(argv[1]);
-
- /* Allocate enough space for arbitrary-length paths */
- char addrbuf[offsetof(struct sockaddr_un, sun_path) + addrlen + 1];
- memset(addrbuf, 0, sizeof(addrbuf));
-
- struct sockaddr_un *addr = (struct sockaddr_un *)addrbuf;
- addr->sun_family = AF_UNIX;
- memcpy(addr->sun_path, argv[1], addrlen+1);
-
- int fd = socket(AF_UNIX, SOCK_STREAM, 0);
- if (fd < 0) {
- fprintf(stderr, "Failed to create socket: %s\n", strerror(errno));
- return 1;
- }
-
- if (connect(fd, (struct sockaddr*)addr, sizeof(addrbuf)) < 0) {
- fprintf(stderr, "Can't connect to `%s': %s\n", argv[1], strerror(errno));
- return 1;
- }
-
- /* Check if stdin refers to a terminal */
- if (!isatty(fileno(stdin))) {
- /* Read from stdin and write to socket */
- while (0 < (r = fread(buf, 1, sizeof(buf), stdin))) {
- send(fd, buf, r, 0);
- }
- }
-
- /* Read from socket and write to stdout */
- while (1) {
- r = recv(fd, buf, sizeof(buf), 0);
- if (r < 0) {
- fprintf(stderr, "read: %s\n", strerror(errno));
- return 1;
- }
-
- if (r == 0)
- return 0;
-
- fwrite(buf, r, 1, stdout);
- }
-
- return 0;
+const char *usage =
+ "Write to and read from a Unix domain socket.\n"
+ "Add commands to send as arguments or pass by pipe.\n"
+ "\n"
+ "Usage: sockread <path> [<commands>]\n";
+
+int main(int argc, char *argv[])
+{
+ char buffer[1024];
+ ssize_t r;
+
+ if (argc < 2) {
+ fprintf(stderr, "%s", usage);
+ return EXIT_FAILURE;
+ }
+
+ struct sockaddr_un address = {0};
+ address.sun_family = AF_UNIX;
+ strcpy((char*) &address.sun_path, argv[1]);
+
+ int sock = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (sock < 0) {
+ fprintf(stderr, "socket() %s\n", strerror(errno));
+ return EXIT_FAILURE;
+ }
+
+ if (connect(sock, (struct sockaddr*)&address, sizeof(address)) < 0) {
+ fprintf(stderr, "connect() %s\n", strerror(errno));
+ return EXIT_FAILURE;
+ }
+
+ /* Check if stdin refers to a terminal */
+ if (!isatty(fileno(stdin))) {
+ /* Read from stdin and write to socket */
+ while (0 < (r = fread(buffer, 1, sizeof(buffer), stdin))) {
+ send(sock, buffer, r, 0);
+ }
+ } else {
+ for (size_t i = 2; i < argc; i++) {
+ if (i > 2) {
+ send(sock, " ", 1, 0);
+ }
+ send(sock, argv[i], strlen(argv[i]), 0);
+ }
+ }
+
+ /* Read from socket and write to stdout */
+ while (1) {
+ r = recv(sock, buffer, sizeof(buffer), 0);
+ if (r < 0) {
+ fprintf(stderr, "recv() %s\n", strerror(errno));
+ return EXIT_FAILURE;
+ }
+
+ if (r == 0)
+ break;
+
+ fwrite(buffer, r, 1, stdout);
+ }
+
+ return EXIT_SUCCESS;
}
PKG_NAME:=tang
PKG_VERSION:=14
-PKG_RELEASE:=3
+PKG_RELEASE:=4
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
PKG_SOURCE_URL:=https://github.com/latchset/$(PKG_NAME)/releases/download/v$(PKG_VERSION)/
PKG_HASH:=04263ed1cc98d60cab29fe47f908921b7b1aa4d6da5f9de2fcbe543773b75886
-PKG_MAINTAINER:=Tibor Dudlák <tibor.dudlak@gmail.com>
+PKG_MAINTAINER:=Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
PKG_LICENSE:=GPL-3.0-or-later
PKG_LICENSE_FILES:=COPYING
if [ -z "${KEYS}" ] || [ "${KEYS}" = "0" ]; then # if db is empty generate new key pair
mkdir -p /usr/share/tang/db
/usr/sbin/tangd-keygen /usr/share/tang/db
+ chown -R tang /usr/share/tang/db
fi
config_load "tang"
include $(TOPDIR)/rules.mk
PKG_NAME:=yq
-PKG_VERSION:=4.35.2
+PKG_VERSION:=4.40.3
PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://codeload.github.com/mikefarah/yq/tar.gz/v$(PKG_VERSION)?
-PKG_HASH:=8b17d710c56f764e9beff06d7a7b1c77d87c4ba4219ce4ce67e7ee29670f4f13
+PKG_HASH:=238b695d372753a32bc0b8500a7ca99f98cf98d7855c3e84d6984a2b035b6268
PKG_MAINTAINER:=Tianling Shen <cnsztl@immortalwrt.org>
PKG_LICENSE:=MIT