diff --git a/windows/nzbget-setup.nsi b/windows/nzbget-setup.nsi
index ca5551657..8fb473cda 100644
--- a/windows/nzbget-setup.nsi
+++ b/windows/nzbget-setup.nsi
@@ -178,7 +178,7 @@ WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\NZBGet" "U
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\NZBGet" "InstallLocation" "$INSTDIR"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\NZBGet" "Publisher" "nzbget.com"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\NZBGet" "DisplayIcon" "$\"$INSTDIR\nzbget.exe$\",0"
-WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\NZBGet" "DisplayVersion" "23.0"
+WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\NZBGet" "DisplayVersion" "23.1"
${GetSize} "$INSTDIR" "/S=0K" $0 $1 $2
IntFmt $0 "0x%08X" $0
diff --git a/windows/resources/nzbget.rc b/windows/resources/nzbget.rc
index 282c55d64..8007f9d94 100644
--- a/windows/resources/nzbget.rc
+++ b/windows/resources/nzbget.rc
@@ -85,7 +85,7 @@ CAPTION "About NZBGet"
FONT 8, "Tahoma", 400, 0, 0x0
BEGIN
DEFPUSHBUTTON "OK",IDOK,63,161,50,14
- CTEXT "Version 23.0",IDC_ABOUT_VERSION,16,70,145,8
+ CTEXT "Version 23.1",IDC_ABOUT_VERSION,16,70,145,8
CTEXT "Lightweight usenet downloader",IDC_STATIC,16,83,145,8
CTEXT "https://nzbget.com",IDC_ABOUT_HOMEPAGE,55,144,64,9,SS_NOTIFY
ICON "",IDC_ABOUT_ICON,67,7,21,20
From 40234499256c06347ef80853fd66d4bf724c3433 Mon Sep 17 00:00:00 2001
From: phnzb <139914799+phnzb@users.noreply.github.com>
Date: Fri, 16 Feb 2024 18:21:41 +0300
Subject: [PATCH 12/42] Update README (#178)
---
README.md | 10 +++-------
1 file changed, 3 insertions(+), 7 deletions(-)
diff --git a/README.md b/README.md
index 6a4356d97..cb0de2c38 100644
--- a/README.md
+++ b/README.md
@@ -36,7 +36,7 @@ More information available at https://nzbget.com
We provide a easy-to-use installer for each platform we support.
Please download binaries from our [releases](https://github.com/nzbgetcom/nzbget/tags) page.
-We also provide a docker image for popular architectures. [Docker readme](docker/README.md)
+Docker images are available for x86-64 / arm64 / armv7 architectures. [Docker readme](docker/README.md)
Synology packages are available as SynoCommunity packages and SPK packages. [Synology readme](synology/README.md)
@@ -52,7 +52,7 @@ QNAP packages are available as native packages and buildroot packages. [QNAP rea
`Windows`: Windows 7 and later, 32 or 64 Bit.
-`Linux`: Linux kernel 2.6 and later, x86 (32 or 64 Bit), ARM 32-bit (armel armhf), ARM 64-bit (aarch64)
+`Linux`: Linux kernel 2.6 and later, x86 (32 or 64 Bit), ARM 32-bit (armel armhf), ARM 64-bit (aarch64), MIPS (mipseb mipsel), PowerPC (ppc6xx ppc500), RISC-V 64-bit (riscv64)
`macOS`: macOS 10.13 High Sierra and later, Intel / Apple Silicon.
@@ -60,11 +60,7 @@ QNAP packages are available as native packages and buildroot packages. [QNAP rea
[General instructions](INSTALLATION.md)
-[Linux cross-compiling / buildroot](linux/build-info.md)
-
-[macOS](osx/build-info.md)
-
-[Synology](synology/build-info.md)
+[Linux](linux/build-info.md) [macOS](osx/build-info.md) [Synology](synology/build-info.md) [QNAP](qnap/build-info.md)
## Contribution
From 0cc6023bfdf7a1d22311dea7d81b8a6ea7a7d880 Mon Sep 17 00:00:00 2001
From: Denis <146707790+dnzbk@users.noreply.github.com>
Date: Wed, 21 Feb 2024 01:16:03 -0800
Subject: [PATCH 13/42] Fix and update links in webui (#177)
- fixed license links
- fixed links from nzbget.conf in webui
---
webui/config.js | 2 +-
webui/index.html | 20 ++++++++++----------
2 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/webui/config.js b/webui/config.js
index b83ad44ef..7c2b4d420 100644
--- a/webui/config.js
+++ b/webui/config.js
@@ -955,7 +955,7 @@ var Config = (new function($)
});
// replace URLs
- exp = /(http:\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig;
+ exp = /(https?:\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig;
htmldescr = htmldescr.replace(exp, "$1 ");
// highlight first line
diff --git a/webui/index.html b/webui/index.html
index 39b435138..2cc18a230 100644
--- a/webui/index.html
+++ b/webui/index.html
@@ -601,27 +601,27 @@ Copyright
Additional exemption: compiling, linking, and/or using OpenSSL is allowed.
Par2
- NZBGet uses Par2 by Peter Brian Clements with library interface by Francois Lesueur.
- Par2 is licensed under the GPL license .
+ NZBGet uses Par2 by Peter Brian Clements with library interface by Francois Lesueur.
+ Par2 is licensed under the GPLv2 license .
jQuery
NZBGet web-interface uses jQuery . The jQuery Project is run by a distributed group of volunteers that all want to see jQuery become the best JavaScript tool possible.
- jQuery is licensed under the MIT and GPL licenses.
+ jQuery is licensed under the MIT license.
Bootstrap
- NZBGet web-interface uses Twitter Bootstrap . Designed and built with all the love in the world @twitter by @mdo and @fat.
- Bootstrap code is licensed under the Apache License v2.0 .
+ NZBGet web-interface uses Bootstrap . Designed and built with all the love in the world @twitter by @mdo and @fat.
+ Bootstrap code is licensed under the Apache License v2.0 .
Raphaël
- NZBGet web-interface makes use of Raphaël built by Dmitry Baranovskiy.
- Raphaël code is licensed under the MIT license .
+ NZBGet web-interface makes use of Raphaël built by Dmitry Baranovskiy.
+ Raphaël code is licensed under the MIT license .
Elycharts
- For charts NZBGet relies on Elycharts by Void Labs s.n.c.
- Elycharts code is licensed under the MIT license .
+ For charts NZBGet relies on Elycharts by Void Labs s.n.c.
+ Elycharts code is licensed under the MIT license .
iconSweets
- NZBGet web-interface includes selected icons from collections iconSweets and iconSweets2 by Yummygum .
+ NZBGet web-interface includes selected icons from collections iconSweets and iconSweets2 by Yummygum .
The icons are generally licensed under a custom license but used in NZBGet with author's permission.
Boost
From 1c03b719f88ece7d67ad348f3aca0d3800ab4d54 Mon Sep 17 00:00:00 2001
From: Denis <146707790+dnzbk@users.noreply.github.com>
Date: Wed, 21 Feb 2024 02:11:49 -0800
Subject: [PATCH 14/42] Fix: new stable/testing release notifications (#181)
- added automatic checking for new testing releases;
- fixed notifications about the new stable/testing release;
- fixed "Uncaught ReferenceError: installedRev" error;
---
nzbget.conf | 3 ++-
webui/config.js | 9 +++------
2 files changed, 5 insertions(+), 7 deletions(-)
diff --git a/nzbget.conf b/nzbget.conf
index 3572addd0..84efd4093 100644
--- a/nzbget.conf
+++ b/nzbget.conf
@@ -439,10 +439,11 @@ AuthorizedIP=
# NOTE: For more details visit https://nzbget.com/documentation/certificate-verification/.
CertCheck=no
-# Automatically check for new releases (none, stable).
+# Automatically check for new releases (none, stable, testing).
#
# None - do not show notifcations;
# Stable - show notifications about new stable releases;
+# Testing - show notifications about new testing releases;
UpdateCheck=stable
# User name for daemon-mode, POSIX only.
diff --git a/webui/config.js b/webui/config.js
index 7c2b4d420..9eace742f 100644
--- a/webui/config.js
+++ b/webui/config.js
@@ -2980,7 +2980,6 @@ var UpdateDialog = (new function($)
var installedVer = installedVersion;
- var installedTesting = installedVersion.indexOf('testing') > -1;
var canInstallStable = UpdateInfo['stable-version'] &&
(installedVer < UpdateInfo['stable-version']);
@@ -3009,11 +3008,9 @@ var UpdateDialog = (new function($)
Util.show('#UpdateDialog_CheckFailed', hasUpdateSource && !hasUpdateInfo);
Util.show('#UpdateDialog_DownloadRow,#UpdateDialog_DownloadAvail', canDownload && !canUpdate);
$('#UpdateDialog_AvailRow').toggleClass('hide', !hasUpdateInfo);
-
- if (!foreground &&
- (((canInstallStable || canDownloadStable) && notificationAllowed('stable')) ||
- (Options.option('UpdateCheck') === 'testing' && installedRev > 0 &&
- (canInstallTesting || canDownloadTesting) && notificationAllowed('testing'))))
+ var canUpdateStable = Options.option('UpdateCheck') === 'stable' && (canInstallStable || canDownloadStable) && notificationAllowed('stable');
+ var canUpdateTesting = Options.option('UpdateCheck') === 'testing' && (canInstallTesting || canDownloadTesting) && notificationAllowed('testing');
+ if (canUpdateStable || canUpdateTesting)
{
$UpdateDialog.modal({backdrop: 'static'});
}
From 56e4225fc73a6d1c7cdc6f647a4cac297e28e9f3 Mon Sep 17 00:00:00 2001
From: Denis <146707790+dnzbk@users.noreply.github.com>
Date: Tue, 5 Mar 2024 02:44:25 -0800
Subject: [PATCH 15/42] Switching to CMake from autotools (#182)
## Description
- switched to CMake from autotools, which will simplify cross-platform development;
- fixed installing/uninstalling on FreeBSD and macOS via autotools/CMake;
- added automatic installation of Boost.Json;
- added Clang-Tidy static code analizer support;
- updated INSTALLATION.md;
## Testing
By @dnzbk:
- Windows 11 x86_64;
- macOS Ventura x86_64;
- FreeBSD 13 x86_64;
- Linux Debian 12 aarch64/x86_64;
By @phnzb
- Linux Debian 12 aarch64
- Ubuntu LTS 22.04 / 20.04 x86_64
- Amazon Linux 2 x86_64
- Cross-compilng Linux armhf
- macOS Mojave
---
.github/workflows/windows-tests.yml | 2 +-
.gitignore | 1 -
CMakeLists.txt | 141 +++++++----
INSTALLATION.md | 257 ++++++++++++++-----
cmake/boost.cmake | 19 ++
cmake/config.h.in | 168 ++++++++++++
cmake/install.cmake | 43 ++++
cmake/posix.cmake | 337 +++++++++++++++++++++++++
cmake/toolchain.cmake | 19 ++
cmake/windows.cmake | 57 +++++
cmake_config.h.in | 5 -
daemon/main/Options.cpp | 1 +
daemon/main/nzbget.h | 13 +-
daemon/sources.cmake | 105 ++++++++
lib/CMakeLists.txt | 45 ----
lib/regex/regex.c | 10 +-
lib/regex/regex.h | 4 +-
lib/sources.cmake | 98 +++++++
tests/extension/CMakeLists.txt | 12 +-
tests/feed/CMakeLists.txt | 10 +-
tests/feed/FeedFileTest.cpp | 4 +-
tests/main/CMakeLists.txt | 11 +-
tests/nntp/CMakeLists.txt | 13 +-
tests/nntp/ServerPoolTest.cpp | 14 +-
tests/postprocess/CMakeLists.txt | 13 +-
tests/postprocess/DirectUnpackTest.cpp | 74 ++++--
tests/queue/CMakeLists.txt | 11 +-
tests/queue/NzbFileTest.cpp | 9 +-
tests/util/CMakeLists.txt | 18 +-
29 files changed, 1226 insertions(+), 288 deletions(-)
create mode 100644 cmake/boost.cmake
create mode 100644 cmake/config.h.in
create mode 100644 cmake/install.cmake
create mode 100644 cmake/posix.cmake
create mode 100644 cmake/toolchain.cmake
create mode 100644 cmake/windows.cmake
delete mode 100644 cmake_config.h.in
create mode 100644 daemon/sources.cmake
delete mode 100644 lib/CMakeLists.txt
create mode 100644 lib/sources.cmake
diff --git a/.github/workflows/windows-tests.yml b/.github/workflows/windows-tests.yml
index a449de7ed..8fed2240d 100644
--- a/.github/workflows/windows-tests.yml
+++ b/.github/workflows/windows-tests.yml
@@ -31,7 +31,7 @@ jobs:
cmake --version
mkdir build
cd build
- cmake .. "-DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake" -DVCPKG_TARGET_TRIPLET=x64-windows-static
+ cmake .. -DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_TARGET_TRIPLET=x64-windows-static -DBUILD_ONLY_TESTS=ON
cmake --build . --config Release -j 2
- name: Test
diff --git a/.gitignore b/.gitignore
index a5d1eec1d..f10cec75f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -26,7 +26,6 @@
# GNU Autotools
.deps/
config.h
-config.h.in
config.h.in~
configure
configure~
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 57f487883..556ff66c6 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,57 +1,112 @@
-cmake_minimum_required(VERSION 3.22)
+cmake_minimum_required(VERSION 3.13)
+
+if (PROJECT_SOURCE_DIR STREQUAL PROJECT_BINARY_DIR)
+ message(FATAL_ERROR "In-source builds are not allowed. You should create separate directory for build files.")
+endif()
+
+set_property(GLOBAL PROPERTY PACKAGE)
+set_property(GLOBAL PROPERTY LIBS)
+set_property(GLOBAL PROPERTY INCLUDES)
set(VERSION "23.1")
+set(PACKAGE "nzbget")
+set(PACKAGE_BUGREPORT "https://github.com/nzbgetcom/nzbget/issues")
+set(CMAKE_CXX_STANDARD 14)
+set(CMAKE_C_STANDARD 11)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+set(CMAKE_C_STANDARD_REQUIRED ON)
+set(CMAKE_CXX_EXTENSIONS OFF)
+set(CMAKE_C_EXTENSIONS OFF)
+set(CMAKE_CONFIGURATION_TYPES "Release" "Debug")
+
+add_compile_definitions(HAVE_CONFIG_H=1)
+
+if(NOT CMAKE_BUILD_TYPE)
+ set(CMAKE_BUILD_TYPE "Release" CACHE STRING "")
+endif()
+
+option(BUILD_ONLY_TESTS "Build only tests (for CI)")
project(
- nzbget
- VERSION ${VERSION}
- DESCRIPTION "NZBGet is a binary downloader, which downloads files from Usenet"
- LANGUAGES C CXX
+ nzbget
+ VERSION ${VERSION}
+ DESCRIPTION "NZBGet is a binary downloader, which downloads files from Usenet"
+ LANGUAGES C CXX
)
-option(ENABLE_TESTS "Enable tests" ON)
+if(CMAKE_BUILD_TYPE STREQUAL "Debug")
+ if(CMAKE_CXX_COMPILER_ID MATCHES "Clang|AppleClang")
+ set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g0 -pthread -g -Weverything -Wno-c++98-compat" CACHE STRING "" FORCE)
+ elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
+ set(CMAKE_CXX_FLAGS "-O0 -g0 -pthread -g -Wall -Wextra" CACHE STRING "" FORCE)
+ elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
+ set(CMAKE_CXX_FLAGS "/Od /Zi /MP /W4 /EHs /DDEBUG /D_DEBUG /DWIN32 /wd4800 /wd4267" CACHE STRING "" FORCE)
+ set(CMAKE_CXX_STANDARD_LIBRARIES "${CMAKE_CXX_STANDARD_LIBRARIES} winmm.lib Dbghelp.lib libcpmtd.lib" CACHE STRING "" FORCE)
+ set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreadedDebug" CACHE STRING "" FORCE)
+ endif()
+elseif(CMAKE_BUILD_TYPE STREQUAL "Release")
+ if(CMAKE_CXX_COMPILER_ID MATCHES "Clang|AppleClang")
+ set(CMAKE_CXX_FLAGS "-O2 -g0 -pthread -DNDEBUG -Weverything -Wno-c++98-compat" CACHE STRING "" FORCE)
+ set(CMAKE_EXE_LINKER_FLAGS_RELEASE "-s" CACHE STRING "" FORCE)
+ elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
+ set(CMAKE_CXX_FLAGS "-O2 -g0 -pthread -DNDEBUG -Wall -Wextra" CACHE STRING "" FORCE)
+ set(CMAKE_EXE_LINKER_FLAGS_RELEASE "-s" CACHE STRING "" FORCE)
+ elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
+ set(CMAKE_CXX_FLAGS "/O2 /MP /W4 /EHs /DNDEBUG /DWIN32 /wd4800 /wd4267" CACHE STRING "" FORCE)
+ set(CMAKE_CXX_STANDARD_LIBRARIES "${CMAKE_CXX_STANDARD_LIBRARIES} winmm.lib" CACHE STRING "" FORCE)
+ set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded" CACHE STRING "" FORCE)
+ endif()
+endif()
+
+set(CMAKE_C_FLAGS_DEBUG ${CMAKE_CXX_FLAGS} CACHE STRING "" FORCE)
+set(CMAKE_C_FLAGS_RELEASE ${CMAKE_CXX_FLAGS} CACHE STRING "" FORCE)
+set(CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS} CACHE STRING "" FORCE)
+set(CMAKE_CXX_FLAGS_RELEASE ${CMAKE_CXX_FLAGS} CACHE STRING "" FORCE)
-set(PACKAGE "nzbget")
-add_compile_definitions(HAVE_CONFIG_H=1)
+include_directories(${CMAKE_BINARY_DIR})
+include_directories(${CMAKE_SOURCE_DIR})
+
+if(NOT BUILD_ONLY_TESTS)
+ include(daemon/sources.cmake)
+ add_executable(${PACKAGE} ${SRC})
+endif()
+
+if(WIN32)
+ include(cmake/windows.cmake)
+ if(NOT BUILD_ONLY_TESTS)
+ target_sources(${PACKAGE} PRIVATE ${CMAKE_SOURCE_DIR}/windows/resources/nzbget.rc)
+ endif()
+else()
+ include(cmake/posix.cmake)
+ if(NOT BUILD_ONLY_TESTS)
+ include(${CMAKE_SOURCE_DIR}/cmake/install.cmake)
+ endif()
+endif()
configure_file(
- ${CMAKE_SOURCE_DIR}/cmake_config.h.in
- ${CMAKE_BINARY_DIR}/config.h
+ ${CMAKE_SOURCE_DIR}/cmake/config.h.in
+ ${CMAKE_BINARY_DIR}/config.h
)
-set(CMAKE_CXX_STANDARD 17)
-set(CMAKE_C_STANDARD 17)
-set(CMAKE_CXX_STANDARD_REQUIRED ON)
-set(CMAKE_C_STANDARD_REQUIRED ON)
-set(CMAKE_CXX_EXTENSIONS OFF)
-set(CMAKE_C_EXTENSIONS OFF)
-set(BUILD_SHARED_LIBS OFF)
-set(OPENSSL_USE_STATIC_LIBS ON)
-set(ZLIB_USE_STATIC_LIBS ON)
-set(Boost_USE_STATIC_LIBS ON)
-set(Boost_USE_MULTITHREADED ON)
-set(Boost_USE_STATIC_RUNTIME OFF)
-set(CMAKE_BUILD_TYPE "Release" CACHE STRING "")
-
-find_package(OpenSSL REQUIRED)
-find_package(ZLIB REQUIRED)
-find_package(LibXml2 REQUIRED)
-find_package(Boost REQUIRED COMPONENTS json)
-
-if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2 -Weverything")
-elseif (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2 -Wall")
-elseif (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /O2 /W4")
- set(CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS} winmm.lib /NODEFAULTLIB:msvcrt.lib;libcmt.lib;msvcrtd.lib")
+if(NOT BUILD_ONLY_TESTS)
+ target_link_libraries(${PACKAGE} PRIVATE ${LIBS})
+ target_include_directories(${PACKAGE} PRIVATE
+ ${CMAKE_SOURCE_DIR}/daemon/connect
+ ${CMAKE_SOURCE_DIR}/daemon/extension
+ ${CMAKE_SOURCE_DIR}/daemon/feed
+ ${CMAKE_SOURCE_DIR}/daemon/frontend
+ ${CMAKE_SOURCE_DIR}/daemon/main
+ ${CMAKE_SOURCE_DIR}/daemon/nntp
+ ${CMAKE_SOURCE_DIR}/daemon/nserv
+ ${CMAKE_SOURCE_DIR}/daemon/postprocess
+ ${CMAKE_SOURCE_DIR}/daemon/queue
+ ${CMAKE_SOURCE_DIR}/daemon/remote
+ ${CMAKE_SOURCE_DIR}/daemon/util
+ ${INCLUDES}
+ )
endif()
-include_directories(lib/regex)
-include_directories(${CMAKE_BINARY_DIR})
-add_subdirectory(lib)
-
-if(ENABLE_TESTS)
- include(CTest)
- add_subdirectory(tests)
+if(ENABLE_TESTS OR BUILD_ONLY_TESTS)
+ include(CTest)
+ add_subdirectory(tests)
endif()
diff --git a/INSTALLATION.md b/INSTALLATION.md
index 2dd0fdefc..1ffac7b1e 100644
--- a/INSTALLATION.md
+++ b/INSTALLATION.md
@@ -58,19 +58,24 @@ If you have downloaded binaries you can just jump to section
NZBGet is developed on a linux-system, but it runs on other
POSIX platforms.
-NZBGet absolutely needs the following libraries:
+To build NZBGet you will need:
- - libstdc++ (usually part of compiler)
+For configuring and building:
+ - [CMake](https://cmake.org/)
+ - [GCC](https://gcc.gnu.org/)
+
+ or
+ - [CLang](https://clang.llvm.org/)
+
+Libraries:
- [libxml2](https://gitlab.gnome.org/GNOME/libxml2/-/wikis/home)
- [Boost.JSON](https://www.boost.org/doc/libs/1_84_0/libs/json/doc/html/index.html)
- - [Boost.Optional](https://www.boost.org/doc/libs/1_84_0/libs/optional/doc/html/index.html)
+> If you face issues with Boost.JSON on your system, you can skip it - CMake will take care of it.
And the following libraries are optional:
For curses-output-mode (enabled by default):
- - libcurses (usually part of commercial systems)
- or (better)
- - [libncurses](https://invisible-island.net/ncurses)
+ - [ncurses](https://invisible-island.net/ncurses)
For encrypted connections (TLS/SSL):
- [OpenSSL](https://www.openssl.org)
@@ -80,60 +85,159 @@ And the following libraries are optional:
For gzip support in web-server and web-client (enabled by default):
- [zlib](https://www.zlib.net/)
-
- For configuration:
- - [autotools](https://www.gnu.org/software/automake/manual/html_node/Autotools-Introduction.html)
- - [autoconf](https://www.gnu.org/software/autoconf/)
-
- For managing package dependencies:
- - [pkg-config](https://www.freedesktop.org/wiki/Software/pkg-config/)
For tests:
- [Boost.Test](https://www.boost.org/doc/libs/1_84_0/libs/test/doc/html/index.html)
-All these libraries are included in modern POSIX distributions and
-should be available as installable packages. Please note that you also
+ For static code analysis:
+ - [Clang-Tidy](https://clang.llvm.org/extra/clang-tidy/)
+
+Please note that you also
need the developer packages for these libraries too, they package names
have often suffix "dev" or "devel". On other systems you may need to
download the libraries at the given URLs and compile them (see hints below).
+### Debian:
+```
+ apt install cmake build-essential libncurses-dev libssl-dev libxml2-dev zlib1g-dev libboost-json1.81-dev
+```
+ - For tests:
+```
+ apt install libboost-test1.81-dev
+```
+ - For static code analysis:
+```
+ apt install clang-tidy
+```
+### FreeBSD:
+```
+ pkg install cmake ncurses openssl libxml2 zlib boost-libs
+```
+### macOS:
+```
+ xcode-select --install
+ brew install cmake ncurses openssl libxml2 zlib boost
+```
+
## 4. Installation on POSIX
Installation from the source distribution archive (nzbget-VERSION.tar.gz):
- - untar the nzbget-source via
- tar -zxf nzbget-VERSION.tar.gz
-
- - change into nzbget-directory via
- cd nzbget-VERSION
-
- - configure it via
-
- autoreconf --install
-
- ./configure
+ - Untar the nzbget-source:
+```
+ tar -zxf nzbget-VERSION.tar.gz
+```
+ - Change into nzbget-directory:
+```
+ cd nzbget-VERSION
+```
+ - Configure:
+```
+ mkdir build
+ cd build
+ cmake ..
+```
+ - In a case you don't have root access or want to install the program
+ in your home directory use the configure parameter -DCMAKE_INSTALL_PREFIX:
+```
+ cmake .. -DCMAKE_INSTALL_PREFIX=~/usr
+```
+ - Build, specifying (-j 8) how many CPU cores to use to speed up compilation:
+```
+ cmake --build . -j 8
+```
+ - Install:
+```
+ cmake --install .
+```
+ - Uninstall:
+```
+ cmake --build . --target uninstall
+```
- (maybe you have to tell configure, where to find some libraries.
- ./configure --help is your friend!
- also see "Configure-options" later)
+### Configure-options
+---------------------
+You may run configure with additional arguments:
+ - Enable tests:
+```
+ cmake .. -DENABLE_TESTS=ON
+```
+ - Enable Clang-Tidy static code analizer:
+```
+ cmake .. -DENABLE_CLANG_TIDY=ON
+```
+ - Disable ncurses. Use this option if you can not use ncurses.
+```
+ cmake .. -DDISABLE_CURSES=ON
+```
+ - Disable parcheck. Use this option if you have troubles when compiling par2-module.
+```
+ cmake .. -DDISABLE_PARCHECK=ON
+```
+ - Use GnuTLS. Use this option if you want to use GnuTLS instead of OpenSSL.
+```
+ cmake .. -DUSE_GNUTLS=ON
+```
+ - Disable TLS. Use this option if you can not neither OpenSSL nor GnuTLS.
+```
+ cmake .. -DDISABLE_TLS=ON
+```
+ - Disable gzip. Use this option if you can not use zlib.
+```
+ cmake .. -DDISABLE_GZIP=ON
+```
+ - Disable sigchld-handler. The disabling may be neccessary on 32-Bit BSD.
+```
+ cmake .. -DDISABLE_SIGCHLD_HANDLER=ON
+```
+ - For debug build.
+```
+ cmake .. -DCMAKE_BUILD_TYPE=Debug
+```
+ - To get a static binary,
+```
+ cmake .. -DENABLE_STATIC=ON
+```
+ `LIBS` and `INCLUDES` env variables can be useful for static linking, since CMake looks for shared libraries by default
+```
+ export LIBS="-lncurses -ltinfo -lboost_json -lxml2 -lz -lm -lssl -lcrypto -Wl,--whole-archive -lpthread -Wl,--no-whole-archive"
+ export INCLUDES="/usr/include/;/usr/include/libxml2/"
+ cmake .. -DENABLE_STATIC=ON
+```
+## Building using autotools (deprecated)
+
+ - configure it via
+```
+ autoreconf --install
+ ./configure
+```
+ (maybe you have to tell configure, where to find some libraries then is your friend!
+```
+ ./configure --help
+```
+ also see "Configure-options" later)
- in a case you don't have root access or want to install the program
in your home directory use the configure parameter --prefix, e. g.:
-
+```
./configure --prefix ~/usr
-
+```
- compile it via
- make
-
+```
+ make
+```
- to install system wide become root via:
- su
-
+```
+ su
+```
- install it via:
- make install
-
+```
+ make install
+```
- install configuration files into /etc via:
- make install-conf
-
+```
+ make install-conf
+```
(you can skip this step if you intend to store configuration
files in a non-standard location)
@@ -143,22 +247,22 @@ You may run configure with additional arguments:
--disable-curses - to make without curses-support. Use this option
if you can not use curses/ncurses.
-
+
--disable-parcheck - to make without parcheck-support. Use this option
if you have troubles when compiling par2-module.
--with-tlslib=(OpenSSL, GnuTLS) - to select which TLS/SSL library
should be used for encrypted server connections.
-
+
--disable-tls - to make without TLS/SSL support. Use this option if
you can not neither OpenSSL nor GnuTLS.
--disable-gzip - to make without gzip support. Use this option
if you can not use zlib.
-
+
--enable-debug - to build in debug-mode, if you want to see and log
debug-messages.
-
+
### Optional package: par-check
-------------------------------
NZBGet can check and repair downloaded files for you. For this purpose
@@ -169,8 +273,9 @@ NZBGet’s source tree and is compiled automatically when you make NZBGet.
In a case errors occur during this process the inclusion of par2-module
can be disabled using configure option "--disable-parcheck":
-
+```
./configure --disable-parcheck
+```
### Optional package: curses
----------------------------
@@ -183,8 +288,9 @@ Following configure-parameters may be useful:
If you are not able to use curses or ncurses or do not want them you can
make the program without support for curses using option "--disable-curses":
-
+```
./configure --disable-curses
+```
### Optional package: TLS
-------------------------
@@ -193,9 +299,10 @@ with TLS/SSL support. NZBGet can use two libraries: OpenSSL or GnuTLS.
Configure-script checks which library is installed and use it. If both are
available it gives the precedence to OpenSSL. You may override that with
the option --with-tlslib=(OpenSSL, GnuTLS). For example to build with GnuTLS:
-
+```
./configure --with-tlslib= GnuTLS
-
+```
+
Following configure-parameters may be useful:
--with-libtls-includess=/path/to/gnutls/includes
@@ -208,29 +315,65 @@ If none of these libraries is available you can make the program without
TLS/SSL support using option "--disable-tls":
./configure --disable-tls
-
+
## 5. Compiling on Windows
-NZBGet is developed using MS Visual Studio 2015 (Community Edition). The project
-file is provided.
+For configuring and building:
+ - [CMake](https://cmake.org/)
+ - [MS C++ Build tools](https://visualstudio.microsoft.com/downloads/?q=build+tools)
-To compile the program with TLS/SSL support you need either OpenSSL or GnuTLS:
+To compile the program with TLS/SSL support you need OpenSSL:
- [OpenSSL](https://www.openssl.org)
- or
- - [GnuTLS](https://gnutls.org/)
-
Also required are:
- - [Regex](https://regexlib.com/)
- [Zlib](https://gnuwin32.sourceforge.net/packages/zlib.htm)
- [libxml2](https://gitlab.gnome.org/GNOME/libxml2/-/wikis/home)
- [Boost.JSON](https://www.boost.org/doc/libs/1_84_0/libs/json/doc/html/index.html)
- [Boost.Optional](https://www.boost.org/doc/libs/1_84_0/libs/optional/doc/html/index.html)
-
For tests:
- [Boost.Test](https://www.boost.org/doc/libs/1_84_0/libs/test/doc/html/index.html)
-We recommend using [vcpkg](https://vcpkg.io/) to install dependencies.
+We recommend using [vcpkg](https://vcpkg.io/) to install dependencies:
+
+```
+ vcpkg install openssl:-windows-static
+ vcpkg install libxml2:-windows-static
+ vcpkg install zlib:-windows-static
+ vcpkg install boost-json:-windows-static
+ vcpkg install boost-optional:-windows-static
+```
+ - For tests:
+```
+ vcpkg install boost-test:-windows-static
+```
+ - Configure:
+```
+ mkdir build
+ cd build
+ cmake .. -DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_TARGET_TRIPLET=x64-windows-static -A x64
+```
+ - For Win32:
+```
+ cmake .. -DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_TARGET_TRIPLET=x86-windows-static -A Win32
+```
+ - For debug build:
+```
+ cmake .. -DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_TARGET_TRIPLET=x64-windows-static -DCMAKE_BUILD_TYPE=Debug
+```
+ - If Debug:
+```
+ cmake --build . --config Debug
+```
+
+You may run configure with additional arguments:
+ - Enable tests:
+```
+ cmake .. -DENABLE_TESTS=ON -DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_TARGET_TRIPLET=x64-windows-static
+```
+ - Disable TLS. Use this option if you can not neither OpenSSL nor GnuTLS.
+```
+ cmake .. -DDISABLE_TLS=ON -DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_TARGET_TRIPLET=x64-windows-static
+```
## 6. Configuration
diff --git a/cmake/boost.cmake b/cmake/boost.cmake
new file mode 100644
index 000000000..7d517368e
--- /dev/null
+++ b/cmake/boost.cmake
@@ -0,0 +1,19 @@
+set(ROOT ${CMAKE_BINARY_DIR}/boost/)
+
+ExternalProject_add(
+ boost
+ PREFIX boost
+ URL https://github.com/boostorg/boost/releases/download/boost-1.84.0/boost-1.84.0.tar.xz
+ TLS_VERIFY TRUE
+ BUILD_IN_SOURCE TRUE
+ GIT_SHALLOW TRUE
+ DOWNLOAD_EXTRACT_TIMESTAMP TRUE
+ CONFIGURE_COMMAND ${ROOT}src/boost/bootstrap.sh
+ --with-libraries=json
+ --prefix=${ROOT}build
+ BUILD_COMMAND ${ROOT}src/boost/b2 link=static
+ INSTALL_COMMAND ${ROOT}src/boost/b2 install
+)
+
+set(LIBS ${LIBS} ${ROOT}build/lib/libboost_json.a)
+set(INCLUDES ${INCLUDES} ${ROOT}build/include/)
diff --git a/cmake/config.h.in b/cmake/config.h.in
new file mode 100644
index 000000000..0e8e0cfe3
--- /dev/null
+++ b/cmake/config.h.in
@@ -0,0 +1,168 @@
+/* Name of package */
+#cmakedefine PACKAGE "@PACKAGE@"
+
+/* Version number of package */
+#cmakedefine VERSION "@VERSION@"
+
+/* Define to the address where bug reports for this package should be sent. */
+#cmakedefine PACKAGE_BUGREPORT "@PACKAGE_BUGREPORT@"
+
+/* Define to 1 to not use curses */
+#cmakedefine DISABLE_CURSES
+
+/* Define to 1 to disable gzip-support */
+#cmakedefine DISABLE_GZIP
+
+/* Define to 1 to not use libxml2, only for development purposes */
+#cmakedefine DISABLE_LIBXML2
+
+/* Define to 1 to disable par-verification and repair */
+#cmakedefine DISABLE_PARCHECK
+
+/* Define to 1 to not use TLS/SSL */
+#cmakedefine DISABLE_TLS
+
+/* Define to 1 to install an empty signal handler for SIGCHLD */
+#cmakedefine SIGCHLD_HANDLER @SIGCHLD_HANDLER@
+
+/* Define to the name of macro which returns the name of function being
+ compiled */
+#cmakedefine FUNCTION_MACRO_NAME @FUNCTION_MACRO_NAME@
+
+/* Define to 1 to create stacktrace on segmentation faults */
+#cmakedefine HAVE_BACKTRACE @HAVE_BACKTRACE@
+
+/* Define to 1 if ctime_r takes 2 arguments */
+#cmakedefine HAVE_CTIME_R_2 @HAVE_CTIME_R_2@
+
+/* Define to 1 if ctime_r takes 3 arguments */
+#cmakedefine HAVE_CTIME_R_3 @HAVE_CTIME_R_3@
+
+/* Define to 1 if you have the header file. */
+#cmakedefine HAVE_CURSES_H @HAVE_CURSES_H@
+
+/* Define to 1 if you have the header file. */
+#cmakedefine HAVE_ENDIAN_H @HAVE_ENDIAN_H@
+
+/* Define to 1 if fdatasync is supported */
+#cmakedefine HAVE_FDATASYNC @HAVE_FDATASYNC@
+
+/* Define to 1 if fseeko (and presumably ftello) exists and is declared. */
+#cmakedefine HAVE_FSEEKO @HAVE_FSEEKO@
+
+/* Define to 1 if F_FULLFSYNC is supported */
+#cmakedefine HAVE_FULLFSYNC @HAVE_FULLFSYNC@
+
+/* Define to 1 if getaddrinfo is supported */
+#cmakedefine HAVE_GETADDRINFO @HAVE_GETADDRINFO@
+
+/* Define to 1 if gethostbyname_r is supported */
+#cmakedefine HAVE_GETHOSTBYNAME_R @HAVE_GETHOSTBYNAME_R@
+
+/* Define to 1 if gethostbyname_r takes 3 arguments */
+#cmakedefine HAVE_GETHOSTBYNAME_R_3 @HAVE_GETHOSTBYNAME_R_3@
+
+/* Define to 1 if gethostbyname_r takes 5 arguments */
+#cmakedefine HAVE_GETHOSTBYNAME_R_5 @HAVE_GETHOSTBYNAME_R_5@
+
+/* Define to 1 if gethostbyname_r takes 6 arguments */
+#cmakedefine HAVE_GETHOSTBYNAME_R_6 @HAVE_GETHOSTBYNAME_R_6@
+
+/* Define to 1 if you have the `getopt' function. */
+#cmakedefine HAVE_GETOPT @HAVE_GETOPT@
+
+/* Define to 1 if you have the header file. */
+#cmakedefine HAVE_GETOPT_H @HAVE_GETOPT_H@
+
+/* Define to 1 if getopt_long is supported */
+#cmakedefine HAVE_GETOPT_LONG @HAVE_GETOPT_LONG@
+
+/* Define to 1 if you have the header file. */
+#cmakedefine HAVE_INTTYPES_H @HAVE_INTTYPES_H@
+
+/* Define to 1 to use GnuTLS library for TLS/SSL-support. */
+#cmakedefine HAVE_LIBGNUTLS @HAVE_LIBGNUTLS@
+
+/* Define to 1 if lockf is supported */
+#cmakedefine HAVE_LOCKF @HAVE_LOCKF@
+
+/* Define to 1 if you have the header file. */
+#cmakedefine HAVE_NCURSES_H @HAVE_NCURSES_H@
+
+/* Define to 1 if you have the header file. */
+#cmakedefine HAVE_NCURSES_NCURSES_H @HAVE_NCURSES_NCURSES_H@
+
+/* Define to 1 to use Nettle library for decryption. */
+#cmakedefine HAVE_NETTLE @HAVE_NETTLE@
+
+/* Define to 1 to use OpenSSL library for TLS/SSL-support and decryption. */
+#cmakedefine HAVE_OPENSSL @HAVE_OPENSSL@
+
+/* Define to 1 if pthread_cancel is supported */
+#cmakedefine HAVE_PTHREAD_CANCEL @HAVE_PTHREAD_CANCEL@
+
+/* Define to 1 if you have the header file. */
+#cmakedefine HAVE_REGEX_H @HAVE_REGEX_H@
+
+/* Define to 1 if _SC_NPROCESSORS_ONLN is present in unistd.h */
+#cmakedefine HAVE_SC_NPROCESSORS_ONLN @HAVE_SC_NPROCESSORS_ONLN@
+
+/* Define to 1 if you have the header file. */
+#cmakedefine HAVE_STDINT_H @HAVE_STDINT_H@
+
+/* Define to 1 if you have the header file. */
+#cmakedefine HAVE_STDIO_H @HAVE_STDIO_H@
+
+/* Define to 1 if you have the header file. */
+#cmakedefine HAVE_STDLIB_H @HAVE_STDLIB_H@
+
+/* Define to 1 if you have the header file. */
+#cmakedefine HAVE_STRINGS_H @HAVE_STRINGS_H@
+
+/* Define to 1 if you have the header file. */
+#cmakedefine HAVE_STRING_H @HAVE_STRING_H@
+
+/* Define to 1 if you have the header file. */
+#cmakedefine HAVE_SYS_PRCTL_H @HAVE_SYS_PRCTL_H@
+
+/* Define to 1 if you have the header file. */
+#cmakedefine HAVE_SYS_STAT_H @HAVE_SYS_STAT_H@
+
+/* Define to 1 if you have the header file. */
+#cmakedefine HAVE_SYS_TYPES_H @HAVE_SYS_TYPES_H@
+
+/* Define to 1 if you have the header file. */
+#cmakedefine HAVE_UNISTD_H @HAVE_UNISTD_H@
+
+/* Define to 1 if variadic macros are supported */
+#cmakedefine HAVE_VARIADIC_MACROS @HAVE_VARIADIC_MACROS@
+
+/* Define to 1 if OpenSSL supports function "X509_check_host" */
+#cmakedefine HAVE_X509_CHECK_HOST @HAVE_X509_CHECK_HOST@
+
+/* Determine what socket length (socklen_t) data type is */
+#cmakedefine SOCKLEN_T @SOCKLEN_T@
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+#cmakedefine _FILE_OFFSET_BITS @_FILE_OFFSET_BITS@
+
+/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */
+#cmakedefine _LARGEFILE_SOURCE @_LARGEFILE_SOURCE@
+
+/* Define for large files, on AIX-style hosts. */
+#cmakedefine _LARGE_FILES @_LARGE_FILES@
+
+/* Define to `unsigned int' if does not define. */
+#cmakedefine size_t @size_t@
+
+/* Define if AMD64 */
+#cmakedefine __amd64__
+
+/* Define if i686 */
+#cmakedefine __i686__
+
+/* Use 32BIT TIME_T */
+#cmakedefine _USE_32BIT_TIME_T
+
+/* detection of memory leaks */
+#cmakedefine _CRTDBG_MAP_ALLOC
diff --git a/cmake/install.cmake b/cmake/install.cmake
new file mode 100644
index 000000000..3175b3bec
--- /dev/null
+++ b/cmake/install.cmake
@@ -0,0 +1,43 @@
+set(DOC_FILES
+ ${CMAKE_SOURCE_DIR}/ChangeLog
+ ${CMAKE_SOURCE_DIR}/COPYING
+)
+set(SHARE_DIR ${CMAKE_INSTALL_PREFIX}/share/${PACKAGE})
+set(CONF_FILE ${CMAKE_SOURCE_DIR}/nzbget.conf)
+set(WEBUI_DIR ${CMAKE_SOURCE_DIR}/webui)
+set(DOC_FILES_DEST ${SHARE_DIR}/doc)
+set(CONF_FILE_DEST ${SHARE_DIR})
+set(WEBUI_DIR_DEST ${SHARE_DIR})
+set(BIN_FILE_DEST ${CMAKE_INSTALL_PREFIX}/bin)
+
+install(TARGETS ${PACKAGE} PERMISSIONS
+ OWNER_EXECUTE
+ OWNER_WRITE
+ OWNER_READ
+ GROUP_READ
+ GROUP_EXECUTE
+ WORLD_READ
+ WORLD_EXECUTE
+ DESTINATION ${BIN_FILE_DEST})
+install(FILES ${DOC_FILES} DESTINATION ${DOC_FILES_DEST})
+install(DIRECTORY ${WEBUI_DIR} DESTINATION ${WEBUI_DIR_DEST})
+
+file(READ ${CONF_FILE} CONFIG_CONTENT)
+string(REPLACE "WebDir=" "WebDir=${WEBUI_DIR_DEST}/webui" MODIFIED_CONFIG_CONTENT "${CONFIG_CONTENT}")
+string(REPLACE "ConfigTemplate=" "ConfigTemplate=${CONF_FILE_DEST}/nzbget.conf" MODIFIED_CONFIG_CONTENT "${MODIFIED_CONFIG_CONTENT}")
+file(WRITE ${CMAKE_BINARY_DIR}/nzbget.conf "${MODIFIED_CONFIG_CONTENT}")
+install(FILES ${CMAKE_BINARY_DIR}/nzbget.conf DESTINATION ${CONF_FILE_DEST})
+
+if(NOT EXISTS ${CMAKE_INSTALL_PREFIX}/etc/nzbget.conf)
+ install(FILES ${CMAKE_BINARY_DIR}/nzbget.conf DESTINATION ${CMAKE_INSTALL_PREFIX}/etc)
+else()
+ message(STATUS "nzbget.conf is already installed in ${CMAKE_INSTALL_PREFIX}/etc")
+ message(STATUS "If you want to overwrite it, then do it manually with caution")
+endif()
+
+add_custom_target(uninstall
+ COMMAND ${CMAKE_COMMAND} -E remove_directory ${DOC_FILES_DEST}
+ COMMAND ${CMAKE_COMMAND} -E remove_directory ${SHARE_DIR}
+ COMMAND ${CMAKE_COMMAND} -E remove ${BIN_FILE_DEST}/${PACKAGE}
+ COMMENT "Uninstalling" ${PACKAGE}
+)
diff --git a/cmake/posix.cmake b/cmake/posix.cmake
new file mode 100644
index 000000000..376d92ea1
--- /dev/null
+++ b/cmake/posix.cmake
@@ -0,0 +1,337 @@
+option(ENABLE_STATIC "Build static executable")
+option(ENABLE_TESTS "Build tests")
+option(ENABLE_CLANG_TIDY "Enable Clang-Tidy static analizer")
+option(DISABLE_TLS "Disable TLS")
+option(DISABLE_CURSES "Disable curses")
+option(DISABLE_GZIP "Disable gzip")
+option(DISABLE_PARCHECK "Disable parcheck")
+option(USE_OPENSSL "Use OpenSSL" ON)
+option(USE_GNUTLS "Use GnuTLS" OFF)
+
+if(NOT DISABLE_TLS AND USE_GNUTLS)
+ set(USE_OPENSSL OFF)
+endif()
+
+if(DISABLE_TLS)
+ set(USE_GNUTLS OFF)
+ set(USE_OPENSSL OFF)
+endif()
+
+message(STATUS "TOOLCHAIN OPTIONS:")
+message(STATUS " SYSTEM NAME ${CMAKE_SYSTEM_NAME}")
+message(STATUS " SYSTEM PROCESSOR ${CMAKE_SYSTEM_PROCESSOR}")
+message(STATUS "BUILD OPTIONS:")
+message(STATUS " BUILD TYPE: ${CMAKE_BUILD_TYPE}")
+message(STATUS " ENABLE STATIC: ${ENABLE_STATIC}")
+message(STATUS " ENABLE TESTS: ${ENABLE_TESTS}")
+message(STATUS " DISABLE TLS: ${DISABLE_TLS}")
+message(STATUS " - OPENSSL: ${USE_OPENSSL}")
+message(STATUS " - GNUTLS: ${USE_GNUTLS}")
+message(STATUS " DISABLE CURSES: ${DISABLE_CURSES}")
+message(STATUS " DISABLE GZIP: ${DISABLE_GZIP}")
+message(STATUS " DISABLE PARCHECK: ${DISABLE_PARCHECK}")
+
+if(ENABLE_CLANG_TIDY)
+ set(CMAKE_CXX_CLANG_TIDY clang-tidy -checks=-*,readability-*)
+endif()
+
+if(ENABLE_STATIC)
+ # due to the error "ld: library not found for -crt0.o" when using Apple Clang with "-static"
+ if(NOT CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
+ set(CMAKE_EXE_LINKER_FLAGS_DEBUG "-static" CACHE STRING "" FORCE)
+ set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} -static" CACHE STRING "" FORCE)
+ endif()
+ set(BUILD_SHARED_LIBS OFF)
+ set(LIBS $ENV{LIBS})
+ set(INCLUDES $ENV{INCLUDES})
+ include(${CMAKE_SOURCE_DIR}/lib/sources.cmake)
+else()
+ find_package(Threads REQUIRED)
+ find_package(LibXml2 REQUIRED)
+
+ set(LIBS ${LIBS} Threads::Threads LibXml2::LibXml2)
+ set(INCLUDES ${INCLUDES} ${LIBXML2_INCLUDE_DIR})
+
+ if(NOT DISABLE_TLS)
+ if(USE_OPENSSL AND NOT USE_GNUTLS)
+ find_package(OpenSSL REQUIRED)
+ set(LIBS ${LIBS} OpenSSL::SSL OpenSSL::Crypto)
+ set(INCLUDES ${INCLUDES} ${OPENSSL_INCLUDE_DIR})
+ elseif(USE_GNUTLS)
+ find_package(GnuTLS REQUIRED)
+ find_library(NETTLE_LIBRARY NAMES nettle libnettle)
+ set(INCLUDES ${INCLUDES} ${GNUTLS_INCLUDE_DIRS})
+ set(LIBS ${LIBS} GnuTLS::GnuTLS ${NETTLE_LIBRARY})
+ endif()
+ endif()
+
+ if(NOT DISABLE_CURSES)
+ set(CURSES_NEED_NCURSES TRUE)
+ find_package(Curses REQUIRED)
+ set(INCLUDES ${INCLUDES} ${CURSES_INCLUDE_DIRS})
+ set(LIBS ${LIBS} ${CURSES_LIBRARIES})
+ endif()
+
+ if(NOT DISABLE_GZIP)
+ find_package(ZLIB REQUIRED)
+ set(INCLUDES ${INCLUDES} ${ZLIB_INCLUDE_DIRS})
+ set(LIBS ${LIBS} ZLIB::ZLIB)
+ endif()
+
+ find_package(Boost COMPONENTS json)
+
+ if(NOT Boost_JSON_FOUND)
+ message(STATUS "The Boost library will be installed from github")
+ include(ExternalProject)
+
+ include(${CMAKE_SOURCE_DIR}/cmake/boost.cmake)
+
+ include(${CMAKE_SOURCE_DIR}/lib/sources.cmake)
+
+ add_dependencies(${PACKAGE} boost)
+ add_dependencies(yencode boost)
+ add_dependencies(par2 boost)
+ add_dependencies(regex boost)
+ else()
+ set(LIBS ${LIBS} Boost::json)
+ set(INCLUDES ${INCLUDES} ${Boost_INCLUDE_DIR})
+
+ include(${CMAKE_SOURCE_DIR}/lib/sources.cmake)
+ endif()
+endif()
+
+include(CheckIncludeFiles)
+include(CheckLibraryExists)
+include(CheckSymbolExists)
+include(CheckFunctionExists)
+include(CheckTypeSize)
+include(CheckCSourceCompiles)
+include(CheckCXXSourceCompiles)
+
+check_include_files(sys/prctl.h HAVE_SYS_PRCTL_H)
+check_include_files(regex.h HAVE_REGEX_H)
+check_include_files(endian.h HAVE_ENDIAN_H)
+check_include_files(getopt.h HAVE_GETOPT_H)
+check_include_file(inttypes.h HAVE_INTTYPES_H)
+check_include_file(stdint.h HAVE_STDINT_H)
+check_include_file(stdio.h HAVE_STDIO_H)
+check_include_file(stdlib.h HAVE_STDLIB_H)
+check_include_file(strings.h HAVE_STRINGS_H)
+check_include_file(string.h HAVE_STRING_H)
+check_include_file(sys/stat.h HAVE_SYS_STAT_H)
+check_include_file(unistd.h HAVE_UNISTD_H)
+
+check_library_exists(pthread pthread_create "" HAVE_PTHREAD_CREATE)
+check_library_exists(socket socket "" HAVE_SOCKET)
+check_library_exists(nsl inet_addr "" HAVE_INET_ADDR)
+check_library_exists(resolv hstrerror "" HAVE_HSTRERROR)
+
+check_symbol_exists(lockf unistd.h HAVE_LOCKF)
+check_symbol_exists(pthread_cancel pthread.h HAVE_PTHREAD_CANCEL)
+check_symbol_exists(F_FULLFSYNC fcntl.h HAVE_FULLFSYNC)
+
+check_function_exists(getopt_long HAVE_GETOPT_LONG)
+check_function_exists(fdatasync HAVE_FDATASYNC)
+
+set(SIGCHLD_HANDLER 1)
+
+if(USE_OPENSSL)
+ set(HAVE_OPENSSL 1)
+endif()
+
+if(USE_GNUTLS)
+ set(HAVE_LIBGNUTLS 1)
+ set(HAVE_NETTLE 1)
+endif()
+
+if(NOT DISABLE_CURSES)
+ set(HAVE_NCURSES_H 1)
+endif()
+
+if(NOT DISABLED_PARCHECK)
+ check_type_size(size_t SIZE_T)
+ check_symbol_exists(fseeko "stdio.h" HAVE_FSEEKO)
+ check_function_exists(getopt HAVE_GETOPT)
+else()
+ set(DISABLED_PARCHECK 1)
+endif()
+
+# check ctime_r
+check_cxx_source_compiles("
+ #include
+ int main()
+ {
+ time_t clock;
+ char buf[26];
+ ctime_r(&clock, buf, 26);
+ return 0;
+ }" HAVE_CTIME_R_3)
+
+if(NOT HAVE_CTIME_R_3)
+ check_cxx_source_compiles("
+ #include
+ int main()
+ {
+ time_t clock;
+ char buf[26];
+ ctime_r(&clock, buf);
+ return 0;
+ }" HAVE_CTIME_R_2)
+endif()
+if(NOT HAVE_CTIME_R_2)
+ message(FATAL_ERROR "ctime_r function not found")
+endif()
+
+check_function_exists(getaddrinfo HAVE_GETADDRINFO)
+if(NOT HAVE_GETADDRINFO)
+ check_library_exists(nsl getaddrinfo "" HAVE_GETADDRINFO)
+endif()
+
+# check gethostbyname_r, if getaddrinfo is not available
+if(NOT HAVE_GETADDRINFO)
+ check_cxx_source_compiles("
+ #include
+ int main()
+ {
+ char* szHost;
+ struct hostent hinfobuf;
+ char* strbuf;
+ int h_errnop;
+ struct hostent* hinfo = gethostbyname_r(szHost, &hinfobuf, strbuf, 1024, &h_errnop);
+ return 0;
+ }" HAVE_GETHOSTBYNAME_R_5)
+if(NOT HAVE_GETHOSTBYNAME_R_5)
+ check_cxx_source_compiles("
+ #include
+ int main()
+ {
+ char* szHost;
+ struct hostent* hinfo;
+ struct hostent hinfobuf;
+ char* strbuf;
+ int h_errnop;
+ int err = gethostbyname_r(szHost, &hinfobuf, strbuf, 1024, &hinfo, &h_errnop);
+ return 0;
+ }" HAVE_GETHOSTBYNAME_R_6)
+if(NOT HAVE_GETHOSTBYNAME_R_6)
+ check_cxx_source_compiles("
+ #include
+ int main()
+ {
+ char* szHost;
+ struct hostent hinfo;
+ struct hostent_data hinfobuf;
+ int err = gethostbyname_r(szHost, &hinfo, &hinfobuf);
+ return 0;
+ }" HAVE_GETHOSTBYNAME_R_3)
+if(NOT HAVE_GETHOSTBYNAME_R_3)
+ message(FATAL_ERROR "gethostbyname_r function not found")
+endif()
+endif()
+endif()
+if (NOT HAVE_GETHOSTBYNAME_R_3)
+ set(HAVE_GETHOSTBYNAME_R 1)
+ check_library_exists(nsl gethostbyname_r "" HAVE_GETHOSTBYNAME_R)
+endif()
+endif()
+
+# Determine what socket length (socklen_t) data type is
+check_cxx_source_compiles("
+ #include
+ #include
+ #include
+ int main()
+ {
+ (void)getsockopt (1, 1, 1, NULL, (socklen_t*)NULL);
+ }" SOCKLEN)
+if(SOCKLEN)
+ set(SOCKLEN_T socklen_t)
+else()
+ check_cxx_source_compiles("
+ #include
+ #include
+ #include
+ int main()
+ {
+ (void)getsockopt (1, 1, 1, NULL, (size_t*)NULL);
+ }" SOCKLEN)
+if(SOCKLEN)
+ set(SOCKLEN_T size_t)
+else()
+ check_cxx_source_compiles("
+ #include
+ #include
+ #include
+ int main()
+ {
+ (void)getsockopt (1, 1, 1, NULL, (int*)NULL);
+ }" SOCKLEN)
+if(SOCKLEN)
+ set(SOCKLEN_T int)
+else()
+ set(SOCKLEN_T int)
+endif()
+endif()
+endif()
+
+# Check CPU cores via sysconf
+check_cxx_source_compiles("
+ #include
+ int main()
+ {
+ int a = _SC_NPROCESSORS_ONLN;
+ }" HAVE_SC_NPROCESSORS_ONLN)
+
+# Check TLS/SSL
+if(USE_OPENSSL AND NOT ENABLE_STATIC)
+ check_library_exists(OpenSSL::Crypto X509_check_host "" HAVE_X509_CHECK_HOST)
+endif()
+
+check_cxx_source_compiles("
+ #include
+ int main()
+ {
+ printf(\"%s\", __FUNCTION__);
+ return 0;
+ }" FUNCTION_MACRO_NAME_ONE)
+
+check_cxx_source_compiles("
+ #include
+ int main()
+ {
+ printf(\"%s\", __func__);
+ return 0;
+ }" FUNCTION_MACRO_NAME_TWO)
+
+if(FUNCTION_MACRO_NAME_ONE)
+ set(FUNCTION_MACRO_NAME __FUNCTION__)
+elseif (FUNCTION_MACRO_NAME_TWO)
+ set(FUNCTION_MACRO_NAME __func__)
+endif()
+
+check_cxx_source_compiles("
+ #define macro(...) macrofunc(__VA_ARGS__)
+ int macrofunc(int a, int b) { return a + b; }
+ int main()
+ {
+ int a = macro(1, 2);
+ return 0;
+ }" HAVE_VARIADIC_MACROS)
+
+if(HAVE_VARIADIC_MACROS)
+ set(DHAVE_VARIADIC_MACROS 1)
+endif()
+
+check_cxx_source_compiles("
+ #include
+ #include
+ #include
+ int main()
+ {
+ void* array[100];
+ size_t size;
+ char** strings;
+ size = backtrace(array, 100);
+ strings = backtrace_symbols(array, size);
+ return 0;
+ }" HAVE_BACKTRACE)
diff --git a/cmake/toolchain.cmake b/cmake/toolchain.cmake
new file mode 100644
index 000000000..329786886
--- /dev/null
+++ b/cmake/toolchain.cmake
@@ -0,0 +1,19 @@
+set(CMAKE_SYSTEM_NAME Linux)
+set(CMAKE_SYSTEM_PROCESSOR ${ARCH})
+
+set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
+
+set(CMAKE_AR ${TOOLCHAIN_PREFIX}-ar)
+set(CMAKE_ASM_COMPILER ${TOOLCHAIN_PREFIX}-as)
+set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}-gcc)
+set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}-g++)
+set(CMAKE_LINKER ${TOOLCHAIN_PREFIX}-ld)
+set(CMAKE_OBJCOPY ${TOOLCHAIN_PREFIX}-objcopy)
+set(CMAKE_RANLIB ${TOOLCHAIN_PREFIX}-ranlib)
+set(CMAKE_SIZE ${TOOLCHAIN_PREFIX}-size)
+set(CMAKE_STRIP ${TOOLCHAIN_PREFIX}-strip)
+
+set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
+set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
+set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
+set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
diff --git a/cmake/windows.cmake b/cmake/windows.cmake
new file mode 100644
index 000000000..bfc265bd7
--- /dev/null
+++ b/cmake/windows.cmake
@@ -0,0 +1,57 @@
+option(ENABLE_TESTS "Enable tests")
+option(DISABLE_TLS "Disable TLS")
+
+message(STATUS "TOOLCHAIN OPTIONS:")
+message(STATUS " SYSTEM NAME ${CMAKE_SYSTEM_NAME}")
+message(STATUS " SYSTEM PROCESSOR ${CMAKE_SYSTEM_PROCESSOR}")
+message(STATUS " TARGET TRIPLET ${VCPKG_TARGET_TRIPLET}")
+message(STATUS "BUILD OPTIONS:")
+message(STATUS " BUILD TYPE: ${CMAKE_BUILD_TYPE}")
+message(STATUS " ENABLE TESTS: ${ENABLE_TESTS}")
+message(STATUS " DISABLE TLS: ${DISABLE_TLS}")
+
+set(Boost_USE_STATIC_LIBS ON)
+
+find_package(Threads REQUIRED)
+find_package(LibXml2 REQUIRED)
+find_package(Boost REQUIRED COMPONENTS json)
+
+set(LIBS Threads::Threads Boost::json LibXml2::LibXml2)
+set(INCLUDES ${Boost_INCLUDE_DIR} ${LIBXML2_INCLUDE_DIR})
+
+if(NOT DISABLE_TLS)
+ find_package(OpenSSL REQUIRED)
+ set(HAVE_OPENSSL 1)
+ set(HAVE_X509_CHECK_HOST 1)
+ set(LIBS ${LIBS} OpenSSL::SSL OpenSSL::Crypto)
+ set(INCLUDES ${INCLUDES} ${OPENSSL_INCLUDE_DIR})
+endif()
+
+find_package(ZLIB REQUIRED)
+set(LIBS ${LIBS} ZLIB::ZLIB)
+set(INCLUDES ${INCLUDES} ${ZLIB_INCLUDE_DIRS})
+
+include(${CMAKE_SOURCE_DIR}/lib/sources.cmake)
+set(INCLUDES ${INCLUDES}
+ ${CMAKE_SOURCE_DIR}/daemon/windows
+ ${CMAKE_SOURCE_DIR}/windows/resources
+)
+
+set(FUNCTION_MACRO_NAME __FUNCTION__)
+set(HAVE_CTIME_R_3 1)
+set(HAVE_VARIADIC_MACROS 1)
+set(HAVE_GETADDRINFO 1)
+set(SOCKLEN_T socklen_t)
+set(HAVE_REGEX_H 1)
+set(HAVE_STDINT_H 1)
+
+if(CMAKE_SIZEOF_VOID_P EQUAL 8)
+ set(__amd64__ 1)
+else()
+ set(__i686__ 1)
+ set(_USE_32BIT_TIME_T 1)
+endif()
+
+if(CMAKE_BUILD_TYPE STREQUAL "Debug")
+ set(_CRTDBG_MAP_ALLOC 1)
+endif()
diff --git a/cmake_config.h.in b/cmake_config.h.in
deleted file mode 100644
index aa35cd479..000000000
--- a/cmake_config.h.in
+++ /dev/null
@@ -1,5 +0,0 @@
-/* Name of package */
-#cmakedefine PACKAGE "@PACKAGE@"
-
-/* Version number of package */
-#cmakedefine VERSION "@VERSION@"
diff --git a/daemon/main/Options.cpp b/daemon/main/Options.cpp
index b10b6bda7..ead51f061 100644
--- a/daemon/main/Options.cpp
+++ b/daemon/main/Options.cpp
@@ -187,6 +187,7 @@ const char* PossibleConfigLocations[] =
"/usr/etc/nzbget.conf",
"/usr/local/etc/nzbget.conf",
"/opt/etc/nzbget.conf",
+ "~/usr/etc/nzbget.conf",
nullptr
};
#endif
diff --git a/daemon/main/nzbget.h b/daemon/main/nzbget.h
index 98bd04fa8..2ec287b6d 100644
--- a/daemon/main/nzbget.h
+++ b/daemon/main/nzbget.h
@@ -112,11 +112,9 @@ compiled */
#endif
-
/***************** GLOBAL INCLUDES *****************/
#ifdef WIN32
-
// WINDOWS INCLUDES
// Using "WIN32_LEAN_AND_MEAN" to disable including of many unneeded headers
@@ -138,14 +136,8 @@ compiled */
#include
#include
#include
-
#include
-#if _MSC_VER >= 1600
-#include
-#define HAVE_STDINT_H
-#endif
-
#ifdef _DEBUG
#include
#endif
@@ -159,9 +151,7 @@ compiled */
#include
#include
#include
-#include
#include
-#include
#include
#include
#include
@@ -172,8 +162,6 @@ compiled */
#include
#include
#include
-#include
-#include
#include
#ifdef HAVE_SYS_PRCTL_H
@@ -200,6 +188,7 @@ compiled */
#include
#include
#include
+#include
#include
#include
#include
diff --git a/daemon/sources.cmake b/daemon/sources.cmake
new file mode 100644
index 000000000..8f764e46b
--- /dev/null
+++ b/daemon/sources.cmake
@@ -0,0 +1,105 @@
+set(SRC
+ ${CMAKE_SOURCE_DIR}/daemon/connect/Connection.cpp
+ ${CMAKE_SOURCE_DIR}/daemon/connect/TlsSocket.cpp
+ ${CMAKE_SOURCE_DIR}/daemon/connect/WebDownloader.cpp
+
+ ${CMAKE_SOURCE_DIR}/daemon/extension/CommandScript.cpp
+ ${CMAKE_SOURCE_DIR}/daemon/extension/FeedScript.cpp
+ ${CMAKE_SOURCE_DIR}/daemon/extension/NzbScript.cpp
+ ${CMAKE_SOURCE_DIR}/daemon/extension/PostScript.cpp
+ ${CMAKE_SOURCE_DIR}/daemon/extension/PostScript.cpp
+ ${CMAKE_SOURCE_DIR}/daemon/extension/QueueScript.cpp
+ ${CMAKE_SOURCE_DIR}/daemon/extension/ScanScript.cpp
+ ${CMAKE_SOURCE_DIR}/daemon/extension/SchedulerScript.cpp
+ ${CMAKE_SOURCE_DIR}/daemon/extension/ScriptConfig.cpp
+ ${CMAKE_SOURCE_DIR}/daemon/extension/ScriptConfig.cpp
+ ${CMAKE_SOURCE_DIR}/daemon/extension/Extension.cpp
+ ${CMAKE_SOURCE_DIR}/daemon/extension/ExtensionLoader.cpp
+ ${CMAKE_SOURCE_DIR}/daemon/extension/ExtensionManager.cpp
+ ${CMAKE_SOURCE_DIR}/daemon/extension/ManifestFile.cpp
+
+ ${CMAKE_SOURCE_DIR}/daemon/feed/FeedCoordinator.cpp
+ ${CMAKE_SOURCE_DIR}/daemon/feed/FeedFile.cpp
+ ${CMAKE_SOURCE_DIR}/daemon/feed/FeedFilter.cpp
+ ${CMAKE_SOURCE_DIR}/daemon/feed/FeedInfo.cpp
+
+ ${CMAKE_SOURCE_DIR}/daemon/frontend/ColoredFrontend.cpp
+ ${CMAKE_SOURCE_DIR}/daemon/frontend/Frontend.cpp
+ ${CMAKE_SOURCE_DIR}/daemon/frontend/LoggableFrontend.cpp
+ ${CMAKE_SOURCE_DIR}/daemon/frontend/NCursesFrontend.cpp
+
+ ${CMAKE_SOURCE_DIR}/daemon/main/CommandLineParser.cpp
+ ${CMAKE_SOURCE_DIR}/daemon/main/DiskService.cpp
+ ${CMAKE_SOURCE_DIR}/daemon/main/Maintenance.cpp
+ ${CMAKE_SOURCE_DIR}/daemon/main/nzbget.cpp
+ ${CMAKE_SOURCE_DIR}/daemon/main/Options.cpp
+ ${CMAKE_SOURCE_DIR}/daemon/main/Scheduler.cpp
+ ${CMAKE_SOURCE_DIR}/daemon/main/StackTrace.cpp
+ ${CMAKE_SOURCE_DIR}/daemon/main/WorkState.cpp
+
+ ${CMAKE_SOURCE_DIR}/daemon/nntp/ArticleDownloader.cpp
+ ${CMAKE_SOURCE_DIR}/daemon/nntp/ArticleWriter.cpp
+ ${CMAKE_SOURCE_DIR}/daemon/nntp/Decoder.cpp
+ ${CMAKE_SOURCE_DIR}/daemon/nntp/NewsServer.cpp
+ ${CMAKE_SOURCE_DIR}/daemon/nntp/NntpConnection.cpp
+ ${CMAKE_SOURCE_DIR}/daemon/nntp/ServerPool.cpp
+ ${CMAKE_SOURCE_DIR}/daemon/nntp/StatMeter.cpp
+
+ ${CMAKE_SOURCE_DIR}/daemon/nserv/NntpServer.cpp
+ ${CMAKE_SOURCE_DIR}/daemon/nserv/NServFrontend.cpp
+ ${CMAKE_SOURCE_DIR}/daemon/nserv/NServMain.cpp
+ ${CMAKE_SOURCE_DIR}/daemon/nserv/NzbGenerator.cpp
+ ${CMAKE_SOURCE_DIR}/daemon/nserv/YEncoder.cpp
+
+ ${CMAKE_SOURCE_DIR}/daemon/postprocess/Cleanup.cpp
+ ${CMAKE_SOURCE_DIR}/daemon/postprocess/DirectUnpack.cpp
+ ${CMAKE_SOURCE_DIR}/daemon/postprocess/DupeMatcher.cpp
+ ${CMAKE_SOURCE_DIR}/daemon/postprocess/ParChecker.cpp
+ ${CMAKE_SOURCE_DIR}/daemon/postprocess/ParParser.cpp
+ ${CMAKE_SOURCE_DIR}/daemon/postprocess/ParRenamer.cpp
+ ${CMAKE_SOURCE_DIR}/daemon/postprocess/PrePostProcessor.cpp
+ ${CMAKE_SOURCE_DIR}/daemon/postprocess/RarReader.cpp
+ ${CMAKE_SOURCE_DIR}/daemon/postprocess/RarRenamer.cpp
+ ${CMAKE_SOURCE_DIR}/daemon/postprocess/Rename.cpp
+ ${CMAKE_SOURCE_DIR}/daemon/postprocess/Repair.cpp
+ ${CMAKE_SOURCE_DIR}/daemon/postprocess/Unpack.cpp
+
+ ${CMAKE_SOURCE_DIR}/daemon/queue/DirectRenamer.cpp
+ ${CMAKE_SOURCE_DIR}/daemon/queue/DiskState.cpp
+ ${CMAKE_SOURCE_DIR}/daemon/queue/DownloadInfo.cpp
+ ${CMAKE_SOURCE_DIR}/daemon/queue/DupeCoordinator.cpp
+ ${CMAKE_SOURCE_DIR}/daemon/queue/HistoryCoordinator.cpp
+ ${CMAKE_SOURCE_DIR}/daemon/queue/NzbFile.cpp
+ ${CMAKE_SOURCE_DIR}/daemon/queue/QueueCoordinator.cpp
+ ${CMAKE_SOURCE_DIR}/daemon/queue/QueueEditor.cpp
+ ${CMAKE_SOURCE_DIR}/daemon/queue/Scanner.cpp
+ ${CMAKE_SOURCE_DIR}/daemon/queue/UrlCoordinator.cpp
+
+ ${CMAKE_SOURCE_DIR}/daemon/remote/BinRpc.cpp
+ ${CMAKE_SOURCE_DIR}/daemon/remote/RemoteClient.cpp
+ ${CMAKE_SOURCE_DIR}/daemon/remote/RemoteServer.cpp
+ ${CMAKE_SOURCE_DIR}/daemon/remote/WebServer.cpp
+ ${CMAKE_SOURCE_DIR}/daemon/remote/XmlRpc.cpp
+ ${CMAKE_SOURCE_DIR}/daemon/remote/MessageBase.h
+
+ ${CMAKE_SOURCE_DIR}/daemon/util/FileSystem.cpp
+ ${CMAKE_SOURCE_DIR}/daemon/util/Log.cpp
+ ${CMAKE_SOURCE_DIR}/daemon/util/NString.cpp
+ ${CMAKE_SOURCE_DIR}/daemon/util/Observer.cpp
+ ${CMAKE_SOURCE_DIR}/daemon/util/ScriptController.cpp
+ ${CMAKE_SOURCE_DIR}/daemon/util/Service.cpp
+ ${CMAKE_SOURCE_DIR}/daemon/util/Thread.cpp
+ ${CMAKE_SOURCE_DIR}/daemon/util/Util.cpp
+ ${CMAKE_SOURCE_DIR}/daemon/util/Json.cpp
+ ${CMAKE_SOURCE_DIR}/daemon/util/Xml.cpp
+)
+
+set(WIN32_SRC
+ ${CMAKE_SOURCE_DIR}/daemon/windows/StdAfx.cpp
+ ${CMAKE_SOURCE_DIR}/daemon/windows/WinConsole.cpp
+ ${CMAKE_SOURCE_DIR}/daemon/windows/WinService.cpp
+)
+
+if(WIN32)
+ set(SRC ${SRC} ${WIN32_SRC})
+endif()
diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt
deleted file mode 100644
index c879cc887..000000000
--- a/lib/CMakeLists.txt
+++ /dev/null
@@ -1,45 +0,0 @@
-add_library(Yencode STATIC
- ${CMAKE_CURRENT_SOURCE_DIR}/yencode/SimdInit.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/yencode/SimdDecoder.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/yencode/ScalarDecoder.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/yencode/Sse2Decoder.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/yencode/Ssse3Decoder.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/yencode/PclmulCrc.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/yencode/NeonDecoder.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/yencode/AcleCrc.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/yencode/SliceCrc.cpp
-)
-target_include_directories(Yencode PUBLIC
- ${CMAKE_CURRENT_SOURCE_DIR}/yencode
- ${CMAKE_SOURCE_DIR}/daemon/main
- ${ZLIB_INCLUDE_DIR}
- ${OPENSSL_INCLUDE_DIR}
-)
-
-add_library(Par2 STATIC
- ${CMAKE_CURRENT_SOURCE_DIR}/par2/commandline.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/par2/crc.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/par2/creatorpacket.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/par2/criticalpacket.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/par2/datablock.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/par2/descriptionpacket.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/par2/diskfile.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/par2/filechecksummer.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/par2/galois.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/par2/mainpacket.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/par2/md5.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/par2/par2fileformat.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/par2/par2repairer.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/par2/par2repairersourcefile.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/par2/parheaders.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/par2/recoverypacket.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/par2/reedsolomon.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/par2/verificationhashtable.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/par2/verificationpacket.cpp
-)
-target_include_directories(Par2 PUBLIC
- ${CMAKE_CURRENT_SOURCE_DIR}/par2
- ${CMAKE_SOURCE_DIR}/daemon/main
- ${CMAKE_SOURCE_DIR}/daemon/util
- ${OPENSSL_INCLUDE_DIR}
-)
diff --git a/lib/regex/regex.c b/lib/regex/regex.c
index f30a6aec9..0242bea30 100644
--- a/lib/regex/regex.c
+++ b/lib/regex/regex.c
@@ -17,7 +17,7 @@
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
-//#include "nzbget.h"
+
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
@@ -52,15 +52,17 @@
# include "../locale/localeinfo.h"
#endif
-#define strncasecmp strnicmp
-#define strcasecmp stricmp
+#define strncasecmp strncmp
+#define strcasecmp strcmp
/* On some systems, limits.h sets RE_DUP_MAX to a lower value than
GNU regex allows. Include it before , which correctly
#undefs RE_DUP_MAX and sets it to the right value. */
#include
-#include
#include
+#ifdef WIN32
+#include
+#endif
//#ifdef __cplusplus
//extern "C" {
diff --git a/lib/regex/regex.h b/lib/regex/regex.h
index 38e7d031e..f1e085725 100644
--- a/lib/regex/regex.h
+++ b/lib/regex/regex.h
@@ -19,12 +19,10 @@
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
-//#ifndef _REGEX_H
-//#define _REGEX_H 1
+
#pragma once
#include
-
/* Allow the use in C++ code. */
#ifdef __cplusplus
extern "C" {
diff --git a/lib/sources.cmake b/lib/sources.cmake
new file mode 100644
index 000000000..45cc45fa7
--- /dev/null
+++ b/lib/sources.cmake
@@ -0,0 +1,98 @@
+if(CMAKE_SYSTEM_PROCESSOR MATCHES "i?86|x86_64")
+ set(SSE2_CXXFLAGS "-msse2")
+ set(SSSE3_CXXFLAGS "-mssse3")
+ set(PCLMUL_CXXFLAGS "-msse4.1 -mpclmul")
+elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^arm.*")
+ set(NEON_CXXFLAGS "-mfpu=neon")
+ set(ACLECRC_CXXFLAGS "-march=armv8-a+crc -fpermissive")
+elseif (CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64")
+ set(ACLECRC_CXXFLAGS "-march=armv8-a+crc -fpermissive")
+endif()
+
+add_library(regex STATIC
+ ${CMAKE_SOURCE_DIR}/lib/regex/regex.c
+)
+target_include_directories(regex PUBLIC
+ ${CMAKE_SOURCE_DIR}/lib/regex
+)
+
+add_library(yencode STATIC
+ ${CMAKE_SOURCE_DIR}/lib/yencode/SimdInit.cpp
+ ${CMAKE_SOURCE_DIR}/lib/yencode/SimdDecoder.cpp
+ ${CMAKE_SOURCE_DIR}/lib/yencode/ScalarDecoder.cpp
+ ${CMAKE_SOURCE_DIR}/lib/yencode/Sse2Decoder.cpp
+ ${CMAKE_SOURCE_DIR}/lib/yencode/Ssse3Decoder.cpp
+ ${CMAKE_SOURCE_DIR}/lib/yencode/PclmulCrc.cpp
+ ${CMAKE_SOURCE_DIR}/lib/yencode/NeonDecoder.cpp
+ ${CMAKE_SOURCE_DIR}/lib/yencode/AcleCrc.cpp
+ ${CMAKE_SOURCE_DIR}/lib/yencode/SliceCrc.cpp
+)
+target_include_directories(yencode PUBLIC
+ ${CMAKE_SOURCE_DIR}/lib/yencode
+ ${CMAKE_SOURCE_DIR}/lib/regex
+ ${CMAKE_SOURCE_DIR}/daemon/main
+ ${INCLUDES}
+)
+
+set_source_files_properties(
+ ${CMAKE_SOURCE_DIR}/lib/yencode/Sse2Decoder.cpp
+ PROPERTIES COMPILE_FLAGS "${CMAKE_CXX_FLAGS} ${SSE2_CXXFLAGS}"
+)
+
+set_source_files_properties(
+ ${CMAKE_SOURCE_DIR}/lib/yencode/Ssse3Decoder.cpp
+ PROPERTIES COMPILE_FLAGS "${CMAKE_CXX_FLAGS} ${SSSE3_CXXFLAGS}"
+)
+
+set_source_files_properties(
+ ${CMAKE_SOURCE_DIR}/lib/yencode/PclmulCrc.cpp
+ PROPERTIES COMPILE_FLAGS "${CMAKE_CXX_FLAGS} ${PCLMUL_CXXFLAGS}"
+)
+
+set_source_files_properties(
+ ${CMAKE_SOURCE_DIR}/lib/yencode/NeonDecoder.cpp
+ PROPERTIES COMPILE_FLAGS "${CMAKE_CXX_FLAGS_RELEASE} ${NEON_CXXFLAGS}"
+)
+
+set_source_files_properties(
+ ${CMAKE_SOURCE_DIR}/lib/yencode/AcleCrc.cpp
+ PROPERTIES COMPILE_FLAGS "${CMAKE_CXX_FLAGS} ${ACLECRC_CXXFLAGS}"
+)
+
+if(NOT DISABLE_PARCHECK)
+ add_library(par2 STATIC
+ ${CMAKE_SOURCE_DIR}/lib/par2/commandline.cpp
+ ${CMAKE_SOURCE_DIR}/lib/par2/crc.cpp
+ ${CMAKE_SOURCE_DIR}/lib/par2/creatorpacket.cpp
+ ${CMAKE_SOURCE_DIR}/lib/par2/criticalpacket.cpp
+ ${CMAKE_SOURCE_DIR}/lib/par2/datablock.cpp
+ ${CMAKE_SOURCE_DIR}/lib/par2/descriptionpacket.cpp
+ ${CMAKE_SOURCE_DIR}/lib/par2/diskfile.cpp
+ ${CMAKE_SOURCE_DIR}/lib/par2/filechecksummer.cpp
+ ${CMAKE_SOURCE_DIR}/lib/par2/galois.cpp
+ ${CMAKE_SOURCE_DIR}/lib/par2/mainpacket.cpp
+ ${CMAKE_SOURCE_DIR}/lib/par2/md5.cpp
+ ${CMAKE_SOURCE_DIR}/lib/par2/par2fileformat.cpp
+ ${CMAKE_SOURCE_DIR}/lib/par2/par2repairer.cpp
+ ${CMAKE_SOURCE_DIR}/lib/par2/par2repairersourcefile.cpp
+ ${CMAKE_SOURCE_DIR}/lib/par2/parheaders.cpp
+ ${CMAKE_SOURCE_DIR}/lib/par2/recoverypacket.cpp
+ ${CMAKE_SOURCE_DIR}/lib/par2/reedsolomon.cpp
+ ${CMAKE_SOURCE_DIR}/lib/par2/verificationhashtable.cpp
+ ${CMAKE_SOURCE_DIR}/lib/par2/verificationpacket.cpp
+ )
+ target_include_directories(par2 PUBLIC
+ ${CMAKE_SOURCE_DIR}/lib/par2
+ ${CMAKE_SOURCE_DIR}/lib/regex
+ ${CMAKE_SOURCE_DIR}/daemon/main
+ ${CMAKE_SOURCE_DIR}/daemon/util
+ ${INCLUDES}
+ )
+endif()
+
+set(LIBS ${LIBS} regex yencode)
+set(INCLUDES ${INCLUDES} ${CMAKE_SOURCE_DIR}/lib/regex ${CMAKE_SOURCE_DIR}/lib/yencode)
+if(NOT DISABLE_PARCHECK)
+ set(LIBS ${LIBS} par2)
+ set(INCLUDES ${INCLUDES} ${CMAKE_SOURCE_DIR}/lib/par2)
+endif()
diff --git a/tests/extension/CMakeLists.txt b/tests/extension/CMakeLists.txt
index fa52c78fe..447c151c2 100644
--- a/tests/extension/CMakeLists.txt
+++ b/tests/extension/CMakeLists.txt
@@ -29,16 +29,10 @@ file(GLOB ExtensionSrc
${CMAKE_SOURCE_DIR}/daemon/connect/WebDownloader.cpp
${CMAKE_SOURCE_DIR}/daemon/connect/Connection.cpp
${CMAKE_SOURCE_DIR}/daemon/connect/TlsSocket.cpp
- ${CMAKE_SOURCE_DIR}/lib/regex/regex.c
)
add_executable(ExtensionTests ${ExtensionSrc})
-target_link_libraries(ExtensionTests PRIVATE
- ZLIB::ZLIB
- Yencode
- OpenSSL::SSL
- ${LIBXML2_LIBRARIES}
-)
+target_link_libraries(ExtensionTests PRIVATE ${LIBS})
target_include_directories(ExtensionTests PRIVATE
${CMAKE_SOURCE_DIR}/daemon/main
@@ -52,9 +46,7 @@ target_include_directories(ExtensionTests PRIVATE
${CMAKE_SOURCE_DIR}/daemon/connect
${CMAKE_SOURCE_DIR}/lib/regex
${CMAKE_SOURCE_DIR}/lib/yencode
- ${ZLIB_INCLUDE_DIR}
- ${OPENSSL_INCLUDE_DIR}
- ${Boost_INCLUDE_DIR}
+ ${INCLUDES}
)
file(COPY ../testdata/extension/manifest DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
diff --git a/tests/feed/CMakeLists.txt b/tests/feed/CMakeLists.txt
index 2620cf141..0fd38c944 100644
--- a/tests/feed/CMakeLists.txt
+++ b/tests/feed/CMakeLists.txt
@@ -13,13 +13,8 @@ add_executable(FeedTest
${CMAKE_SOURCE_DIR}/daemon/queue/DownloadInfo.cpp
${CMAKE_SOURCE_DIR}/daemon/queue/DiskState.cpp
${CMAKE_SOURCE_DIR}/daemon/nntp/NewsServer.cpp
- ${CMAKE_SOURCE_DIR}/lib/regex/regex.c
-)
-target_link_libraries(FeedTest PRIVATE
- ZLIB::ZLIB
- Yencode
- LibXml2::LibXml2
)
+target_link_libraries(FeedTest PRIVATE ${LIBS})
target_include_directories(FeedTest PRIVATE
${CMAKE_SOURCE_DIR}/daemon/feed
${CMAKE_SOURCE_DIR}/daemon/main
@@ -28,8 +23,7 @@ target_include_directories(FeedTest PRIVATE
${CMAKE_SOURCE_DIR}/daemon/nntp
${CMAKE_SOURCE_DIR}/daemon/remote
${CMAKE_SOURCE_DIR}/lib/regex
- ${Boost_INCLUDE_DIR}
- ${LIBXML2_INCLUDE_DIR}
+ ${INCLUDES}
)
file(COPY ../testdata/feed DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
diff --git a/tests/feed/FeedFileTest.cpp b/tests/feed/FeedFileTest.cpp
index 5375f1fc3..c5fce143d 100644
--- a/tests/feed/FeedFileTest.cpp
+++ b/tests/feed/FeedFileTest.cpp
@@ -21,12 +21,12 @@
#include
-#include
+#include "FileSystem.h"
#include "FeedFile.h"
BOOST_AUTO_TEST_CASE(FeedFileTest)
{
- std::string path = std::filesystem::current_path().string();
+ std::string path = FileSystem::GetCurrentDirectory().Str();
std::string testFile = path + "/feed/feed.xml";
FeedFile file(testFile.c_str(), "feedName");
diff --git a/tests/main/CMakeLists.txt b/tests/main/CMakeLists.txt
index c38b58b74..4cab2dd56 100644
--- a/tests/main/CMakeLists.txt
+++ b/tests/main/CMakeLists.txt
@@ -12,13 +12,8 @@ add_executable(MainTests
${CMAKE_SOURCE_DIR}/daemon/queue/DownloadInfo.cpp
${CMAKE_SOURCE_DIR}/daemon/feed/FeedInfo.cpp
${CMAKE_SOURCE_DIR}/daemon/nntp/NewsServer.cpp
- ${CMAKE_SOURCE_DIR}/lib/regex/regex.c
-)
-target_link_libraries(MainTests PRIVATE
- ZLIB::ZLIB
- Yencode
- LibXml2::LibXml2
)
+target_link_libraries(MainTests PRIVATE ${LIBS})
target_include_directories(MainTests PRIVATE
${CMAKE_SOURCE_DIR}/daemon/main
${CMAKE_SOURCE_DIR}/daemon/util
@@ -28,9 +23,7 @@ target_include_directories(MainTests PRIVATE
${CMAKE_SOURCE_DIR}/daemon/nntp
${CMAKE_SOURCE_DIR}/lib/yencode
${CMAKE_SOURCE_DIR}/lib/regex
- ${OPENSSL_INCLUDE_DIR}
- ${Boost_INCLUDE_DIR}
- ${LIBXML2_INCLUDE_DIR}
+ ${INCLUDES}
)
add_test(NAME MainTests COMMAND $ --log_level=message)
diff --git a/tests/nntp/CMakeLists.txt b/tests/nntp/CMakeLists.txt
index 5c06ecc5d..9089edd35 100644
--- a/tests/nntp/CMakeLists.txt
+++ b/tests/nntp/CMakeLists.txt
@@ -13,15 +13,8 @@ add_executable(ServerPoolTest
${CMAKE_SOURCE_DIR}/daemon/feed/FeedInfo.cpp
${CMAKE_SOURCE_DIR}/daemon/connect/Connection.cpp
${CMAKE_SOURCE_DIR}/daemon/connect/TlsSocket.cpp
- ${CMAKE_SOURCE_DIR}/lib/regex/regex.c
-)
-target_link_libraries(ServerPoolTest PRIVATE
- OpenSSL::SSL
- ZLIB::ZLIB
- Par2
- Yencode
- LibXml2::LibXml2
)
+target_link_libraries(ServerPoolTest PRIVATE ${LIBS})
target_include_directories(ServerPoolTest PRIVATE
${CMAKE_SOURCE_DIR}/daemon/main
${CMAKE_SOURCE_DIR}/daemon/nntp
@@ -32,9 +25,7 @@ target_include_directories(ServerPoolTest PRIVATE
${CMAKE_SOURCE_DIR}/daemon/remote
${CMAKE_SOURCE_DIR}/lib/yencode
${CMAKE_SOURCE_DIR}/lib/par2
- ${OPENSSL_INCLUDE_DIR}
- ${Boost_INCLUDE_DIR}
- ${LIBXML2_INCLUDE_DIR}
+ ${INCLUDES}
)
add_test(NAME ServerPoolTest COMMAND $ --log_level=message)
diff --git a/tests/nntp/ServerPoolTest.cpp b/tests/nntp/ServerPoolTest.cpp
index d7eb7ca59..d728472fc 100644
--- a/tests/nntp/ServerPoolTest.cpp
+++ b/tests/nntp/ServerPoolTest.cpp
@@ -214,7 +214,7 @@ BOOST_AUTO_TEST_CASE(ActiveOnOffTest)
BOOST_CHECK(con3 == nullptr);
}
-BOOST_AUTO_TEST_CASE(IgnoreServers)
+BOOST_AUTO_TEST_CASE(IgnoreServersTest)
{
ServerPool pool;
AddTestServer(&pool, 1, true, 0, false, 0, 2);
@@ -236,7 +236,7 @@ BOOST_AUTO_TEST_CASE(IgnoreServers)
BOOST_CHECK(con4 == nullptr);
}
-BOOST_AUTO_TEST_CASE(IgnoreServersGrouped)
+BOOST_AUTO_TEST_CASE(IgnoreServersGroupedTest)
{
ServerPool pool;
AddTestServer(&pool, 1, true, 0, false, 1, 2);
@@ -267,17 +267,17 @@ BOOST_AUTO_TEST_CASE(IgnoreServersGrouped)
BOOST_CHECK(con3 == nullptr);
}
-BOOST_AUTO_TEST_CASE(BlockServersUngrouped)
+BOOST_AUTO_TEST_CASE(BlockServersUngroupedTest)
{
TestBlockServers(0);
}
-BOOST_AUTO_TEST_CASE(BlockServersGrouped)
+BOOST_AUTO_TEST_CASE(BlockServersGroupedTest)
{
TestBlockServers(1);
}
-BOOST_AUTO_TEST_CASE(BlockOptionalServersUngrouped)
+BOOST_AUTO_TEST_CASE(BlockOptionalServersUngroupedTest)
{
TestOptionalBlockServers(0);
}
@@ -287,12 +287,12 @@ BOOST_AUTO_TEST_CASE(BlockOptionalServersGrouped)
TestOptionalBlockServers(1);
}
-BOOST_AUTO_TEST_CASE(BlockOptionalAndNonOptionalServersUngrouped)
+BOOST_AUTO_TEST_CASE(BlockOptionalAndNonOptionalServersUngroupedTest)
{
TestBlockOptionalAndNonOptionalServers(0);
}
-BOOST_AUTO_TEST_CASE(BlockOptionalAndNonOptionalServersGrouped)
+BOOST_AUTO_TEST_CASE(BlockOptionalAndNonOptionalServersGroupedTest)
{
TestBlockOptionalAndNonOptionalServers(1);
}
diff --git a/tests/postprocess/CMakeLists.txt b/tests/postprocess/CMakeLists.txt
index 398b994fc..5189f8788 100644
--- a/tests/postprocess/CMakeLists.txt
+++ b/tests/postprocess/CMakeLists.txt
@@ -24,18 +24,10 @@ file(GLOB PostprocessTestsSrc
${CMAKE_SOURCE_DIR}/daemon/util/FileSystem.cpp
${CMAKE_SOURCE_DIR}/daemon/queue/DownloadInfo.cpp
${CMAKE_SOURCE_DIR}/daemon/queue/DiskState.cpp
- ${CMAKE_SOURCE_DIR}/lib/regex/regex.c
)
add_executable(PostprocessTests ${PostprocessTestsSrc})
-target_link_libraries(PostprocessTests PRIVATE
- ZLIB::ZLIB
- Yencode
- Par2
- OpenSSL::SSL
- OpenSSL::Crypto
- LibXml2::LibXml2
-)
+target_link_libraries(PostprocessTests PRIVATE ${LIBS})
target_include_directories(PostprocessTests PRIVATE
../suite
${CMAKE_SOURCE_DIR}/daemon/main
@@ -48,8 +40,7 @@ target_include_directories(PostprocessTests PRIVATE
${CMAKE_SOURCE_DIR}/daemon/nntp
${CMAKE_SOURCE_DIR}/lib/yencode
${CMAKE_SOURCE_DIR}/lib/par2
- ${Boost_INCLUDE_DIR}
- ${LIBXML2_INCLUDE_DIR}
+ ${INCLUDES}
)
file(COPY ../testdata/rarrenamer DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
diff --git a/tests/postprocess/DirectUnpackTest.cpp b/tests/postprocess/DirectUnpackTest.cpp
index 3e913fa08..b8234481c 100644
--- a/tests/postprocess/DirectUnpackTest.cpp
+++ b/tests/postprocess/DirectUnpackTest.cpp
@@ -21,13 +21,21 @@
#include "nzbget.h"
#include
-#include
+#include "FileSystem.h"
#include "DirectUnpack.h"
#include "Log.h"
#include "Options.h"
#include "DiskState.h"
+Log* g_Log = new Log();
+Options* g_Options;
+DiskState* g_DiskState;
+
+char* envVars[] = {"NZBXX_YYYY", 0};
+char* (*g_EnvironmentVariables)[2] = &envVars;
+char* (*g_Arguments)[] = nullptr;
+
class DirectUnpackDownloadQueueMock : public DownloadQueue
{
public:
@@ -51,24 +59,32 @@ BOOST_AUTO_TEST_CASE(DirectUnpackSimpleTest)
BOOST_TEST_MESSAGE("This test requires working unrar 5 in search path");
- const std::string testDataDir = std::filesystem::current_path().string() + "/rarrenamer";
- const std::string workingDir = testDataDir + "/empty";
- std::filesystem::create_directory(workingDir);
+ std::string currDir = FileSystem::GetCurrentDirectory().Str();
+ std::string testDataDir = currDir + "/rarrenamer";
+ std::string workingDir = testDataDir + "/empty";
+
+ BOOST_REQUIRE(FileSystem::CreateDirectory(workingDir.c_str()));
- std::filesystem::copy(
- (testDataDir + "/testfile3.part01.rar").c_str(),
- (workingDir + "/testfile3.part01.rar").c_str()
+ BOOST_REQUIRE(
+ FileSystem::CopyFile(
+ (testDataDir + "/testfile3.part01.rar").c_str(),
+ (workingDir + "/testfile3.part01.rar").c_str()
+ )
);
- std::filesystem::copy(
- (testDataDir + "/testfile3.part02.rar").c_str(),
- (workingDir + "/testfile3.part02.rar").c_str()
+ BOOST_REQUIRE(
+ FileSystem::CopyFile(
+ (testDataDir + "/testfile3.part02.rar").c_str(),
+ (workingDir + "/testfile3.part02.rar").c_str()
+ )
);
- std::filesystem::copy(
- (testDataDir + "/testfile3.part03.rar").c_str(),
- (workingDir + "/testfile3.part03.rar").c_str()
+ BOOST_REQUIRE(
+ FileSystem::CopyFile(
+ (testDataDir + "/testfile3.part03.rar").c_str(),
+ (workingDir + "/testfile3.part03.rar").c_str()
+ )
);
-
+
std::unique_ptr nzbInfo = std::make_unique();
NzbInfo* nzbPtr = nzbInfo.get();
nzbInfo->SetName("test");
@@ -94,8 +110,8 @@ BOOST_AUTO_TEST_CASE(DirectUnpackSimpleTest)
}
BOOST_CHECK(nzbPtr->GetDirectUnpackStatus() == NzbInfo::nsSuccess);
- BOOST_CHECK(std::filesystem::exists((workingDir + "/_unpack/testfile3.dat").c_str()));
- std::filesystem::remove_all(workingDir);
+ BOOST_CHECK(FileSystem::FileExists((workingDir + "/_unpack/testfile3.dat").c_str()));
+ BOOST_REQUIRE(FileSystem::RemoveDirectory(workingDir.c_str()));
}
BOOST_AUTO_TEST_CASE(DirectUnpackTwoArchives)
@@ -109,32 +125,34 @@ BOOST_AUTO_TEST_CASE(DirectUnpackTwoArchives)
BOOST_TEST_MESSAGE("This test requires working unrar 5 in search path");
- const std::string testDataDir = std::filesystem::current_path().string() + "/testdata";
- const std::string workingDir = testDataDir + "empty";
- std::filesystem::create_directory(workingDir);
+ std::string currDir = FileSystem::GetCurrentDirectory().Str();
+ std::string testDataDir = currDir + "/rarrenamer";
+ std::string workingDir = testDataDir + "/empty";
+
+ BOOST_REQUIRE(FileSystem::CreateDirectory(workingDir.c_str()));
- std::filesystem::copy(
+ FileSystem::CopyFile(
(testDataDir + "/testfile3.part01.rar").c_str(),
(workingDir + "/testfile3.part01.rar").c_str()
);
- std::filesystem::copy(
+ FileSystem::CopyFile(
(testDataDir + "/testfile3.part02.rar").c_str(),
(workingDir + "/testfile3.part02.rar").c_str()
);
- std::filesystem::copy(
+ FileSystem::CopyFile(
(testDataDir + "/testfile3.part03.rar").c_str(),
(workingDir + "/testfile3.part03.rar").c_str()
);
- std::filesystem::copy(
+ FileSystem::CopyFile(
(testDataDir + "/testfile5.part01.rar").c_str(),
(workingDir + "/testfile5.part01.rar").c_str()
);
- std::filesystem::copy(
+ FileSystem::CopyFile(
(testDataDir + "/testfile5.part02.rar").c_str(),
(workingDir + "/testfile5.part02.rar").c_str()
);
- std::filesystem::copy(
+ FileSystem::CopyFile(
(testDataDir + "/testfile5.part03.rar").c_str(),
(workingDir + "/testfile5.part03.rar").c_str()
);
@@ -164,7 +182,7 @@ BOOST_AUTO_TEST_CASE(DirectUnpackTwoArchives)
}
BOOST_CHECK(nzbPtr->GetDirectUnpackStatus() == NzbInfo::nsSuccess);
- BOOST_CHECK(std::filesystem::exists((workingDir + "/_unpack/testfile3.dat").c_str()));
- BOOST_CHECK(std::filesystem::exists((workingDir + "/_unpack/testfile5.dat").c_str()));
- std::filesystem::remove_all(workingDir);
+ BOOST_CHECK(FileSystem::FileExists((workingDir + "/_unpack/testfile3.dat").c_str()));
+ BOOST_CHECK(FileSystem::FileExists((workingDir + "/_unpack/testfile5.dat").c_str()));
+ BOOST_REQUIRE(FileSystem::RemoveDirectory(workingDir.c_str()));
}
diff --git a/tests/queue/CMakeLists.txt b/tests/queue/CMakeLists.txt
index bb535efd5..b1952ee0e 100644
--- a/tests/queue/CMakeLists.txt
+++ b/tests/queue/CMakeLists.txt
@@ -11,13 +11,8 @@ add_executable(NzbFileTest
${CMAKE_SOURCE_DIR}/daemon/util/NString.cpp
${CMAKE_SOURCE_DIR}/daemon/util/Log.cpp
${CMAKE_SOURCE_DIR}/daemon/nntp/NewsServer.cpp
- ${CMAKE_SOURCE_DIR}/lib/regex/regex.c
-)
-target_link_libraries(NzbFileTest PRIVATE
- ZLIB::ZLIB
- Yencode
- LibXml2::LibXml2
)
+target_link_libraries(NzbFileTest PRIVATE ${LIBS})
target_include_directories(NzbFileTest PRIVATE
${CMAKE_SOURCE_DIR}/daemon/main
${CMAKE_SOURCE_DIR}/daemon/util
@@ -26,9 +21,7 @@ target_include_directories(NzbFileTest PRIVATE
${CMAKE_SOURCE_DIR}/daemon/remote
${CMAKE_SOURCE_DIR}/daemon/nntp
${CMAKE_SOURCE_DIR}/lib/yencode
- ${OPENSSL_INCLUDE_DIR}
- ${Boost_INCLUDE_DIR}
- ${LIBXML2_INCLUDE_DIR}
+ ${INCLUDES}
)
file(COPY ../testdata/nzbfile DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
diff --git a/tests/queue/NzbFileTest.cpp b/tests/queue/NzbFileTest.cpp
index b5a1771f1..ce119f9f2 100644
--- a/tests/queue/NzbFileTest.cpp
+++ b/tests/queue/NzbFileTest.cpp
@@ -23,12 +23,11 @@
#define BOOST_TEST_MODULE "NzbFileTest"
#include
-#include
-
#include "NzbFile.h"
#include "Log.h"
#include "Options.h"
#include "DiskState.h"
+#include "FileSystem.h"
Log* g_Log;
Options* g_Options;
@@ -36,9 +35,7 @@ DiskState* g_DiskState;
void TestNzb(std::string testFilename)
{
- BOOST_TEST_MESSAGE(std::string("Filename: ") + testFilename);
-
- std::string path = std::filesystem::current_path().string();
+ std::string path = FileSystem::GetCurrentDirectory().Str();
std::string nzbFilename(path + "/nzbfile/" + testFilename + ".nzb");
std::string infoFilename(path + "/nzbfile/" + testFilename + ".txt");
@@ -73,7 +70,7 @@ void TestNzb(std::string testFilename)
xmlCleanupParser();
}
-BOOST_AUTO_TEST_CASE(NZBParser)
+BOOST_AUTO_TEST_CASE(NZBParserTest)
{
Options::CmdOptList cmdOpts;
Options options(&cmdOpts, nullptr);
diff --git a/tests/util/CMakeLists.txt b/tests/util/CMakeLists.txt
index 480719680..bff0dbd18 100644
--- a/tests/util/CMakeLists.txt
+++ b/tests/util/CMakeLists.txt
@@ -9,25 +9,11 @@ file(GLOB UtilTestSrc
${CMAKE_SOURCE_DIR}/daemon/util/Util.cpp
${CMAKE_SOURCE_DIR}/daemon/util/Json.cpp
${CMAKE_SOURCE_DIR}/daemon/util/Xml.cpp
- ${CMAKE_SOURCE_DIR}/lib/regex/regex.c
)
add_executable(UtilTests ${UtilTestSrc})
-target_link_libraries(UtilTests PRIVATE
- ZLIB::ZLIB
- Yencode
- LibXml2::LibXml2
-)
+target_link_libraries(UtilTests PRIVATE ${LIBS})
-target_include_directories(UtilTests PRIVATE
- ${CMAKE_SOURCE_DIR}/daemon/main
- ${CMAKE_SOURCE_DIR}/daemon/util
- ${CMAKE_SOURCE_DIR}/lib/regex
- ${CMAKE_SOURCE_DIR}/lib/yencode
- ${ZLIB_INCLUDE_DIR}
- ${OPENSSL_INCLUDE_DIR}
- ${Boost_INCLUDE_DIR}
- ${LIBXML2_INCLUDE_DIR}
-)
+target_include_directories(UtilTests PRIVATE ${INCLUDES})
add_test(NAME UtilTests COMMAND $ --log_level=message)
From f273f7e2d0922383ed99d63c7ab3853955c18685 Mon Sep 17 00:00:00 2001
From: Denis <146707790+dnzbk@users.noreply.github.com>
Date: Wed, 6 Mar 2024 01:52:13 -0800
Subject: [PATCH 16/42] CMake fixies (#192)
---
CMakeLists.txt | 6 ++----
cmake/posix.cmake | 2 ++
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 556ff66c6..c455a8880 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -40,9 +40,8 @@ if(CMAKE_BUILD_TYPE STREQUAL "Debug")
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
set(CMAKE_CXX_FLAGS "-O0 -g0 -pthread -g -Wall -Wextra" CACHE STRING "" FORCE)
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
- set(CMAKE_CXX_FLAGS "/Od /Zi /MP /W4 /EHs /DDEBUG /D_DEBUG /DWIN32 /wd4800 /wd4267" CACHE STRING "" FORCE)
+ set(CMAKE_CXX_FLAGS "/Od /Zi /MTd /MP /W4 /EHs /DDEBUG /D_DEBUG /DWIN32 /wd4800 /wd4267" CACHE STRING "" FORCE)
set(CMAKE_CXX_STANDARD_LIBRARIES "${CMAKE_CXX_STANDARD_LIBRARIES} winmm.lib Dbghelp.lib libcpmtd.lib" CACHE STRING "" FORCE)
- set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreadedDebug" CACHE STRING "" FORCE)
endif()
elseif(CMAKE_BUILD_TYPE STREQUAL "Release")
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang|AppleClang")
@@ -52,9 +51,8 @@ elseif(CMAKE_BUILD_TYPE STREQUAL "Release")
set(CMAKE_CXX_FLAGS "-O2 -g0 -pthread -DNDEBUG -Wall -Wextra" CACHE STRING "" FORCE)
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "-s" CACHE STRING "" FORCE)
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
- set(CMAKE_CXX_FLAGS "/O2 /MP /W4 /EHs /DNDEBUG /DWIN32 /wd4800 /wd4267" CACHE STRING "" FORCE)
+ set(CMAKE_CXX_FLAGS "/O2 /MT /MP /W4 /EHs /DNDEBUG /DWIN32 /wd4800 /wd4267" CACHE STRING "" FORCE)
set(CMAKE_CXX_STANDARD_LIBRARIES "${CMAKE_CXX_STANDARD_LIBRARIES} winmm.lib" CACHE STRING "" FORCE)
- set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded" CACHE STRING "" FORCE)
endif()
endif()
diff --git a/cmake/posix.cmake b/cmake/posix.cmake
index 376d92ea1..ff46d04e2 100644
--- a/cmake/posix.cmake
+++ b/cmake/posix.cmake
@@ -285,6 +285,8 @@ check_cxx_source_compiles("
# Check TLS/SSL
if(USE_OPENSSL AND NOT ENABLE_STATIC)
check_library_exists(OpenSSL::Crypto X509_check_host "" HAVE_X509_CHECK_HOST)
+elseif(USE_OPENSSL AND ENABLE_STATIC)
+ set(HAVE_X509_CHECK_HOST 1)
endif()
check_cxx_source_compiles("
From e104151521d44b769beb47db3f282d9ec4f1eb2d Mon Sep 17 00:00:00 2001
From: Denis <146707790+dnzbk@users.noreply.github.com>
Date: Wed, 6 Mar 2024 23:02:58 -0800
Subject: [PATCH 17/42] Fix/v1 extension loader (#193)
## Description
Added:
- additional checks that "select options" are at the end of the string line;
- more unit tests;
## Testing
By @dnzbk with all available extensions in the Extension manager + NotifyPlex;
---
daemon/extension/ExtensionLoader.cpp | 13 +++++++++----
tests/extension/ExtensionLoaderTest.cpp | 24 ++++++++++++++++++++++--
tests/testdata/extension/V1/Extension.py | 10 ++++++++++
3 files changed, 41 insertions(+), 6 deletions(-)
diff --git a/daemon/extension/ExtensionLoader.cpp b/daemon/extension/ExtensionLoader.cpp
index c5135f7a4..72317b107 100644
--- a/daemon/extension/ExtensionLoader.cpp
+++ b/daemon/extension/ExtensionLoader.cpp
@@ -226,11 +226,11 @@ namespace ExtensionLoader
size_t selectStartIdx = line.rfind("(");
size_t selectEndIdx = line.rfind(")");
- bool hasSelectOptions = selectStartIdx != std::string::npos
- && description.empty()
+ bool hasSelectOptions = description.empty()
+ && !strncmp(line.c_str(), "# ", 2)
+ && selectStartIdx != std::string::npos
&& selectEndIdx != std::string::npos
- && selectEndIdx != std::string::npos
- && !strncmp(line.c_str(), "# ", 2);
+ && selectEndIdx == line.length() - 2;
// e.g. # Description (Always, OnFailure) or # Description (1-65535) or # Description (1, 2-5, 10).
if (hasSelectOptions)
@@ -411,6 +411,11 @@ namespace ExtensionLoader
word += str[i];
}
+ if (elements.size() == 1)
+ {
+ return std::make_pair(std::move(elements), "");
+ }
+
return std::make_pair(std::move(elements), ",");
}
}
diff --git a/tests/extension/ExtensionLoaderTest.cpp b/tests/extension/ExtensionLoaderTest.cpp
index e48bc6d2e..a495e5d6b 100644
--- a/tests/extension/ExtensionLoaderTest.cpp
+++ b/tests/extension/ExtensionLoaderTest.cpp
@@ -79,7 +79,7 @@ BOOST_AUTO_TEST_CASE(ExtensionV1LoaderTest)
BOOST_CHECK(command2.action == "Send Test");
BOOST_CHECK(command2.description == std::vector({ "Test (0 1).", "description." }));
- BOOST_CHECK(extension.GetOptions().size() == 14);
+ BOOST_CHECK(extension.GetOptions().size() == 16);
auto option = extension.GetOptions()[0];
@@ -220,6 +220,26 @@ BOOST_AUTO_TEST_CASE(ExtensionV1LoaderTest)
"ionice scheduling class.",
"Set the ionice scheduling class (0, 1, 2, 3)."
}));
- BOOST_CHECK(boost::variant2::get(option13.value) == "2");
+ BOOST_CHECK(boost::variant2::get(option14.value) == "2");
BOOST_CHECK(option14.select.empty());
+
+ auto option15 = extension.GetOptions()[14];
+ BOOST_CHECK(option15.name == "customPlexSection");
+ BOOST_CHECK(option15.displayName == "customPlexSection");
+ BOOST_CHECK(option15.description == std::vector({
+ "Custom Plex Section(s) you would like to update [Optional].",
+ "Section Number(s) corresponding to your Plex library (comma separated)."
+ }));
+ BOOST_CHECK(boost::variant2::get(option15.value) == "");
+ BOOST_CHECK(option15.select.empty());
+
+ auto option16 = extension.GetOptions()[15];
+ BOOST_CHECK(option16.name == "test2");
+ BOOST_CHECK(option16.displayName == "test2");
+ BOOST_CHECK(option16.description == std::vector({
+ "(Test2).",
+ "description."
+ }));
+ BOOST_CHECK(boost::variant2::get(option16.value) == "");
+ BOOST_CHECK(option16.select.empty());
}
diff --git a/tests/testdata/extension/V1/Extension.py b/tests/testdata/extension/V1/Extension.py
index 2dba2ea15..ca84e6591 100644
--- a/tests/testdata/extension/V1/Extension.py
+++ b/tests/testdata/extension/V1/Extension.py
@@ -88,5 +88,15 @@
# description.
#Test@Send Test
+# Custom Plex Section(s) you would like to update [Optional].
+#
+# Section Number(s) corresponding to your Plex library (comma separated).
+#customPlexSection=
+
+# (Test2).
+#
+# description.
+#test2=
+
### NZBGET POST-PROCESSING SCRIPT ###
##############################################################################
From f84e39da8e059b31e4ba213b1f1a1286ece7af04 Mon Sep 17 00:00:00 2001
From: Denis <146707790+dnzbk@users.noreply.github.com>
Date: Mon, 11 Mar 2024 09:42:15 +0300
Subject: [PATCH 18/42] Fix: compiler and cppcheck warnings (#197)
## Description
- removed unnecessary empty namespaces;
- use std::string instead of custom BString due to potential memory corruption;
- added the recommended & qualifier to GetExtensions method;
## Testing
By @dnzbk on:
- Windows 11;
- Debian 12;
---
daemon/extension/Extension.cpp | 25 +-
daemon/extension/Extension.h | 7 +-
daemon/extension/ExtensionLoader.cpp | 381 +++++++++++++-------------
daemon/extension/ExtensionLoader.h | 33 +--
daemon/extension/ExtensionManager.cpp | 11 +-
daemon/extension/ExtensionManager.h | 2 +-
daemon/extension/ManifestFile.cpp | 251 +++++++++--------
daemon/extension/ManifestFile.h | 16 +-
8 files changed, 353 insertions(+), 373 deletions(-)
diff --git a/daemon/extension/Extension.cpp b/daemon/extension/Extension.cpp
index 044fbad22..e6ab2bbda 100644
--- a/daemon/extension/Extension.cpp
+++ b/daemon/extension/Extension.cpp
@@ -416,21 +416,18 @@ namespace Extension
return result;
}
- namespace
+ void AddNewNode(xmlNodePtr rootNode, const char* name, const char* type, const char* value)
{
- void AddNewNode(xmlNodePtr rootNode, const char* name, const char* type, const char* value)
- {
- xmlNodePtr memberNode = xmlNewNode(NULL, BAD_CAST "member");
- xmlNodePtr valueNode = xmlNewNode(NULL, BAD_CAST "value");
- xmlNewChild(memberNode, NULL, BAD_CAST "name", BAD_CAST name);
- xmlNewChild(valueNode, NULL, BAD_CAST type, BAD_CAST value);
- xmlAddChild(memberNode, valueNode);
- xmlAddChild(rootNode, memberNode);
- }
+ xmlNodePtr memberNode = xmlNewNode(NULL, BAD_CAST "member");
+ xmlNodePtr valueNode = xmlNewNode(NULL, BAD_CAST "value");
+ xmlNewChild(memberNode, NULL, BAD_CAST "name", BAD_CAST name);
+ xmlNewChild(valueNode, NULL, BAD_CAST type, BAD_CAST value);
+ xmlAddChild(memberNode, valueNode);
+ xmlAddChild(rootNode, memberNode);
+ }
- const char* BoolToStr(bool value)
- {
- return value ? "true" : "false";
- }
+ const char* BoolToStr(bool value)
+ {
+ return value ? "true" : "false";
}
}
diff --git a/daemon/extension/Extension.h b/daemon/extension/Extension.h
index 6e3e7ef11..dd4f04078 100644
--- a/daemon/extension/Extension.h
+++ b/daemon/extension/Extension.h
@@ -107,11 +107,8 @@ namespace Extension
std::string ToJsonStr(const Script& script);
std::string ToXmlStr(const Script& script);
- namespace
- {
- void AddNewNode(xmlNodePtr rootNode, const char* name, const char* type, const char* value);
- const char* BoolToStr(bool value);
- }
+ static void AddNewNode(xmlNodePtr rootNode, const char* name, const char* type, const char* value);
+ static const char* BoolToStr(bool value);
}
#endif
diff --git a/daemon/extension/ExtensionLoader.cpp b/daemon/extension/ExtensionLoader.cpp
index 72317b107..5ade183f8 100644
--- a/daemon/extension/ExtensionLoader.cpp
+++ b/daemon/extension/ExtensionLoader.cpp
@@ -181,243 +181,241 @@ namespace ExtensionLoader
return true;
}
- namespace
+
+ void RemoveTailAndTrim(std::string& str, const char* tail)
{
- void RemoveTailAndTrim(std::string& str, const char* tail)
+ size_t tailIdx = str.find(tail);
+ if (tailIdx != std::string::npos)
{
- size_t tailIdx = str.find(tail);
- if (tailIdx != std::string::npos)
- {
- str.erase(tailIdx);
- }
- Util::TrimRight(str);
+ str.erase(tailIdx);
}
+ Util::TrimRight(str);
+ }
- void BuildDisplayName(Extension::Script& script)
- {
- BString<1024> shortName = script.GetName();
- if (char* ext = strrchr(shortName, '.')) *ext = '\0'; // strip file extension
+ void BuildDisplayName(Extension::Script& script)
+ {
+ BString<1024> shortName = script.GetName();
+ if (char* ext = strrchr(shortName, '.')) *ext = '\0'; // strip file extension
- const char* displayName = FileSystem::BaseFileName(shortName);
+ const char* displayName = FileSystem::BaseFileName(shortName);
- script.SetDisplayName(displayName);
- }
+ script.SetDisplayName(displayName);
+ }
+
+ void ParseOptionsAndCommands(
+ std::ifstream& file,
+ std::vector& options,
+ std::vector& commands)
+ {
+ std::vector selectOpts;
+ std::vector description;
- void ParseOptionsAndCommands(
- std::ifstream& file,
- std::vector& options,
- std::vector& commands)
+ std::string line;
+ while (std::getline(file, line))
{
- std::vector selectOpts;
- std::vector description;
+ if (strstr(line.c_str(), END_SCRIPT_SIGNATURE))
+ {
+ break;
+ }
+
+ if (line.empty())
+ {
+ continue;
+ }
- std::string line;
- while (std::getline(file, line))
+ size_t selectStartIdx = line.rfind("(");
+ size_t selectEndIdx = line.rfind(")");
+ bool hasSelectOptions = description.empty()
+ && !strncmp(line.c_str(), "# ", 2)
+ && selectStartIdx != std::string::npos
+ && selectEndIdx != std::string::npos
+ && selectEndIdx == line.length() - 2;
+
+ // e.g. # Description (Always, OnFailure) or # Description (1-65535) or # Description (1, 2-5, 10).
+ if (hasSelectOptions)
{
- if (strstr(line.c_str(), END_SCRIPT_SIGNATURE))
+ std::string selectOptionsStr = line.substr(selectStartIdx + 1, selectEndIdx - selectStartIdx - 1);
+ auto result = ExtractElements(selectOptionsStr);
+ auto& selectOptions = result.first;
+ auto& delimiter = result.second;
+ bool canBeNum = delimiter == "-";
+
+ if (delimiter.empty()) // doesn't have
{
- break;
+ description.push_back(line.substr(2));
+ continue;
}
- if (line.empty())
+ if (canBeNum)
{
- continue;
+ description.push_back(line.substr(2));
+ }
+ else
+ {
+ description.push_back(line.substr(2, selectStartIdx - 3) + ".");
}
- size_t selectStartIdx = line.rfind("(");
- size_t selectEndIdx = line.rfind(")");
- bool hasSelectOptions = description.empty()
- && !strncmp(line.c_str(), "# ", 2)
- && selectStartIdx != std::string::npos
- && selectEndIdx != std::string::npos
- && selectEndIdx == line.length() - 2;
+ selectOpts = GetSelectOptions(selectOptions, canBeNum);
+ continue;
+ }
- // e.g. # Description (Always, OnFailure) or # Description (1-65535) or # Description (1, 2-5, 10).
- if (hasSelectOptions)
- {
- std::string selectOptionsStr = line.substr(selectStartIdx + 1, selectEndIdx - selectStartIdx - 1);
- auto result = ExtractElements(selectOptionsStr);
- auto& selectOptions = result.first;
- auto& delimiter = result.second;
- bool canBeNum = delimiter == "-";
-
- if (delimiter.empty()) // doesn't have
- {
- description.push_back(line.substr(2));
- continue;
- }
+ if (!strncmp(line.c_str(), "# ", 2))
+ {
+ description.push_back(line.substr(2));
+ continue;
+ }
- if (canBeNum)
- {
- description.push_back(line.substr(2));
- }
- else
- {
- description.push_back(line.substr(2, selectStartIdx - 3) + ".");
- }
+ if (strncmp(line.c_str(), "# ", 2))
+ {
+ // if option, e.g. #ConnectionTest=Send
+ size_t eqPos = line.find("=");
+ // if command, e.g. #ConnectionTest@Send Test E-Mail
+ size_t atPos = line.find("@");
- selectOpts = GetSelectOptions(selectOptions, canBeNum);
+ if (atPos != std::string::npos && eqPos == std::string::npos)
+ {
+ ManifestFile::Command command;
+ std::string name = line.substr(1, atPos - 1);
+ std::string action = line.substr(atPos + 1);
+ Util::Trim(action);
+ Util::Trim(name);
+ command.action = std::move(action);
+ command.name = std::move(name);
+ command.description = std::move(description);
+ command.displayName = command.name;
+ commands.push_back(std::move(command));
+ description.clear();
+ selectOpts.clear();
continue;
}
- if (!strncmp(line.c_str(), "# ", 2))
+ if (eqPos != std::string::npos)
{
- description.push_back(line.substr(2));
+ ManifestFile::Option option;
+ std::string name = line.substr(1, eqPos - 1);
+ std::string value = line.substr(eqPos + 1);
+ Util::Trim(value);
+ Util::Trim(name);
+ bool canBeNum = !selectOpts.empty() && boost::variant2::get_if(&selectOpts[0]);
+ option.value = std::move(GetSelectOpt(value, canBeNum));
+ option.name = std::move(name);
+ option.description = std::move(description);
+ option.select = std::move(selectOpts);
+ option.displayName = option.name;
+ options.push_back(std::move(option));
+ description.clear();
+ selectOpts.clear();
continue;
}
+ }
+ }
+ }
- if (strncmp(line.c_str(), "# ", 2))
- {
- // if option, e.g. #ConnectionTest=Send
- size_t eqPos = line.find("=");
- // if command, e.g. #ConnectionTest@Send Test E-Mail
- size_t atPos = line.find("@");
-
- if (atPos != std::string::npos && eqPos == std::string::npos)
- {
- ManifestFile::Command command;
- std::string name = line.substr(1, atPos - 1);
- std::string action = line.substr(atPos + 1);
- Util::Trim(action);
- Util::Trim(name);
- command.action = std::move(action);
- command.name = std::move(name);
- command.description = std::move(description);
- command.displayName = command.name;
- commands.push_back(std::move(command));
- description.clear();
- selectOpts.clear();
- continue;
- }
+ std::vector
+ GetSelectOptions(const std::vector& opts, bool canBeNum)
+ {
+ std::vector selectOpts;
- if (eqPos != std::string::npos)
- {
- ManifestFile::Option option;
- std::string name = line.substr(1, eqPos - 1);
- std::string value = line.substr(eqPos + 1);
- Util::Trim(value);
- Util::Trim(name);
- bool canBeNum = !selectOpts.empty() && boost::variant2::get_if(&selectOpts[0]);
- option.value = std::move(GetSelectOpt(value, canBeNum));
- option.name = std::move(name);
- option.description = std::move(description);
- option.select = std::move(selectOpts);
- option.displayName = option.name;
- options.push_back(std::move(option));
- description.clear();
- selectOpts.clear();
- continue;
- }
- }
- }
+ for (const auto& option : opts)
+ {
+ selectOpts.push_back(GetSelectOpt(option, canBeNum));
}
+ return selectOpts;
+ }
- std::vector
- GetSelectOptions(const std::vector& opts, bool canBeNum)
+ ManifestFile::SelectOption GetSelectOpt(const std::string& val, bool canBeNum)
+ {
+ if (!canBeNum)
{
- std::vector selectOpts;
+ return ManifestFile::SelectOption(val);
+ }
- for (const auto& option : opts)
- {
- selectOpts.push_back(GetSelectOpt(option, canBeNum));
- }
- return selectOpts;
+ auto result = Util::StrToNum(val);
+ if (result.has_value())
+ {
+ return ManifestFile::SelectOption(result.get());
}
- ManifestFile::SelectOption GetSelectOpt(const std::string& val, bool canBeNum)
+ return ManifestFile::SelectOption(val);
+ }
+
+ std::pair, std::string>
+ ExtractElements(const std::string& str)
+ {
+ std::vector elements;
+ std::string word;
+
+ for (size_t i = 0; i < str.size(); ++i)
{
- if (!canBeNum)
+ if (i == (str.size() - 1))
{
- return ManifestFile::SelectOption(val);
+ word += str[i];
+ elements.push_back(std::move(word));
+ break;
}
- auto result = Util::StrToNum(val);
- if (result.has_value())
+ if (str[i] == ',')
{
- return ManifestFile::SelectOption(result.get());
+ elements.push_back(std::move(word));
+ word.clear();
+ continue;
}
- return ManifestFile::SelectOption(val);
- }
-
- std::pair, std::string>
- ExtractElements(const std::string& str)
- {
- std::vector elements;
- std::string word;
-
- for (size_t i = 0; i < str.size(); ++i)
+ if (str[i] == ' ' && word.empty())
{
- if (i == str.size() - 1)
- {
- word += str[i];
- elements.push_back(std::move(word));
- break;
- }
-
- if (str[i] == ',')
- {
- elements.push_back(std::move(word));
- word.clear();
- continue;
- }
+ continue;
+ }
- if (str[i] == ' ' && word.empty())
- {
- continue;
- }
+ if (str[i] == ' ' && !word.empty())
+ {
+ elements.clear();
+ elements.push_back(str);
+ return std::make_pair(std::move(elements), "");
+ }
- if (str[i] == ' ' && !word.empty())
+ if (str[i] == '-' && elements.empty())
+ {
+ std::string restWord;
+ for (size_t j = i + 1; j < str.size(); ++j)
{
- elements.clear();
- elements.push_back(str);
- return std::make_pair(std::move(elements), "");
- }
+ if (j >= str.size() - 1)
+ {
+ restWord += str[j];
+ elements.push_back(std::move(word));
+ elements.push_back(std::move(restWord));
+ return std::make_pair(std::move(elements), "-");
+ }
- if (str[i] == '-' && elements.empty())
- {
- std::string restWord;
- for (size_t j = i + 1; j < str.size(); ++j)
+ if (str[j] == ' ')
{
- if (j >= str.size() - 1)
- {
- restWord += str[j];
- elements.push_back(std::move(word));
- elements.push_back(std::move(restWord));
- return std::make_pair(std::move(elements), "-");
- }
-
- if (str[j] == ' ')
- {
- elements.push_back(str);
- return std::make_pair(std::move(elements), "");
- }
-
- if (str[j] == ',')
- {
- word += '-' + restWord;
- elements.push_back(std::move(word));
- word.clear();
- i = j;
- break;
- }
+ elements.push_back(str);
+ return std::make_pair(std::move(elements), "");
+ }
- restWord += str[j];
+ if (str[j] == ',')
+ {
+ word += '-' + restWord;
+ elements.push_back(std::move(word));
+ word.clear();
+ i = j;
+ break;
}
- continue;
+ restWord += str[j];
}
- word += str[i];
+ continue;
}
- if (elements.size() == 1)
- {
- return std::make_pair(std::move(elements), "");
- }
+ word += str[i];
+ }
- return std::make_pair(std::move(elements), ",");
+ if (elements.size() == 1)
+ {
+ return std::make_pair(std::move(elements), "");
}
+
+ return std::make_pair(std::move(elements), ",");
}
}
@@ -448,17 +446,14 @@ namespace ExtensionLoader
return true;
}
- namespace
+ Extension::Kind GetScriptKind(const std::string& line)
{
- Extension::Kind GetScriptKind(const std::string& line)
- {
- Extension::Kind kind;
- kind.post = strstr(line.c_str(), POST_SCRIPT_SIGNATURE) != nullptr;
- kind.scan = strstr(line.c_str(), SCAN_SCRIPT_SIGNATURE) != nullptr;
- kind.queue = strstr(line.c_str(), QUEUE_SCRIPT_SIGNATURE) != nullptr;
- kind.scheduler = strstr(line.c_str(), SCHEDULER_SCRIPT_SIGNATURE) != nullptr;
- kind.feed = strstr(line.c_str(), FEED_SCRIPT_SIGNATURE) != nullptr;
- return kind;
- }
+ Extension::Kind kind;
+ kind.post = strstr(line.c_str(), POST_SCRIPT_SIGNATURE) != nullptr;
+ kind.scan = strstr(line.c_str(), SCAN_SCRIPT_SIGNATURE) != nullptr;
+ kind.queue = strstr(line.c_str(), QUEUE_SCRIPT_SIGNATURE) != nullptr;
+ kind.scheduler = strstr(line.c_str(), SCHEDULER_SCRIPT_SIGNATURE) != nullptr;
+ kind.feed = strstr(line.c_str(), FEED_SCRIPT_SIGNATURE) != nullptr;
+ return kind;
}
}
diff --git a/daemon/extension/ExtensionLoader.h b/daemon/extension/ExtensionLoader.h
index 1fb504c5e..916e8c626 100644
--- a/daemon/extension/ExtensionLoader.h
+++ b/daemon/extension/ExtensionLoader.h
@@ -47,21 +47,19 @@ namespace ExtensionLoader
namespace V1
{
bool Load(Extension::Script& script, const char* location, const char* rootDir);
- namespace
- {
- void ParseOptionsAndCommands(
- std::ifstream& file,
- std::vector& options,
- std::vector& commands
- );
- std::vector
- GetSelectOptions(const std::vector& opts, bool isDashDelim);
- ManifestFile::SelectOption GetSelectOpt(const std::string& val, bool canBeNum);
- void RemoveTailAndTrim(std::string& str, const char* tail);
- void BuildDisplayName(Extension::Script& script);
- std::pair, std::string>
- ExtractElements(const std::string& str);
- }
+
+ static void ParseOptionsAndCommands(
+ std::ifstream& file,
+ std::vector& options,
+ std::vector& commands
+ );
+ static std::vector
+ GetSelectOptions(const std::vector& opts, bool isDashDelim);
+ static ManifestFile::SelectOption GetSelectOpt(const std::string& val, bool canBeNum);
+ static void RemoveTailAndTrim(std::string& str, const char* tail);
+ static void BuildDisplayName(Extension::Script& script);
+ static std::pair, std::string>
+ ExtractElements(const std::string& str);
}
namespace V2
@@ -69,10 +67,7 @@ namespace ExtensionLoader
bool Load(Extension::Script& script, const char* location, const char* rootDir);
}
- namespace
- {
- Extension::Kind GetScriptKind(const std::string& line);
- }
+ static Extension::Kind GetScriptKind(const std::string& line);
}
#endif
diff --git a/daemon/extension/ExtensionManager.cpp b/daemon/extension/ExtensionManager.cpp
index 4f0c088db..550ff4def 100644
--- a/daemon/extension/ExtensionManager.cpp
+++ b/daemon/extension/ExtensionManager.cpp
@@ -29,7 +29,7 @@
namespace ExtensionManager
{
- const Extensions& Manager::GetExtensions() const
+ const Extensions& Manager::GetExtensions() const &
{
std::shared_lock lock{m_mutex};
return m_extensions;
@@ -38,20 +38,21 @@ namespace ExtensionManager
std::pair
Manager::DownloadExtension(const std::string& url, const std::string& extName)
{
- BString<1024> tmpFileName;
- tmpFileName.Format("%s%cextension-%s.tmp.zip", g_Options->GetTempDir(), PATH_SEPARATOR, extName.c_str());
+ std::string tmpFileName = std::string(g_Options->GetTempDir())
+ + PATH_SEPARATOR
+ + "extension-" + extName + ".tmp.zip";
std::unique_ptr downloader = std::make_unique();
downloader->SetUrl(url.c_str());
downloader->SetForce(true);
downloader->SetRetry(false);
- downloader->SetOutputFilename(tmpFileName);
+ downloader->SetOutputFilename(tmpFileName.c_str());
downloader->SetInfoName(extName.c_str());
WebDownloader::EStatus status = downloader->DownloadWithRedirects(5);
downloader.reset();
- return std::make_pair(status, tmpFileName.Str());
+ return std::make_pair(status, std::move(tmpFileName));
}
boost::optional
diff --git a/daemon/extension/ExtensionManager.h b/daemon/extension/ExtensionManager.h
index 6a9c63f9a..d1a8e9c8f 100644
--- a/daemon/extension/ExtensionManager.h
+++ b/daemon/extension/ExtensionManager.h
@@ -60,7 +60,7 @@ namespace ExtensionManager
std::pair
DownloadExtension(const std::string& url, const std::string& info);
- const Extensions& GetExtensions() const;
+ const Extensions& GetExtensions() const &;
private:
void LoadExtensionDir(const char* directory, bool isSubDir, const char* rootDir);
diff --git a/daemon/extension/ManifestFile.cpp b/daemon/extension/ManifestFile.cpp
index bed19e5ef..d96836c12 100644
--- a/daemon/extension/ManifestFile.cpp
+++ b/daemon/extension/ManifestFile.cpp
@@ -48,185 +48,182 @@ namespace ManifestFile
return true;
}
- namespace
+ bool ValidateAndSet(const Json::JsonObject& json, Manifest& manifest)
{
- bool ValidateAndSet(const Json::JsonObject& json, Manifest& manifest)
- {
- if (!CheckKeyAndSet(json, "author", manifest.author))
- return false;
+ if (!CheckKeyAndSet(json, "author", manifest.author))
+ return false;
- if (!CheckKeyAndSet(json, "main", manifest.main))
- return false;
+ if (!CheckKeyAndSet(json, "main", manifest.main))
+ return false;
- if (!CheckKeyAndSet(json, "homepage", manifest.homepage))
- return false;
+ if (!CheckKeyAndSet(json, "homepage", manifest.homepage))
+ return false;
- if (!CheckKeyAndSet(json, "about", manifest.about))
- return false;
+ if (!CheckKeyAndSet(json, "about", manifest.about))
+ return false;
- if (!CheckKeyAndSet(json, "version", manifest.version))
- return false;
+ if (!CheckKeyAndSet(json, "version", manifest.version))
+ return false;
- if (!CheckKeyAndSet(json, "name", manifest.name))
- return false;
+ if (!CheckKeyAndSet(json, "name", manifest.name))
+ return false;
- if (!CheckKeyAndSet(json, "displayName", manifest.displayName))
- return false;
+ if (!CheckKeyAndSet(json, "displayName", manifest.displayName))
+ return false;
- if (!CheckKeyAndSet(json, "kind", manifest.kind))
- return false;
+ if (!CheckKeyAndSet(json, "kind", manifest.kind))
+ return false;
- if (!CheckKeyAndSet(json, "license", manifest.license))
- return false;
+ if (!CheckKeyAndSet(json, "license", manifest.license))
+ return false;
- if (!CheckKeyAndSet(json, "taskTime", manifest.taskTime))
- return false;
+ if (!CheckKeyAndSet(json, "taskTime", manifest.taskTime))
+ return false;
- if (!CheckKeyAndSet(json, "queueEvents", manifest.queueEvents))
- return false;
+ if (!CheckKeyAndSet(json, "queueEvents", manifest.queueEvents))
+ return false;
- if (!ValidateOptionsAndSet(json, manifest.options))
- return false;
+ if (!ValidateOptionsAndSet(json, manifest.options))
+ return false;
- if (!ValidateCommandsAndSet(json, manifest.commands))
- return false;
+ if (!ValidateCommandsAndSet(json, manifest.commands))
+ return false;
+
+ if (!ValidateTxtAndSet(json, manifest.description, "description"))
+ return false;
- if (!ValidateTxtAndSet(json, manifest.description, "description"))
- return false;
+ if (!ValidateTxtAndSet(json, manifest.requirements, "requirements"))
+ return false;
- if (!ValidateTxtAndSet(json, manifest.requirements, "requirements"))
- return false;
+ return true;
+ }
- return true;
- }
+ bool ValidateCommandsAndSet(const Json::JsonObject& json, std::vector& commands)
+ {
+ auto rawCommands = json.if_contains("commands");
+ if (!rawCommands || !rawCommands->is_array())
+ return false;
- bool ValidateCommandsAndSet(const Json::JsonObject& json, std::vector& commands)
+ for (auto& value : rawCommands->as_array())
{
- auto rawCommands = json.if_contains("commands");
- if (!rawCommands || !rawCommands->is_array())
- return false;
+ Json::JsonObject cmdJson = value.as_object();
+ Command command;
- for (auto& value : rawCommands->as_array())
- {
- Json::JsonObject cmdJson = value.as_object();
- Command command;
+ if (!CheckKeyAndSet(cmdJson, "name", command.name))
+ continue;
- if (!CheckKeyAndSet(cmdJson, "name", command.name))
- continue;
+ if (!CheckKeyAndSet(cmdJson, "displayName", command.displayName))
+ continue;
- if (!CheckKeyAndSet(cmdJson, "displayName", command.displayName))
- continue;
+ if (!ValidateTxtAndSet(cmdJson, command.description, "description"))
+ continue;
- if (!ValidateTxtAndSet(cmdJson, command.description, "description"))
- continue;
+ if (!CheckKeyAndSet(cmdJson, "action", command.action))
+ continue;
- if (!CheckKeyAndSet(cmdJson, "action", command.action))
- continue;
+ commands.emplace_back(std::move(command));
+ }
- commands.emplace_back(std::move(command));
- }
+ commands.shrink_to_fit();
- commands.shrink_to_fit();
+ return true;
+ }
- return true;
- }
+ bool ValidateOptionsAndSet(const Json::JsonObject& json, std::vector& options)
+ {
+ auto rawOptions = json.if_contains("options");
+ if (!rawOptions || !rawOptions->is_array())
+ return false;
- bool ValidateOptionsAndSet(const Json::JsonObject& json, std::vector & options)
+ for (auto& optionVal : rawOptions->as_array())
{
- auto rawOptions = json.if_contains("options");
- if (!rawOptions || !rawOptions->is_array())
- return false;
+ Json::JsonObject optionJson = optionVal.as_object();
+ auto selectJson = optionJson.if_contains("select");
+ if (!selectJson || !selectJson->is_array())
+ continue;
- for (auto& optionVal : rawOptions->as_array())
- {
- Json::JsonObject optionJson = optionVal.as_object();
- auto selectJson = optionJson.if_contains("select");
- if (!selectJson || !selectJson->is_array())
- continue;
+ Option option;
+ if (!CheckKeyAndSet(optionJson, "name", option.name))
+ continue;
- Option option;
- if (!CheckKeyAndSet(optionJson, "name", option.name))
- continue;
+ if (!CheckKeyAndSet(optionJson, "displayName", option.displayName))
+ continue;
- if (!CheckKeyAndSet(optionJson, "displayName", option.displayName))
- continue;
+ if (!CheckKeyAndSet(optionJson, "value", option.value))
+ continue;
- if (!CheckKeyAndSet(optionJson, "value", option.value))
- continue;
+ if (!ValidateTxtAndSet(optionJson, option.description, "description"))
+ continue;
- if (!ValidateTxtAndSet(optionJson, option.description, "description"))
+ for (auto& selectVal : selectJson->as_array())
+ {
+ if (selectVal.is_string())
+ {
+ option.select.emplace_back(selectVal.get_string().c_str());
continue;
-
- for (auto& selectVal : selectJson->as_array())
+ }
+ if (selectVal.is_number())
{
- if (selectVal.is_string())
- {
- option.select.emplace_back(selectVal.get_string().c_str());
- continue;
- }
- if (selectVal.is_number())
- {
- option.select.emplace_back(selectVal.to_number());
- continue;
- }
+ option.select.emplace_back(selectVal.to_number());
+ continue;
}
-
- options.emplace_back(std::move(option));
}
- options.shrink_to_fit();
-
- return true;
+ options.emplace_back(std::move(option));
}
- bool ValidateTxtAndSet(const Json::JsonObject& json, std::vector& property, const char* propName)
- {
- auto rawProp = json.if_contains(propName);
- if (!rawProp || !rawProp->is_array())
- return false;
+ options.shrink_to_fit();
+
+ return true;
+ }
- for (auto& value : rawProp->as_array())
+ bool ValidateTxtAndSet(const Json::JsonObject& json, std::vector& property, const char* propName)
+ {
+ auto rawProp = json.if_contains(propName);
+ if (!rawProp || !rawProp->is_array())
+ return false;
+
+ for (auto& value : rawProp->as_array())
+ {
+ if (value.is_string())
{
- if (value.is_string())
- {
- property.emplace_back(value.get_string().c_str());
- }
+ property.emplace_back(value.get_string().c_str());
}
+ }
- property.shrink_to_fit();
+ property.shrink_to_fit();
- return true;
- }
+ return true;
+ }
- bool CheckKeyAndSet(const Json::JsonObject& json, const char* key, std::string& property)
- {
- const auto& rawProperty = json.if_contains(key);
- if (!rawProperty || !rawProperty->is_string())
- return false;
+ bool CheckKeyAndSet(const Json::JsonObject& json, const char* key, std::string& property)
+ {
+ const auto& rawProperty = json.if_contains(key);
+ if (!rawProperty || !rawProperty->is_string())
+ return false;
+ property = rawProperty->get_string().c_str();
+ return true;
+ }
+
+ bool CheckKeyAndSet(const Json::JsonObject& json, const char* key, SelectOption& property)
+ {
+ const auto& rawProperty = json.if_contains(key);
+ if (!rawProperty)
+ return false;
+
+ if (rawProperty->is_string())
+ {
property = rawProperty->get_string().c_str();
return true;
}
- bool CheckKeyAndSet(const Json::JsonObject& json, const char* key, SelectOption& property)
+ if (rawProperty->is_number())
{
- const auto& rawProperty = json.if_contains(key);
- if (!rawProperty)
- return false;
-
- if (rawProperty->is_string())
- {
- property = rawProperty->get_string().c_str();
- return true;
- }
-
- if (rawProperty->is_number())
- {
- property = rawProperty->to_number();
- return true;
- }
-
- return false;
+ property = rawProperty->to_number();
+ return true;
}
+
+ return false;
}
}
diff --git a/daemon/extension/ManifestFile.h b/daemon/extension/ManifestFile.h
index 751ab3f7c..494e784e6 100644
--- a/daemon/extension/ManifestFile.h
+++ b/daemon/extension/ManifestFile.h
@@ -68,15 +68,13 @@ namespace ManifestFile
};
bool Load(Manifest& manifest, const char* directory);
- namespace
- {
- bool ValidateAndSet(const Json::JsonObject& json, Manifest& manifest);
- bool ValidateCommandsAndSet(const Json::JsonObject& json, std::vector& commands);
- bool ValidateOptionsAndSet(const Json::JsonObject& json, std::vector& options);
- bool ValidateTxtAndSet(const Json::JsonObject& json, std::vector& property, const char* propName);
- bool CheckKeyAndSet(const Json::JsonObject& json, const char* key, std::string& property);
- bool CheckKeyAndSet(const Json::JsonObject& json, const char* key, SelectOption& property);
- }
+
+ static bool ValidateAndSet(const Json::JsonObject& json, Manifest& manifest);
+ static bool ValidateCommandsAndSet(const Json::JsonObject& json, std::vector& commands);
+ static bool ValidateOptionsAndSet(const Json::JsonObject& json, std::vector& options);
+ static bool ValidateTxtAndSet(const Json::JsonObject& json, std::vector& property, const char* propName);
+ static bool CheckKeyAndSet(const Json::JsonObject& json, const char* key, std::string& property);
+ static bool CheckKeyAndSet(const Json::JsonObject& json, const char* key, SelectOption& property);
};
#endif
From ffcb29d9c1a5e9bed797c9fc5ed82f879da6a8a4 Mon Sep 17 00:00:00 2001
From: phnzb <139914799+phnzb@users.noreply.github.com>
Date: Mon, 11 Mar 2024 11:02:25 +0300
Subject: [PATCH 19/42] Docker - add checks to chown at startup (#195)
---
docker/entrypoint.sh | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh
index 39c2f802c..199e6329b 100644
--- a/docker/entrypoint.sh
+++ b/docker/entrypoint.sh
@@ -34,6 +34,14 @@ PGID=${PGID:-1000}
groupmod -o -g "$PGID" users
usermod -o -u "$PUID" user
-chown -R user:users /config
-chown -R user:users /downloads
+chown -R user:users /config || CONFIG_CHOWN_STATUS=$?
+if [ ! -z $CONFIG_CHOWN_STATUS ]; then
+ echo "*** Could not set permissions on /config ; this container may not work as expected ***"
+fi
+
+chown -R user:users /downloads || DOWNLOADS_CHOWN_STATUS=$?
+if [ ! -z $DOWNLOADS_CHOWN_STATUS ]; then
+ echo "*** Could not set permissions on /downloads ; this container may not work as expected ***"
+fi
+
su -p user -c "/app/nzbget/nzbget -s -c /config/nzbget.conf -o OutputMode=log ${OPTIONS}"
From 90a89f8fb3b81432e192203e8a66419cfd3cd723 Mon Sep 17 00:00:00 2001
From: phnzb <139914799+phnzb@users.noreply.github.com>
Date: Mon, 11 Mar 2024 12:05:55 +0300
Subject: [PATCH 20/42] macOS x64 build support (macOS Mojave 10.14+) (#194)
---
.github/workflows/build.yml | 2 +
.github/workflows/osx.yml | 77 +++++++++++++++-
README.md | 2 +-
osx/build-info.md | 48 +++++++---
...ld-nzbget.sh => build-nzbget-universal.sh} | 2 +-
osx/build-nzbget-x64.sh | 92 +++++++++++++++++++
6 files changed, 206 insertions(+), 17 deletions(-)
rename osx/{build-nzbget.sh => build-nzbget-universal.sh} (98%)
create mode 100644 osx/build-nzbget-x64.sh
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index e628e6177..73f117792 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -16,6 +16,8 @@ jobs:
build-osx:
uses: ./.github/workflows/osx.yml
+ permissions:
+ actions: write
build-synology:
uses: ./.github/workflows/synology.yml
diff --git a/.github/workflows/osx.yml b/.github/workflows/osx.yml
index f4f1c4909..80ba53624 100644
--- a/.github/workflows/osx.yml
+++ b/.github/workflows/osx.yml
@@ -5,8 +5,47 @@ on:
workflow_dispatch:
jobs:
- build:
- runs-on: [self-hosted, macos]
+ build-x64:
+ runs-on: [self-hosted, macos, x64]
+
+ steps:
+
+ - name: Checkout
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+
+ - name: Change version for non-release
+ if: github.ref_name != 'main'
+ run: |
+ VERSION=$(grep "set(VERSION" CMakeLists.txt | cut -d '"' -f 2)
+ NEW_VERSION="$VERSION-testing-$(date '+%Y%m%d')"
+ echo NEW_VERSION=$NEW_VERSION >> $GITHUB_ENV
+
+ - name: Build
+ run: |
+ bash osx/build-nzbget-x64.sh
+
+ - name: Rename build artifacts
+ if: github.ref_name != 'main' && github.ref_name != 'develop'
+ run: |
+ cd tmp
+ NEW_VERSION_FEATURE="$NEW_VERSION-${GITHUB_REF_NAME/\//-}"
+ for FILE in *.zip; do
+ [ -f $FILE ] || continue
+ NEW_FILE=${FILE/$NEW_VERSION/$NEW_VERSION_FEATURE}
+ mv $FILE $NEW_FILE
+ done
+
+ - name: Upload build artifacts
+ uses: actions/upload-artifact@v4
+ with:
+ name: nzbget-osx-installers-x64
+ path: tmp/*.zip
+ retention-days: 5
+
+ build-universal:
+ runs-on: [self-hosted, macos, arm64]
steps:
@@ -25,7 +64,7 @@ jobs:
- name: Build
run: |
- bash osx/build-nzbget.sh
+ bash osx/build-nzbget-universal.sh
- name: Rename build artifacts
if: github.ref_name != 'main' && github.ref_name != 'develop'
@@ -41,6 +80,36 @@ jobs:
- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
- name: nzbget-osx-installers
+ name: nzbget-osx-installers-universal
path: osx/build/Release/*.zip
retention-days: 5
+
+ combine-osx-artifacts:
+ runs-on: ubuntu-latest
+ needs: [build-x64, build-universal]
+ permissions:
+ actions: write
+ steps:
+
+ - name: Download build artifacts
+ uses: actions/download-artifact@v4
+
+ - name: Combine artifacts
+ run: |
+ mkdir -p nzbget-osx-installers
+ mv nzbget-osx-installers-x64/* nzbget-osx-installers
+ mv nzbget-osx-installers-universal/* nzbget-osx-installers
+
+ - name: Upload build artifacts with signatures
+ uses: actions/upload-artifact@v4
+ with:
+ name: nzbget-osx-installers
+ path: nzbget-osx-installers/*
+ retention-days: 5
+
+ - name: Delete unneded artifacts
+ uses: geekyeggo/delete-artifact@v4
+ with:
+ name: |
+ nzbget-osx-installers-x64
+ nzbget-osx-installers-universal
diff --git a/README.md b/README.md
index cb0de2c38..1e3f00370 100644
--- a/README.md
+++ b/README.md
@@ -54,7 +54,7 @@ QNAP packages are available as native packages and buildroot packages. [QNAP rea
`Linux`: Linux kernel 2.6 and later, x86 (32 or 64 Bit), ARM 32-bit (armel armhf), ARM 64-bit (aarch64), MIPS (mipseb mipsel), PowerPC (ppc6xx ppc500), RISC-V 64-bit (riscv64)
-`macOS`: macOS 10.13 High Sierra and later, Intel / Apple Silicon.
+`macOS`: X64 binary: macOS Mojave 10.14+, Universal (Intel / Apple Silicon) binary: macOS Monterey 12+
## Building from sources
diff --git a/osx/build-info.md b/osx/build-info.md
index 7e57832fb..df5206f3a 100644
--- a/osx/build-info.md
+++ b/osx/build-info.md
@@ -1,10 +1,11 @@
-About
------
-"build-nzbget.sh" is a bash script which is used to build macOS universal (Intel/Apple Silicon) application.
+# About
+"build-nzbget-*.sh" is a bash scripts which is used to build macOS nzbget binaries
+- [build-nzbget-universal.sh](#build-nzbget-universalsh) - universal (Intel/Apple Silicon) application (macOS Monterey 12+)
+- [build-macos-x64.sh](#build-nzbget-x64sh) - x64 application (macOS Mojave 10.14+)
-Prerequisites
--------------
+## build-nzbget-universal.sh
+### Prerequisites
- Homebrew package manager (https://brew.sh/) and several dependencies:
Install homebrew:
@@ -21,14 +22,39 @@ brew install git zlib libxml2 ncurses openssl@3 pkg-config boost
xcode-select --install
```
-Building NZBGet
----------------
+### Building NZBGet
From cloned repository run
```
-bash osx/build-nzbget.sh
+bash osx/build-nzbget-universal.sh
```
-Output files
-------------
+### Output files
- osx/build/Release/NZBGet.app - application
-- osx/build/Release/nzbget-$VERSION-bin-macos.zip - release archive
+- osx/build/Release/nzbget-$VERSION-bin-macos-universal.zip - release archive
+
+## build-nzbget-x64.sh
+
+### Prerequisites
+- vcpkg package manager (https://vcpkg.io/) and several dependencies:
+```
+cd $HOME
+git clone https://github.com/microsoft/vcpkg
+cd vcpkg
+./bootstrap-vcpkg.sh
+./vcpkg install boost-json boost-optional libxml2 zlib openssl
+```
+- Xcode build tools
+```
+xcode-select --install
+```
+- cmake 3.13+
+
+### Building NZBGet
+From cloned repository run
+```
+bash osx/build-nzbget-x64.sh
+```
+
+### Output files
+- tmp/osx/build/Release/NZBGet.app - application
+- tmp/nzbget-$VERSION-bin-macos-x64.zip - release archive
\ No newline at end of file
diff --git a/osx/build-nzbget.sh b/osx/build-nzbget-universal.sh
similarity index 98%
rename from osx/build-nzbget.sh
rename to osx/build-nzbget-universal.sh
index 97e6f5966..5019a4e7f 100755
--- a/osx/build-nzbget.sh
+++ b/osx/build-nzbget-universal.sh
@@ -181,7 +181,7 @@ Make_archive()
{
VERSION=`grep "AC_INIT(nzbget, " configure.ac`
VERSION=`expr "$VERSION" : '.*, \(.*\),.*)'`
- (cd osx/build/Release/ && zip -r nzbget-$VERSION-bin-macos.zip NZBGet.app)
+ (cd osx/build/Release/ && zip -r nzbget-$VERSION-bin-macos-universal.zip NZBGet.app)
}
Make_OpenSSL_for_arm_and_x86
diff --git a/osx/build-nzbget-x64.sh b/osx/build-nzbget-x64.sh
new file mode 100644
index 000000000..ce18f1612
--- /dev/null
+++ b/osx/build-nzbget-x64.sh
@@ -0,0 +1,92 @@
+#!/bin/sh
+
+# strict error handling for debugging
+set -o errexit
+
+# config variables
+# urls
+URL_UNRAR=https://www.rarlab.com/rar/rarmacos-x64-624.tar.gz
+URL_7Z=https://www.7-zip.org/a/7z2301-mac.tar.xz
+# use vcpkg libs for build and link daemon - install it via ./vcpkg install boost-json boost-optional libxml2 zlib openssl
+LIB_PATH=$HOME/vcpkg/installed/x64-osx/lib
+INCLUDE_PATH=$HOME/vcpkg/installed/x64-osx/include
+# make jobs
+JOBS=$(sysctl -n hw.ncpu)
+
+# create directories and cleanup
+mkdir -p build
+mkdir -p tmp
+rm -rf build/*
+rm -rf tmp/*
+
+export LIBS="-liconv -lncurses $LIB_PATH/libboost_json.a $LIB_PATH/libxml2.a $LIB_PATH/libz.a $LIB_PATH/libssl.a $LIB_PATH/libcrypto.a $LIB_PATH/liblzma.a"
+export INCLUDES="$INCLUDE_PATH/;$INCLUDE_PATH/libxml2/"
+VERSION=$(grep "set(VERSION" CMakeLists.txt | cut -d '"' -f 2)
+
+# copy macOS project to tmp
+cp -r osx tmp/
+DAEMON_PATH=osx/Resources/daemon/usr/local
+
+# make static daemon binary
+cd build
+cmake .. -DENABLE_STATIC=ON -DCMAKE_INSTALL_PREFIX="$PWD/../tmp/$DAEMON_PATH"
+# if running from CI/CD, add testing to builds from non-main branch
+if [ -n "$GITHUB_REF_NAME" ]; then
+ if [ "$GITHUB_REF_NAME" != "main" ]; then
+ VERSION="$VERSION-testing-$(date '+%Y%m%d')"
+ sed -e "s|#define VERSION.*|#define VERSION \"$VERSION\"|g" -i '' config.h
+ fi
+fi
+cmake --build . -j $JOBS
+strip nzbget
+cmake --install .
+
+# fetch tools and root certificates
+cd ../tmp
+mkdir -p $DAEMON_PATH/bin
+rm -rf $DAEMON_PATH/etc
+
+# 7zip
+curl -o 7z.tar.xz $URL_7Z
+mkdir -p 7z
+tar xf 7z.tar.xz -C 7z
+cp 7z/7zz $DAEMON_PATH/bin/7za
+
+# unrar
+curl -o unrar.tar.gz $URL_UNRAR
+tar -xf unrar.tar.gz
+cp rar/unrar $DAEMON_PATH/bin/unrar
+
+# root certificates
+curl -o $DAEMON_PATH/bin/cacert.pem https://curl.se/ca/cacert.pem
+
+# adjust nzbget.conf
+CONF_FILE=$DAEMON_PATH/share/nzbget/nzbget.conf
+sed -i '' 's:^MainDir=.*:MainDir=~/Library/Application Support/NZBGet:' $CONF_FILE
+sed -i '' 's:^DestDir=.*:DestDir=~/Downloads:' $CONF_FILE
+sed -i '' 's:^InterDir=.*:InterDir=~/Downloads/Intermediate:' $CONF_FILE
+sed -i '' 's:^WebDir=.*:# NOTE\: option WebDir cannot be changed because it is hardcoded in OSX version.:' $CONF_FILE
+sed -i '' 's:^LockFile=.*:# NOTE\: option LockFile cannot be changed because it is hardcoded in OSX version.:' $CONF_FILE
+sed -i '' 's:^LogFile=.*:LogFile=~/Library/Logs/NZBGet.log:' $CONF_FILE
+sed -i '' '/# example configuration file (installed to/{N;s/.*/# example configuration file (installed to\n# \/usr\/local\/share\/nzbget\/nz bget.conf)./;}' $CONF_FILE
+sed -i '' 's:^ConfigTemplate=.*:# NOTE\: option ConfigTemplate cannot be changed because it is hardcoded in OSX version.:' $CONF_FILE
+sed -i '' 's:^DaemonUsername=.*:# NOTE\: option DaemonUsername cannot be changed because it is hardcoded in OSX version.:' $CONF_FILE
+sed -i '' 's:^CertStore=.*:CertStore=${AppDir}/cacert.pem:' $CONF_FILE
+sed -i '' 's:^CertCheck=.*:CertCheck=yes:' $CONF_FILE
+sed -i '' 's:^AuthorizedIP=.*:AuthorizedIP=127.0.0.1:' $CONF_FILE
+sed -i '' 's:^ArticleCache=.*:ArticleCache=700:' $CONF_FILE
+sed -i '' 's:^DirectWrite=.*:DirectWrite=no:' $CONF_FILE
+sed -i '' 's:^WriteBuffer=.*:WriteBuffer=1024:' $CONF_FILE
+sed -i '' 's:^ParBuffer=.*:ParBuffer=500:' $CONF_FILE
+sed -i '' 's:^DirectRename=.*:DirectRename=yes:' $CONF_FILE
+sed -i '' 's:^DirectUnpack=.*:DirectUnpack=yes:' $CONF_FILE
+sed -i '' 's:^UnrarCmd=.*:UnrarCmd=${AppDir}/unrar:' $CONF_FILE
+sed -i '' 's:^SevenZipCmd=.*:SevenZipCmd=${AppDir}/7za:' $CONF_FILE
+
+# build macos frontend
+xcodebuild -project osx/NZBGet.xcodeproj -configuration "Release" -destination "platform=macOS" build
+
+# create build archive
+ARCHIVE_NAME=nzbget-$VERSION-bin-macos-x64.zip
+(cd osx/build/Release/ && zip -r $ARCHIVE_NAME NZBGet.app)
+mv osx/build/Release/$ARCHIVE_NAME .
From c93b551b1fa0afae458c1e78485c6d3eb6410514 Mon Sep 17 00:00:00 2001
From: Denis <146707790+dnzbk@users.noreply.github.com>
Date: Wed, 13 Mar 2024 13:00:33 +0300
Subject: [PATCH 21/42] Doc: EXTENSIONS.md, Cppcheck, INSTALLATION.md
refactoring (#199)
- updated README.md;
- moved CONTRIBUTING.md to docs/;
- splitted INSTALLATION.md to POSIX.md, WINDOWS.md and HOW_TO_USE.md;
- added Extensions doc;
- added a mention of how Cppcheck can be used together with CMake;
---------
Co-authored-by: Paul
---
INSTALLATION.md | 655 +-----------------------
README.md | 9 +-
CONTRIBUTING.md => docs/CONTRIBUTING.md | 0
docs/HOW_TO_USE.md | 208 ++++++++
docs/POSIX.md | 280 ++++++++++
docs/WINDOWS.md | 87 ++++
docs/extensions/EXTENSIONS.md | 365 +++++++++++++
docs/extensions/EXTENSIONS_LEGACY.md | 9 +
docs/extensions/FEED.md | 10 +
docs/extensions/POST-PROCESSING.md | 115 +++++
docs/extensions/QUEUE.md | 85 +++
docs/extensions/SCAN.md | 95 ++++
docs/extensions/SCHEDULER.md | 47 ++
13 files changed, 1314 insertions(+), 651 deletions(-)
rename CONTRIBUTING.md => docs/CONTRIBUTING.md (100%)
create mode 100644 docs/HOW_TO_USE.md
create mode 100644 docs/POSIX.md
create mode 100644 docs/WINDOWS.md
create mode 100644 docs/extensions/EXTENSIONS.md
create mode 100644 docs/extensions/EXTENSIONS_LEGACY.md
create mode 100644 docs/extensions/FEED.md
create mode 100644 docs/extensions/POST-PROCESSING.md
create mode 100644 docs/extensions/QUEUE.md
create mode 100644 docs/extensions/SCAN.md
create mode 100644 docs/extensions/SCHEDULER.md
diff --git a/INSTALLATION.md b/INSTALLATION.md
index 1ffac7b1e..ff1d0448b 100644
--- a/INSTALLATION.md
+++ b/INSTALLATION.md
@@ -1,651 +1,8 @@
-# NZBGet installation
+## Platforms
-This is a short documentation. For more information please
-visit NZBGet home page at
- https://nzbget.com
+Articles below provide detailed information on manual compilation of NZBGet for specific platforms:
-Contents
---------
-1. About NZBGet
-2. Supported OS
-3. Prerequisites on POSIX
-4. Installation on POSIX
-5. Compiling on Windows
-6. Configuration
-7. Usage
-8. Authors
-9. Copyright
-10. Contact
-
-
-## 1. About NZBGet
-
-NZBGet is a binary newsgrabber, which downloads files from usenet
-based on information given in nzb-files. NZBGet can be used in
-standalone and in server/client modes. In standalone mode you
-pass a nzb-file as parameter in command-line, NZBGet downloads
-listed files and then exits.
-
-In server/client mode NZBGet runs as server in background.
-Then you use client to send requests to server. The sample requests
-are: download nzb-file, list files in queue, etc.
-
-There is also a built-in web-interface. The server has RPC-support
-and can be controlled from third party applications too.
-
-Standalone-tool, server and client are all contained in only one
-executable file "nzbget". The mode in which the program works
-depends on command-line parameters passed to the program.
-
-## 2. Supported OS
-
-NZBGet is written in C++ and works on Windows, OS X, Linux and
-most POSIX-conform OS'es.
-
-Clients and servers running on different OS'es may communicate with
-each other. For example, you can use NZBGet as client on Windows to
-control your NZBGet-server running on Linux.
-
-The download-section of NZBGet web-site provides binary files
-for Windows, OS X and Linux. For most POSIX-systems you need to compile
-the program yourself.
-
-If you have downloaded binaries you can just jump to section
-"Configuration".
-
-## 3. Prerequisites on POSIX
-
-NZBGet is developed on a linux-system, but it runs on other
-POSIX platforms.
-
-To build NZBGet you will need:
-
-For configuring and building:
- - [CMake](https://cmake.org/)
- - [GCC](https://gcc.gnu.org/)
-
- or
- - [CLang](https://clang.llvm.org/)
-
-Libraries:
- - [libxml2](https://gitlab.gnome.org/GNOME/libxml2/-/wikis/home)
- - [Boost.JSON](https://www.boost.org/doc/libs/1_84_0/libs/json/doc/html/index.html)
-> If you face issues with Boost.JSON on your system, you can skip it - CMake will take care of it.
-
-And the following libraries are optional:
-
- For curses-output-mode (enabled by default):
- - [ncurses](https://invisible-island.net/ncurses)
-
- For encrypted connections (TLS/SSL):
- - [OpenSSL](https://www.openssl.org)
-
- or
- - [GnuTLS](https://gnutls.org)
-
- For gzip support in web-server and web-client (enabled by default):
- - [zlib](https://www.zlib.net/)
-
- For tests:
- - [Boost.Test](https://www.boost.org/doc/libs/1_84_0/libs/test/doc/html/index.html)
-
- For static code analysis:
- - [Clang-Tidy](https://clang.llvm.org/extra/clang-tidy/)
-
-Please note that you also
-need the developer packages for these libraries too, they package names
-have often suffix "dev" or "devel". On other systems you may need to
-download the libraries at the given URLs and compile them (see hints below).
-
-### Debian:
-```
- apt install cmake build-essential libncurses-dev libssl-dev libxml2-dev zlib1g-dev libboost-json1.81-dev
-```
- - For tests:
-```
- apt install libboost-test1.81-dev
-```
- - For static code analysis:
-```
- apt install clang-tidy
-```
-### FreeBSD:
-```
- pkg install cmake ncurses openssl libxml2 zlib boost-libs
-```
-### macOS:
-```
- xcode-select --install
- brew install cmake ncurses openssl libxml2 zlib boost
-```
-
-## 4. Installation on POSIX
-
-Installation from the source distribution archive (nzbget-VERSION.tar.gz):
-
- - Untar the nzbget-source:
-```
- tar -zxf nzbget-VERSION.tar.gz
-```
- - Change into nzbget-directory:
-```
- cd nzbget-VERSION
-```
- - Configure:
-```
- mkdir build
- cd build
- cmake ..
-```
- - In a case you don't have root access or want to install the program
- in your home directory use the configure parameter -DCMAKE_INSTALL_PREFIX:
-```
- cmake .. -DCMAKE_INSTALL_PREFIX=~/usr
-```
- - Build, specifying (-j 8) how many CPU cores to use to speed up compilation:
-```
- cmake --build . -j 8
-```
- - Install:
-```
- cmake --install .
-```
- - Uninstall:
-```
- cmake --build . --target uninstall
-```
-
-### Configure-options
----------------------
-You may run configure with additional arguments:
- - Enable tests:
-```
- cmake .. -DENABLE_TESTS=ON
-```
- - Enable Clang-Tidy static code analizer:
-```
- cmake .. -DENABLE_CLANG_TIDY=ON
-```
- - Disable ncurses. Use this option if you can not use ncurses.
-```
- cmake .. -DDISABLE_CURSES=ON
-```
- - Disable parcheck. Use this option if you have troubles when compiling par2-module.
-```
- cmake .. -DDISABLE_PARCHECK=ON
-```
- - Use GnuTLS. Use this option if you want to use GnuTLS instead of OpenSSL.
-```
- cmake .. -DUSE_GNUTLS=ON
-```
- - Disable TLS. Use this option if you can not neither OpenSSL nor GnuTLS.
-```
- cmake .. -DDISABLE_TLS=ON
-```
- - Disable gzip. Use this option if you can not use zlib.
-```
- cmake .. -DDISABLE_GZIP=ON
-```
- - Disable sigchld-handler. The disabling may be neccessary on 32-Bit BSD.
-```
- cmake .. -DDISABLE_SIGCHLD_HANDLER=ON
-```
- - For debug build.
-```
- cmake .. -DCMAKE_BUILD_TYPE=Debug
-```
- - To get a static binary,
-```
- cmake .. -DENABLE_STATIC=ON
-```
- `LIBS` and `INCLUDES` env variables can be useful for static linking, since CMake looks for shared libraries by default
-```
- export LIBS="-lncurses -ltinfo -lboost_json -lxml2 -lz -lm -lssl -lcrypto -Wl,--whole-archive -lpthread -Wl,--no-whole-archive"
- export INCLUDES="/usr/include/;/usr/include/libxml2/"
- cmake .. -DENABLE_STATIC=ON
-```
-## Building using autotools (deprecated)
-
- - configure it via
-```
- autoreconf --install
- ./configure
-```
- (maybe you have to tell configure, where to find some libraries then is your friend!
-```
- ./configure --help
-```
- also see "Configure-options" later)
-
- - in a case you don't have root access or want to install the program
- in your home directory use the configure parameter --prefix, e. g.:
-```
- ./configure --prefix ~/usr
-```
- - compile it via
-```
- make
-```
- - to install system wide become root via:
-```
- su
-```
- - install it via:
-```
- make install
-```
- - install configuration files into /etc via:
-```
- make install-conf
-```
- (you can skip this step if you intend to store configuration
- files in a non-standard location)
-
-### Configure-options
----------------------
-You may run configure with additional arguments:
-
- --disable-curses - to make without curses-support. Use this option
- if you can not use curses/ncurses.
-
- --disable-parcheck - to make without parcheck-support. Use this option
- if you have troubles when compiling par2-module.
-
- --with-tlslib=(OpenSSL, GnuTLS) - to select which TLS/SSL library
- should be used for encrypted server connections.
-
- --disable-tls - to make without TLS/SSL support. Use this option if
- you can not neither OpenSSL nor GnuTLS.
-
- --disable-gzip - to make without gzip support. Use this option
- if you can not use zlib.
-
- --enable-debug - to build in debug-mode, if you want to see and log
- debug-messages.
-
-### Optional package: par-check
--------------------------------
-NZBGet can check and repair downloaded files for you. For this purpose
-it uses library par2.
-
-For your convenience the source code of libpar2 is integrated into
-NZBGet’s source tree and is compiled automatically when you make NZBGet.
-
-In a case errors occur during this process the inclusion of par2-module
-can be disabled using configure option "--disable-parcheck":
-```
- ./configure --disable-parcheck
-```
-
-### Optional package: curses
-----------------------------
-For curses-outputmode you need ncurses or curses on your system.
-If you do not have one of them you can download and compile ncurses yourself.
-Following configure-parameters may be useful:
-
- --with-libcurses-includes=/path/to/curses/includes
- --with-libcurses-libraries=/path/to/curses/libraries
-
-If you are not able to use curses or ncurses or do not want them you can
-make the program without support for curses using option "--disable-curses":
-```
- ./configure --disable-curses
-```
-
-### Optional package: TLS
--------------------------
-To enable encrypted server connections (TLS/SSL) you need to build the program
-with TLS/SSL support. NZBGet can use two libraries: OpenSSL or GnuTLS.
-Configure-script checks which library is installed and use it. If both are
-available it gives the precedence to OpenSSL. You may override that with
-the option --with-tlslib=(OpenSSL, GnuTLS). For example to build with GnuTLS:
-```
- ./configure --with-tlslib= GnuTLS
-```
-
-Following configure-parameters may be useful:
-
- --with-libtls-includess=/path/to/gnutls/includes
- --with-libtls-libraries=/path/to/gnutls/libraries
-
- --with-openssl-includess=/path/to/openssl/includes
- --with-openssl-libraries=/path/to/openssl/libraries
-
-If none of these libraries is available you can make the program without
-TLS/SSL support using option "--disable-tls":
-
- ./configure --disable-tls
-
-## 5. Compiling on Windows
-
-For configuring and building:
- - [CMake](https://cmake.org/)
- - [MS C++ Build tools](https://visualstudio.microsoft.com/downloads/?q=build+tools)
-
-To compile the program with TLS/SSL support you need OpenSSL:
- - [OpenSSL](https://www.openssl.org)
-
-Also required are:
- - [Zlib](https://gnuwin32.sourceforge.net/packages/zlib.htm)
- - [libxml2](https://gitlab.gnome.org/GNOME/libxml2/-/wikis/home)
- - [Boost.JSON](https://www.boost.org/doc/libs/1_84_0/libs/json/doc/html/index.html)
- - [Boost.Optional](https://www.boost.org/doc/libs/1_84_0/libs/optional/doc/html/index.html)
-For tests:
- - [Boost.Test](https://www.boost.org/doc/libs/1_84_0/libs/test/doc/html/index.html)
-
-We recommend using [vcpkg](https://vcpkg.io/) to install dependencies:
-
-```
- vcpkg install openssl:-windows-static
- vcpkg install libxml2:-windows-static
- vcpkg install zlib:-windows-static
- vcpkg install boost-json:-windows-static
- vcpkg install boost-optional:-windows-static
-```
- - For tests:
-```
- vcpkg install boost-test:-windows-static
-```
- - Configure:
-```
- mkdir build
- cd build
- cmake .. -DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_TARGET_TRIPLET=x64-windows-static -A x64
-```
- - For Win32:
-```
- cmake .. -DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_TARGET_TRIPLET=x86-windows-static -A Win32
-```
- - For debug build:
-```
- cmake .. -DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_TARGET_TRIPLET=x64-windows-static -DCMAKE_BUILD_TYPE=Debug
-```
- - If Debug:
-```
- cmake --build . --config Debug
-```
-
-You may run configure with additional arguments:
- - Enable tests:
-```
- cmake .. -DENABLE_TESTS=ON -DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_TARGET_TRIPLET=x64-windows-static
-```
- - Disable TLS. Use this option if you can not neither OpenSSL nor GnuTLS.
-```
- cmake .. -DDISABLE_TLS=ON -DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_TARGET_TRIPLET=x64-windows-static
-```
-
-## 6. Configuration
-
-NZBGet needs a configuration file.
-
-An example configuration file is provided in "nzbget.conf", which
-is installed into "/share/nzbget" (where depends on
-system configuration and configure options - typically "/usr/local",
-"/usr" or "/opt"). The installer adjusts the file according to your
-system paths. If you have performed the installation step
-"make install-conf" this file is already copied to "/etc" and
-NZBGet finds it automatically. If you install the program manually
-from a binary archive you have to copy the file from "/share/nzbget"
-to one of the locations listed below.
-
-Open the file in a text editor and modify it accodring to your needs.
-
-You need to set at least the option "MAINDIR" and one news server in
-configuration file. The file has comments on how to use each option.
-
-The program looks for configuration file in following standard
-locations (in this order):
-
-On POSIX systems:
- /nzbget.conf
- ~/.nzbget
- /etc/nzbget.conf
- /usr/etc/nzbget.conf
- /usr/local/etc/nzbget.conf
- /opt/etc/nzbget.conf
-
-On Windows:
- \nzbget.conf
-
-If you put the configuration file in other place, you can use command-
-line switch "-c " to point the program to correct location.
-
-In special cases you can run program without configuration file using
-switch "-n". You need to use switch "-o" to pass required configuration
-options via command-line.
-
-## 7. Usage
-
-NZBGet can be used in either standalone mode which downloads a single file
-or as a server which is able to queue up numerous download requests.
-
-TIP for Windows users: NZBGet is controlled via various command line
-parameters. For easier using there is a simple shell script included
-in "nzbget-shell.bat". Start this script from Windows Explorer and you will
-be running a command shell with PATH adjusted to find NZBGet executable.
-Then you can type all commands without full path to nzbget.exe.
-
-### Standalone mode:
---------------------
-
-nzbget
-
-### Server mode:
-----------------
-
-First start the nzbget-server:
-
- - in console mode:
-
- nzbget -s
-
- - or in daemon mode (POSIX only):
-
- nzbget -D
-
- - or as a service (Windowx only, firstly install the service with command
- "nzbget -install"):
-
- net start NZBGet
-
-To stop server use:
-
- nzbget -Q
-
-TIP for POSIX users: with included script "nzbgetd" you can use standard
-commands to control daemon:
-
- nzbgetd start
- nzbgetd stop
- etc.
-
-When NZBGet is started in console server mode it displays a message that
-it is ready to receive download requests. In daemon mode it doesn't print any
-messages to console since it runs in background.
-
-When the server is running it is possible to queue up downloads. This can be
-done either in terminal with "nzbget -A " or by uploading
-a nzb-file into server's monitor-directory (/nzb by default).
-
-To check the status of server start client and connect it to server:
-
- nzbget -C
-
-The client have three different (display) outputmodes, which you can select
-in configuration file (on client computer) or in command line. Try them:
-
- nzbget -o outputmode=log -C
-
- nzbget -o outputmode=color -C
-
- nzbget -o outputmode=curses -C
-
-To list files in server's queue:
-
- nzbget -L
-
-It prints something like:
-
- [1] nzbname\filename1.rar (50.00 MB)
- [2] nzbname\filename1.r01 (50.00 MB)
- [3] another-nzb\filename3.r01 (100.00 MB)
- [4] another-nzb\filename3.r02 (100.00 MB)
-
-This is the list of individual files listed within nzb-file. To print
-the list of nzb-files (without content) add G-modifier to the list command:
-
- [1] nzbname (4.56 GB)
- [2] another-nzb (4.20 GB)
-
-The numbers in square braces are ID's of files or groups in queue.
-They can be used in edit-command. For example to move file with
-ID 2 to the top of queue:
-
- nzbget -E T 2
-
-or to pause files with IDs from 10 to 20:
-
- nzbget -E P 10-20
-
-or to delete files from queue:
-
- nzbget -E D 3 10-15 20-21 16
-
-The edit-command has also a group-mode which affects all files from the
-same nzb-file. You need to pass an ID of the group. For example to delete
-the whole group 1:
-
- nzbget -E G D 1
-
-The switch "o" is useful to override options in configuration files.
-For example:
-
- nzbget -o reloadqueue=no -o dupecheck=no -o parcheck=yes -s
-
-or:
-
- nzbget -o createlog=no -C
-
-### Running client & server on seperate machines:
--------------------------------------------------
-
-Since nzbget communicates via TCP/IP it's possible to have a server running on
-one computer and adding downloads via a client on another computer.
-
-Do this by setting the "ControlIP" option in the nzbget.conf file to point to the
-IP of the server (default is localhost which means client and server runs on
-same computer)
-
-### Security warning
---------------------
-
-NZBGet communicates via unsecured socket connections. This makes it vulnerable.
-Although server checks the password passed by client, this password is still
-transmitted in unsecured way. For this reason it is highly recommended
-to configure your Firewall to not expose the port used by NZBGet to WAN.
-
-If you need to control server from WAN it is better to connect to server's
-terminal via SSH (POSIX) or remote desktop (Windows) and then run
-nzbget-client-commands in this terminal.
-
-### Post processing scripts
----------------------------
-
-After the download of nzb-file is completed nzbget can call post-processing
-scripts, defined in configuration file.
-
-Example post-processing scripts are provided in directory "scripts".
-
-To use the scripts copy them into your local directory and set options
-, and .
-
-For information on writing your own post-processing scripts please
-visit NZBGet web site.
-
-### Web-interface
------------------
-
-NZBGet has a built-in web-server providing the access to the program
-functions via web-interface.
-
-To activate web-interface set the option "WebDir" to the path with
-web-interface files. If you install using "make install-conf" as
-described above the option is set automatically. If you install using
-binary files you should check if the option is set correctly.
-
-To access web-interface from your web-browser use the server address
-and port defined in NZBGet configuration file in options "ControlIP" and
-"ControlPort". For example:
-
- http://localhost:6789/
-
-For login credentials type username and the password defined by
-options "ControlUsername" (default "nzbget") and "ControlPassword"
-(default "tegbzn6789").
-
-In a case your browser forget credentials, to prevent typing them each
-time, there is a workaround - use URL in the form:
-
- http://localhost:6789/username:password/
-
-Please note, that in this case the password is saved in a bookmark or in
-browser history in plain text and is easy to find by persons having
-access to your computer.
-
-## 8. Authors
-
-NZBGet is developed and maintained by Andrey Prygunkov
-(hugbug@users.sourceforge.net).
-
-The original project was initially created by Sven Henkel
-(sidddy@users.sourceforge.net) in 2004 and later developed by
-Bo Cordes Petersen (placebodk@users.sourceforge.net) until 2005.
-In 2007 the abandoned project was overtaken by Andrey Prygunkov.
-Since then the program has been completely rewritten.
-
-NZBGet distribution archive includes additional components
-written by other authors:
-
-Par2:
- Peter Brian Clements
-
-Par2 library API:
- Francois Lesueur
-
-jQuery:
- John Resig
- The Dojo Foundation
-
-Bootstrap:
- Twitter, Inc
-
-Raphaël:
- Dmitry Baranovskiy
- Sencha Labs
-
-Elycharts:
- Void Labs s.n.c.
-
-iconSweets:
- Yummygum
-
-Boost:
- Boost organization and wider Boost community
-
-
-## 9. Copyright
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-The complete content of license is provided in file COPYING.
-
-Additional exemption: compiling, linking, and/or using OpenSSL is allowed.
-
-## 10. Contact
-
-If you encounter any problem, feel free to contact us
- https://nzbget.com/contact/
+ - [POSIX](docs/POSIX.md)
+ - [Windows](docs/WINDOWS.md)
+ - [Synology](synology/build-info.md)
+ - [QNAP](qnap/build-info.md)
diff --git a/README.md b/README.md
index 1e3f00370..990b61036 100644
--- a/README.md
+++ b/README.md
@@ -60,13 +60,18 @@ QNAP packages are available as native packages and buildroot packages. [QNAP rea
[General instructions](INSTALLATION.md)
-[Linux](linux/build-info.md) [macOS](osx/build-info.md) [Synology](synology/build-info.md) [QNAP](qnap/build-info.md)
+## Extensions
+ - [V1 (NZBGet v22 and below)](docs/extensions/EXTENSIONS_LEGACY.md)
+ - [V2 (NZBGet v23 and above)](docs/extensions/EXTENSIONS.md)
+
+## Brief introduction on how to use NZBGet
+ - [How to use](docs/HOW_TO_USE.md)
## Contribution
Contributions are very welcome - not only from developers, but from our users too - please don't hesitate to participate in [discussions](https://github.com/nzbgetcom/nzbget/discussions) or [create a new discussion](https://github.com/nzbgetcom/nzbget/discussions/new/choose)
-For more information - see [Contributing](CONTRIBUTING.md).
+For more information - see [Contributing](docs/CONTRIBUTING.md).
## Donate
diff --git a/CONTRIBUTING.md b/docs/CONTRIBUTING.md
similarity index 100%
rename from CONTRIBUTING.md
rename to docs/CONTRIBUTING.md
diff --git a/docs/HOW_TO_USE.md b/docs/HOW_TO_USE.md
new file mode 100644
index 000000000..e4d4d9b85
--- /dev/null
+++ b/docs/HOW_TO_USE.md
@@ -0,0 +1,208 @@
+## Configuration
+
+NZBGet needs a configuration file.
+
+An example configuration file is provided in "nzbget.conf", which
+is installed into "``/share/nzbget" (where `` depends on
+system configuration and configure options - typically "/usr/local",
+"/usr" or "/opt"). The installer adjusts the file according to your
+system paths. If you have performed the installation step
+"make install-conf" this file is already copied to "``/etc" and
+NZBGet finds it automatically. If you install the program manually
+from a binary archive you have to copy the file from "``/share/nzbget"
+to one of the locations listed below.
+
+Open the file in a text editor and modify it accodring to your needs.
+
+You need to set at least the option "MAINDIR" and one news server in
+configuration file. The file has comments on how to use each option.
+
+The program looks for configuration file in following standard
+locations (in this order):
+
+On POSIX systems:
+```
+/nzbget.conf
+~/.nzbget
+/etc/nzbget.conf
+/usr/etc/nzbget.conf
+/usr/local/etc/nzbget.conf
+/opt/etc/nzbget.conf
+~/usr/etc/nzbget.conf
+```
+
+On Windows:
+```
+\nzbget.conf
+```
+
+If you put the configuration file in other place, you can use command-
+line switch "-c ``" to point the program to correct location.
+
+In special cases you can run program without configuration file using
+switch "-n". You need to use switch "-o" to pass required configuration
+options via command-line.
+
+## Usage
+
+NZBGet can be used in either standalone mode which downloads a single file
+or as a server which is able to queue up numerous download requests.
+
+TIP for Windows users: NZBGet is controlled via various command line
+parameters. For easier using there is a simple shell script included
+in "nzbget-shell.bat". Start this script from Windows Explorer and you will
+be running a command shell with PATH adjusted to find NZBGet executable.
+Then you can type all commands without full path to nzbget.exe.
+
+### Standalone mode:
+--------------------
+```
+nzbget
+```
+### Server mode:
+----------------
+
+First start the nzbget-server:
+
+ - in console mode:
+```
+nzbget -s
+```
+ - or in daemon mode (POSIX only):
+```
+ nzbget -D
+```
+ - or as a service (Windowx only, firstly install the service with command "nzbget -install"):
+```
+ net start NZBGet
+```
+To stop server use:
+```
+nzbget -Q
+```
+TIP for POSIX users: with included script "nzbgetd" you can use standard
+commands to control daemon:
+```
+nzbgetd start
+nzbgetd stop
+```
+
+When NZBGet is started in console server mode it displays a message that
+it is ready to receive download requests. In daemon mode it doesn't print any
+messages to console since it runs in background.
+
+When the server is running it is possible to queue up downloads. This can be
+done either in terminal with "nzbget -A " or by uploading
+a nzb-file into server's monitor-directory (/nzb by default).
+
+To check the status of server start client and connect it to server:
+```
+nzbget -C
+```
+The client have three different (display) outputmodes, which you can select
+in configuration file (on client computer) or in command line. Try them:
+```
+nzbget -o outputmode=log -C
+nzbget -o outputmode=color -C
+nzbget -o outputmode=curses -C
+```
+To list files in server's queue:
+```
+nzbget -L
+```
+It prints something like:
+```
+[1] nzbname\filename1.rar (50.00 MB)
+[2] nzbname\filename1.r01 (50.00 MB)
+[3] another-nzb\filename3.r01 (100.00 MB)
+[4] another-nzb\filename3.r02 (100.00 MB)
+```
+This is the list of individual files listed within nzb-file. To print
+the list of nzb-files (without content) add G-modifier to the list command:
+```
+[1] nzbname (4.56 GB)
+[2] another-nzb (4.20 GB)
+```
+The numbers in square braces are ID's of files or groups in queue.
+They can be used in edit-command. For example to move file with
+ID 2 to the top of queue:
+```
+nzbget -E T 2
+```
+or to pause files with IDs from 10 to 20:
+```
+nzbget -E P 10-20
+```
+or to delete files from queue:
+```
+nzbget -E D 3 10-15 20-21 16
+```
+
+The edit-command has also a group-mode which affects all files from the
+same nzb-file. You need to pass an ID of the group. For example to delete
+the whole group 1:
+```
+nzbget -E G D 1
+```
+The switch "o" is useful to override options in configuration files.
+For example:
+```
+nzbget -o reloadqueue=no -o dupecheck=no -o parcheck=yes -s
+```
+or:
+```
+nzbget -o createlog=no -C
+```
+
+### Running client & server on seperate machines:
+-------------------------------------------------
+
+Since nzbget communicates via TCP/IP it's possible to have a server running on
+one computer and adding downloads via a client on another computer.
+
+Do this by setting the "ControlIP" option in the nzbget.conf file to point to the
+IP of the server (default is localhost which means client and server runs on
+same computer)
+
+### Security warning
+--------------------
+
+NZBGet communicates via unsecured socket connections. This makes it vulnerable.
+Although server checks the password passed by client, this password is still
+transmitted in unsecured way. For this reason it is highly recommended
+to configure your Firewall to not expose the port used by NZBGet to WAN.
+
+If you need to control server from WAN it is better to connect to server's
+terminal via SSH (POSIX) or remote desktop (Windows) and then run
+nzbget-client-commands in this terminal.
+
+### Web-interface
+-----------------
+
+NZBGet has a built-in web-server providing the access to the program
+functions via web-interface.
+
+To activate web-interface set the option "WebDir" to the path with
+web-interface files. If you install using "make install-conf" as
+described above the option is set automatically. If you install using
+binary files you should check if the option is set correctly.
+
+To access web-interface from your web-browser use the server address
+and port defined in NZBGet configuration file in options "ControlIP" and
+"ControlPort". For example:
+```
+http://localhost:6789/
+```
+
+For login credentials type username and the password defined by
+options "ControlUsername" (default `"nzbget"`) and "ControlPassword"
+(default `"tegbzn6789"`).
+
+In a case your browser forget credentials, to prevent typing them each
+time, there is a workaround - use URL in the form:
+```
+http://localhost:6789/username:password/
+```
+Please note, that in this case the password is saved in a bookmark or in
+browser history in plain text and is easy to find by persons having
+access to your computer.
diff --git a/docs/POSIX.md b/docs/POSIX.md
new file mode 100644
index 000000000..6cf011b27
--- /dev/null
+++ b/docs/POSIX.md
@@ -0,0 +1,280 @@
+## To build NZBGet you will need:
+
+ - For configuring and building:
+ - [CMake](https://cmake.org/)
+ - [GCC](https://gcc.gnu.org/)
+
+ or
+ - [CLang](https://clang.llvm.org/)
+
+ - Libraries:
+ - [libxml2](https://gitlab.gnome.org/GNOME/libxml2/-/wikis/home)
+ - [Boost.JSON](https://www.boost.org/doc/libs/1_84_0/libs/json/doc/html/index.html)
+
+> If you face issues with Boost.JSON on your system, you can skip it - CMake will take care of it.
+
+- And the following libraries are optional:
+
+ - For curses-output-mode (enabled by default):
+ - [ncurses](https://invisible-island.net/ncurses)
+
+ - For encrypted connections (TLS/SSL):
+ - [OpenSSL](https://www.openssl.org)
+
+ or
+ - [GnuTLS](https://gnutls.org)
+
+ - For gzip support in web-server and web-client (enabled by default):
+ - [zlib](https://www.zlib.net/)
+
+ - For tests:
+ - [Boost.Test](https://www.boost.org/doc/libs/1_84_0/libs/test/doc/html/index.html)
+
+ - For static code analysis:
+ - [Clang-Tidy](https://clang.llvm.org/extra/clang-tidy/)
+
+Please note that you also
+need the developer packages for these libraries too, they package names
+have often suffix "dev" or "devel". On other systems you may need to
+download the libraries at the given URLs and compile them (see hints below).
+
+### Debian:
+```
+apt install cmake build-essential libncurses-dev libssl-dev libxml2-dev zlib1g-dev libboost-json1.81-dev
+```
+ - For tests:
+```
+apt install libboost-test1.81-dev
+```
+ - For static code analysis:
+```
+apt install clang-tidy
+```
+### FreeBSD:
+```
+pkg install cmake ncurses openssl libxml2 zlib boost-libs
+```
+### macOS:
+```
+xcode-select --install
+brew install cmake ncurses openssl libxml2 zlib boost
+```
+
+## 4. Installation on POSIX
+
+Installation from the source distribution archive (nzbget-VERSION.tar.gz):
+
+ - Untar the nzbget-source:
+```
+tar -zxf nzbget-VERSION.tar.gz
+```
+ - Change into nzbget-directory:
+```
+cd nzbget-VERSION
+```
+ - Configure:
+```
+mkdir build
+cd build
+cmake ..
+```
+ - In a case you don't have root access or want to install the program
+ in your home directory use the configure parameter -DCMAKE_INSTALL_PREFIX:
+```
+cmake .. -DCMAKE_INSTALL_PREFIX=~/usr
+```
+ - Build, specifying (-j 8) how many CPU cores to use to speed up compilation:
+```
+cmake --build . -j 8
+```
+ - Install:
+```
+cmake --install .
+```
+ - Uninstall:
+```
+cmake --build . --target uninstall
+```
+
+### Configure-options
+---------------------
+You may run configure with additional arguments:
+ - Enable tests:
+```
+cmake .. -DENABLE_TESTS=ON
+```
+ - Enable Clang-Tidy static code analizer:
+```
+cmake .. -DENABLE_CLANG_TIDY=ON
+```
+ - Disable ncurses. Use this option if you can not use ncurses.
+```
+cmake .. -DDISABLE_CURSES=ON
+```
+ - Disable parcheck. Use this option if you have troubles when compiling par2-module.
+```
+cmake .. -DDISABLE_PARCHECK=ON
+```
+ - Use GnuTLS. Use this option if you want to use GnuTLS instead of OpenSSL.
+```
+cmake .. -DUSE_GNUTLS=ON
+```
+ - Disable TLS. Use this option if you can not neither OpenSSL nor GnuTLS.
+```
+cmake .. -DDISABLE_TLS=ON
+```
+ - Disable gzip. Use this option if you can not use zlib.
+```
+cmake .. -DDISABLE_GZIP=ON
+```
+ - Disable sigchld-handler. The disabling may be neccessary on 32-Bit BSD.
+```
+cmake .. -DDISABLE_SIGCHLD_HANDLER=ON
+```
+ - For debug build.
+```
+cmake .. -DCMAKE_BUILD_TYPE=Debug
+```
+ - To get a static binary,
+```
+cmake .. -DENABLE_STATIC=ON
+```
+`LIBS` and `INCLUDES` env variables can be useful for static linking, since CMake looks for shared libraries by default
+```
+export LIBS="-lncurses -ltinfo -lboost_json -lxml2 -lz -lm -lssl -lcrypto -Wl,--whole-archive -lpthread -Wl,--no-whole-archive"
+export INCLUDES="/usr/include/;/usr/include/libxml2/"
+cmake .. -DENABLE_STATIC=ON
+```
+## Cppcheck
+ - Install Cppcheck
+```
+apt install cppcheck
+```
+ - Generate a compile database:
+```
+cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON .
+```
+ - The file compile_commands.json is created in the current folder. Now run Cppcheck like this:
+```
+cppcheck --project=compile_commands.json
+```
+ - To ignore certain folders you can use -i. This will skip analysis of source files in
+the foo folder.
+```
+cppcheck --project=compile_commands.json -ifoo
+```
+
+## Building using autotools (deprecated)
+
+ - configure it via
+```
+autoreconf --install./configure
+```
+ (maybe you have to tell configure, where to find some libraries then is your friend!
+```
+./configure --help
+```
+ also see "Configure-options" later)
+
+ - in a case you don't have root access or want to install the program
+ in your home directory use the configure parameter --prefix, e. g.:
+```
+./configure --prefix ~/usr
+```
+ - compile it via
+```
+make -j 4
+```
+ - to install system wide become root via:
+```
+su
+```
+ - install it via:
+```
+make install
+```
+ - install configuration files into /etc via:
+```
+make install-conf
+```
+(you can skip this step if you intend to store configuration
+ files in a non-standard location)
+
+### Configure-options
+---------------------
+You may run configure with additional arguments:
+
+ - --disable-curses - to make without curses-support. Use this option
+ if you can not use curses/ncurses.
+
+ - --disable-parcheck - to make without parcheck-support. Use this option
+ if you have troubles when compiling par2-module.
+
+ - --with-tlslib=(OpenSSL, GnuTLS) - to select which TLS/SSL library
+ should be used for encrypted server connections.
+
+ - --disable-tls - to make without TLS/SSL support. Use this option if
+ you can not neither OpenSSL nor GnuTLS.
+
+ - --disable-gzip - to make without gzip support. Use this option
+ if you can not use zlib.
+
+ - --enable-debug - to build in debug-mode, if you want to see and log
+ debug-messages.
+
+### Optional package: par-check
+-------------------------------
+NZBGet can check and repair downloaded files for you. For this purpose
+it uses library par2.
+
+For your convenience the source code of libpar2 is integrated into
+NZBGet’s source tree and is compiled automatically when you make NZBGet.
+
+In a case errors occur during this process the inclusion of par2-module
+can be disabled using configure option "--disable-parcheck":
+```
+./configure --disable-parcheck
+```
+
+### Optional package: curses
+----------------------------
+For curses-outputmode you need ncurses or curses on your system.
+If you do not have one of them you can download and compile ncurses yourself.
+Following configure-parameters may be useful:
+
+ - --with-libcurses-includes=/path/to/curses/includes
+ - --with-libcurses-libraries=/path/to/curses/libraries
+
+If you are not able to use curses or ncurses or do not want them you can
+make the program without support for curses using option "--disable-curses":
+```
+./configure --disable-curses
+```
+
+### Optional package: TLS
+-------------------------
+To enable encrypted server connections (TLS/SSL) you need to build the program
+with TLS/SSL support. NZBGet can use two libraries: OpenSSL or GnuTLS.
+Configure-script checks which library is installed and use it. If both are
+available it gives the precedence to OpenSSL. You may override that with
+the option --with-tlslib=(OpenSSL, GnuTLS). For example to build with GnuTLS:
+```
+./configure --with-tlslib= GnuTLS
+```
+
+Following configure-parameters may be useful:
+
+ - --with-libtls-includess=/path/to/gnutls/includes
+ - --with-libtls-libraries=/path/to/gnutls/libraries
+
+ - --with-openssl-includess=/path/to/openssl/includes
+ - --with-openssl-libraries=/path/to/openssl/libraries
+
+If none of these libraries is available you can make the program without
+TLS/SSL support using option "--disable-tls", but
+ some features of nzbget will stop working, such as Extension Manager:
+```
+./configure --disable-tls
+```
+## Known issues:
+- does not compile on `armhf` hosts due to `yencode` library optimizations for vfp fpu hosts;
diff --git a/docs/WINDOWS.md b/docs/WINDOWS.md
new file mode 100644
index 000000000..e309cdea2
--- /dev/null
+++ b/docs/WINDOWS.md
@@ -0,0 +1,87 @@
+## To build NZBGet you will need:
+
+ - [CMake](https://cmake.org/)
+ - [MS C++ Build tools](https://visualstudio.microsoft.com/downloads/?q=build+tools#build-tools-for-visual-studio-2022)
+ - Download `Build Tools for Visual Studio 2022` and install it
+ - Select `Desktop development with C++` in the `Desktop & Mobile` section and install the necessary components:
+ - MSVC v143 - VS 2022 C++ x64/x86 build tools
+ - Windows 11 SDK
+ - C++ ATL for latest v143 build tools
+ - C++ MFC for latest v143 build tools
+ - Edit the `Path` enviroment variable and append the folder's path that contains the `MSBuild.exe` to it, e.g.:
+
+ `C:\Users\asus\AppData\Local\Programs\Microsoft VS Code\bin\`
+
+To compile the program with TLS/SSL support you need OpenSSL:
+ - [OpenSSL](https://www.openssl.org)
+
+Also required are:
+ - [Zlib](https://gnuwin32.sourceforge.net/packages/zlib.htm)
+ - [libxml2](https://gitlab.gnome.org/GNOME/libxml2/-/wikis/home)
+ - [Boost.JSON](https://www.boost.org/doc/libs/1_84_0/libs/json/doc/html/index.html)
+ - [Boost.Optional](https://www.boost.org/doc/libs/1_84_0/libs/optional/doc/html/index.html)
+
+For tests:
+ - [Boost.Test](https://www.boost.org/doc/libs/1_84_0/libs/test/doc/html/index.html)
+
+We recommend using [vcpkg](https://vcpkg.io/) to install dependencies:
+ - Clone the repository to the recommended `C:\` disk:
+```
+git clone --depth 1 https://github.com/microsoft/vcpkg.git
+```
+ - Run the `bootstrap` script:
+```
+.\vcpkg\bootstrap-vcpkg.bat
+```
+ - Edit the `Path` enviroment variable and append the folder's path: `C:\vcpkg`
+ - Install all the dependencies:
+```
+vcpkg install openssl:x64-windows-static
+vcpkg install libxml2:x64-windows-static
+vcpkg install zlib:x64-windows-static
+vcpkg install boost-json:x64-windows-static
+vcpkg install boost-optional:x64-windows-static
+```
+ - For tests:
+```
+vcpkg install boost-test:x64-windows-static
+```
+
+For `Win32`, instead of `:x64-windows-static`, use `:x86-windows-static`.
+
+ - Configure:
+```
+mkdir build
+cd build
+cmake .. -DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_TARGET_TRIPLET=x64-windows-static -A x64
+```
+ - Or for Win32:
+```
+cmake .. -DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_TARGET_TRIPLET=x86-windows-static -A Win32
+```
+ - Release build:
+```
+cmake --build . --config Release
+```
+ - Or for debug build:
+```
+cmake .. -DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_TARGET_TRIPLET=x64-windows-static -DCMAKE_BUILD_TYPE=Debug
+```
+ - Debug build:
+```
+cmake --build . --config Debug
+```
+ - Now, you can find the binary in the `Release/Debug` directory.
+
+
+You may run configure with additional arguments:
+ - Enable tests:
+```
+cmake .. -DENABLE_TESTS=ON -DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_TARGET_TRIPLET=x64-windows-static
+```
+ - Disable TLS. Use this option if you can not use OpenSSL but
+ some features of nzbget will stop working, such as Extension Manager:
+
+```
+cmake .. -DDISABLE_TLS=ON -DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_TARGET_TRIPLET=x64-windows-static
+```
diff --git a/docs/extensions/EXTENSIONS.md b/docs/extensions/EXTENSIONS.md
new file mode 100644
index 000000000..e9af67920
--- /dev/null
+++ b/docs/extensions/EXTENSIONS.md
@@ -0,0 +1,365 @@
+## About
+
+The core functionality of NZBGet can be extended using extensions.
+NZBGet provides documented entry points for extensions.
+On certain events the extensions are executed, they receive information about event,
+do certain work and can communicate with NZBGet to give it instructions for further processing.
+
+## Installation
+
+### Using the Extension Manager
+
+On the `SETTINGS` page you can easily find `EXTENSION MANAGER`
+and use it to install the extensions you need. Make sure that the internet connection is working
+and the path to the `7z` in `UNPACK->SevenZipCmd`(required for unpacking the extensions) is correct.
+The list of available extensions can be found in the
+[nzbget-extensions](https://github.com/nzbgetcom/nzbget-extensions) repository.
+
+### Manually, for your custom extensions
+
+Option `ScriptDir` defines the location of extensions.
+To make an extension available in NZBGet put the extension into this directory.
+Then go to settings tab in web-interface (if you were already on settings
+tab switch to downloads tab and then back to settings
+tab to reread the list of available extensions from the disk).
+
+Menu at the left of page should list all extensions found in `ScriptDir`.
+Select an extension to review or change its options (if it has any).
+
+## Writing extension
+
+In general, an extension consists of 2 files: `manifest.json` -
+with all the meta-data describing the extension
+and the `executable` file, like `main.py`.
+
+`manifest.json` example:
+```json
+{
+ "main": "main.py",
+ "name": "EMail",
+ "homepage": "https://github.com/nzbgetcom/Extension-EMail",
+ "kind": "POST-PROCESSING",
+ "displayName": "My EMail Extension",
+ "version": "2.0.0",
+ "author": "John Doe",
+ "license": "GNU",
+ "about": "Sends E-Mail notification.",
+ "queueEvents": "",
+ "requirements": [
+ "This script requires Python3.8 to be installed on your system."
+ ],
+ "description": ["This script sends E-Mail notification when the job is done."],
+ "options": [
+ {
+ "name": "Server",
+ "displayName": "Server",
+ "value": "smtp.gmail.com",
+ "description": ["SMTP server host."],
+ "select": []
+ },
+ {
+ "name": "Port",
+ "displayName": "Port",
+ "value": 25,
+ "description": ["SMTP server port (1-65535)"],
+ "select": [1, 65535]
+ },
+ {
+ "name": "SendMail",
+ "displayName": "SendMail",
+ "value": "Always",
+ "description": ["When to send the message."],
+ "select": ["Always", "OnFailure"]
+ },
+ ],
+ "commands": [
+ {
+ "name": "ConnectionTest",
+ "action": "Send Test E-Mail",
+ "displayName": "ConnectionTest",
+ "description": ["To check connection parameters click the button."]
+ }
+ ],
+ "taskTime": ""
+}
+```
+
+### `"main"`
+
+The name of the executable file.
+For example: `main.py`, `main.exe`, `MyExt.sh`.
+
+### `"name"`
+
+The extension name, identifier and prefix needed to
+save the extension configuration options to `nzbget.conf`.
+
+### `"homepage"`
+
+Just a link to the repository where the extension lives.
+
+### `"kind"`
+
+Depending on the purpose of the extension, can be:
+```
+"kind": "POST-PROCESSING"
+"kind": "SCAN"
+"kind": "QUEUE"
+"kind": "SCHEDULER"
+"kind": "FEED"
+```
+
+If the extension can be used for multiple purposes the `kind` can be mixed, for example:
+```
+"kind": "SCAN/QUEUE"
+```
+
+More information about extension kinds can be found at:
+ - [POST-PROCESSING](POST-PROCESSING.md)
+ - [SCAN](SCAN.md)
+ - [QUEUE](QUEUE.md)
+ - [SCHEDULER](SCHEDULER.md)
+ - [FEED](FEED.md)
+
+### `"displayName"`
+
+The name that will be displayed in the web interface.
+
+### `"version"`
+
+Extension version.
+
+### `"author"`
+
+Author's name.
+
+### `"license"`
+
+Extension license.
+
+### `"about"`
+
+Brief description of the extension.
+
+### `"description"`
+
+For more detailed description of the extension.
+
+### `"queueEvents"`
+
+To describe the events that could be used by the extension, e.g.:
+
+```json
+"queueEvents": "NZB_ADDED, NZB_DOWNLOADED"
+```
+
+More information can be found at [QUEUE](QUEUE.md).
+
+### "`requirements"`
+
+To describe the list of requirements, e.g.:
+
+```json
+"requirements": [
+ "This script requires Python3.8+ to be installed on your system."
+],
+```
+
+### `"options"`
+
+Let’s say we are writing an extension to send E-Mail notification.
+The user needs to configure the extension with options such as SMTP-Server host,
+port, login and password. To avoid hard-coding of these data in the extension
+NZBGet allows the extension to define the required options.
+The options are then made available on the settings page for user to configure.
+
+In the provided `manifest.json` example we defined three options:
+
+```json
+"options": [
+ {
+ "name": "Server",
+ "displayName": "Server",
+ "value": "smtp.gmail.com",
+ "description": ["SMTP server host."],
+ "select": []
+ },
+ {
+ "name": "Port",
+ "displayName": "Port",
+ "value": 25,
+ "description": ["SMTP server port (1-65535)"],
+ "select": [1, 65535]
+ },
+ {
+ "name": "SendMail",
+ "displayName": "SendMail",
+ "value": "Always",
+ "description": ["When to send the message."],
+ "select": ["Always", "OnFailure"]
+ },
+],
+```
+
+When the user saves settings in web-interface the extension configuration
+options are saved to NZBGet configuration file using the extension name as prefix. For example:
+```
+EMail:Server=smtp.gmail.com
+EMail:Port=25
+```
+
+Extension configuration options are passed using env-vars with prefix `NZBPO_`.
+There are two env-vars for each option:
+ - one env-var with the name exactly as defined by pp-option;
+ - another env-var with the name written in UPPER CASE and with
+ special characters replaced with underscores.
+
+For example, for pp-option `Server.Name` two env-vars are passed:
+`NZBPO_Server.Name` and `NZBPO_SERVER_NAME`.
+
+> In a case the user has installed the extension but have not saved the configuration, the options are not saved to
+configuration file yet. The extension will not get the options passed.
+This is a situation your extension must handle. You can either use a default settings or terminate the extension with
+a proper message asking the user to check and save configuration in web-interface.
+
+Example (python):
+```python
+required_options = ('NZBPO_FROM', 'NZBPO_TO', 'NZBPO_SERVER', 'NZBPO_PORT', 'NZBPO_ENCRYPTION',
+'NZBPO_USERNAME', 'NZBPO_PASSWORD', 'NZBPO_FILELIST', 'NZBPO_BROKENLOG', 'NZBPO_POSTPROCESSLOG')
+for optname in required_options:
+if (not optname in os.environ):
+ print('[ERROR] Option %s is missing in configuration file. Please check script settings' % optname[6:])
+ sys.exit(POSTPROCESS_ERROR)
+```
+
+### `"commands"`
+
+Sometimes it may be helpful to be able to execute extension extensions from settings page.
+For example pp-extension EMail could use a button "Send test email". For other extensions something like
+"Validate settings" or "Cleanup database" may be useful too.
+
+Starting from v19 it is possible to put buttons on the extension settings page. The buttons are defined as
+part of extension configuration, almost similar to extension configuration options:
+```json
+"commands": [
+ {
+ "name": "ConnectionTest",
+ "action": "Send Test E-Mail",
+ "displayName": "ConnectionTest",
+ "description": ["To check connection parameters click the button."]
+ }
+],
+```
+
+This example creates a button with text "Send Test E-Mail" and description
+"To check connection parameters click the button.".
+
+When user presses the button NZBGet executes the extension in a special context passing
+button name via env. var NZBCP_COMMAND.
+The extension can check if it runs in command mode by examining this variable (python example):
+```python
+# Exit codes used by NZBGet
+COMMAND_SUCCESS=93
+COMMAND_ERROR=94
+
+# Check if the script is executed from settings page with a custom command
+command = os.environ.get('NZBCP_COMMAND')
+test_mode = command == 'ConnectionTest'
+if command != None and not test_mode:
+ print('[ERROR] Invalid command ' + command)
+ sys.exit(COMMAND_ERROR)
+
+if test_mode:
+ print('[INFO] Test connection...')
+ sys.exit(COMMAND_SUCCESS)
+
+