fix whiptail capture bug (2>/dev/null killed selections); add artic; fix ENABLE_MAP

Root cause of all 85 engines being disabled:
  `3>&1 1>&2 2>&3 2>/dev/null` — the trailing `2>/dev/null` overwrites FD2
  with /dev/null AFTER the FD swap, destroying the pipe that whiptail writes
  selections to. User selections were silently discarded every time. Remove it.

Also: if whiptail exits 0 but returns empty string (all items unchecked),
fall back to pre-checked defaults rather than disabling everything.

ENABLE_MAP: unbound variable (configure-searxng-safesearch.sh):
  bash < 4.4 treats `${!empty_assoc[@]}` as unbound under `set -u`.
  Wrap for loops and mark_disabled key-check with set +u / set -u.

Add artic (Art Institute of Chicago) to image engine menus.
Add yandex images (defaults OFF for moderate/strict, same as yandex).
Update _SX_AUTOFF to include "yandex images" so re-enabling it works.
Update configure script engine category lists to match expanded menus.

https://claude.ai/code/session_012gDnantBmFTWZGCiKyjazx
This commit is contained in:
Claude
2026-03-21 05:45:30 +00:00
parent fc10cbf668
commit b090b902c0
3 changed files with 44 additions and 20 deletions
+18 -8
View File
@@ -81,24 +81,29 @@ NO_SAFESEARCH_ENGINES=(
# Web engines without safe-search API
"mojeek" "naver" "baidu"
# Yandex: parameter exists but not reliably enforced for non-Russian queries
"yandex"
"yandex" "yandex images"
# Video frontends — no safe-search passthrough
"invidious" "piped" "peertube" "sepiasearch"
)
# ── Category → engine lists ───────────────────────────────────────────────────
VIDEOS_ENGINES=(
"youtube" "invidious" "piped" "peertube" "sepiasearch"
"dailymotion" "vimeo"
"bing videos" "duckduckgo videos" "google videos"
"youtube" "bing videos" "brave videos" "duckduckgo videos" "google videos" "qwant videos"
"dailymotion" "media.ccc.de" "wikcommons.videos"
"vimeo" "odysee" "rumble" "bitchute"
"invidious" "piped" "peertube" "sepiasearch"
)
IMAGES_ENGINES=(
"google images" "bing images" "duckduckgo images"
"brave images" "qwant images"
"flickr" "unsplash" "imgur" "deviantart" "openverse"
"google images" "bing images" "duckduckgo images" "brave images" "qwant images"
"startpage images" "mojeek images" "presearch images"
"openverse" "unsplash" "pexels" "pixabay images" "pinterest" "flickr"
"wikcommons.images" "artic" "yandex images"
"imgur" "deviantart" "artstation" "adobe stock"
)
NEWS_ENGINES=(
"google news" "bing news" "duckduckgo news" "brave news" "qwant news"
"startpage news" "presearch news" "mojeek news"
"reuters" "yahoo news" "wikinews" "yep news"
)
SCIENCE_ENGINES=(
"arxiv" "semantic scholar" "pubmed" "crossref" "base"
@@ -123,7 +128,9 @@ fi
# Helper: add to DISABLE_MAP unless explicitly re-enabled
mark_disabled() {
local eng="$1"
[[ -n "${ENABLE_MAP[$eng]+x}" ]] && return # user said keep it
# Use set +u to safely check array key existence on bash < 4.4 (set -u quirk)
set +u; local _chk="${ENABLE_MAP[$eng]+x}"; set -u
[[ -n "$_chk" ]] && return # user said keep it
DISABLE_MAP["$eng"]=1
}
@@ -167,12 +174,15 @@ SECRET_KEY=$(grep -oP '(?<=secret_key: ")[^"]+' "$SETTINGS" 2>/dev/null || true)
# ── Build engine override block ───────────────────────────────────────────────
ENGINE_BLOCK=""
# set +u: iterating empty associative arrays throws "unbound variable" on bash <4.4
set +u
for eng in "${!DISABLE_MAP[@]}"; do
ENGINE_BLOCK+=" - name: ${eng}\n disabled: true\n"
done
for eng in "${!ENABLE_MAP[@]}"; do
ENGINE_BLOCK+=" - name: ${eng}\n disabled: false\n"
done
set -u
# ── Write settings.yml ────────────────────────────────────────────────────────
{
+13 -6
View File
@@ -593,7 +593,8 @@ if $INSTALL_AI && $SVC_SEARXNG; then
[[ "$SEARXNG_SAFE_LEVEL" == "none" ]] && echo ON && return
case "$1" in
mojeek|"mojeek images"|"mojeek news"|\
yandex|baidu|naver|\
yandex|"yandex images"|\
baidu|naver|\
invidious|piped|peertube|sepiasearch|\
vimeo|bitchute|rumble|odysee|\
imgur|deviantart|artstation) echo OFF ;;
@@ -614,11 +615,15 @@ if $INSTALL_AI && $SVC_SEARXNG; then
done
local _h=$(( ${#_n[@]} + 9 > 24 ? 24 : ${#_n[@]} + 9 ))
local _lh=$(( ${#_n[@]} < 14 ? ${#_n[@]} : 14 ))
local _o _j
if ! _o=$(whiptail --backtitle "SearXNG — $SEARXNG_SAFE_LEVEL" \
local _o _rc _j
# Note: NO 2>/dev/null after the FD swap — that redirect would overwrite
# the pipe (FD2 after swap) with /dev/null, silently discarding selections.
_o=$(whiptail --backtitle "SearXNG — $SEARXNG_SAFE_LEVEL" \
--title "$_t" --checklist \
"SPACE = toggle ENTER = confirm ESC = use defaults" \
"$_h" 76 "$_lh" "${_a[@]}" 3>&1 1>&2 2>&3 2>/dev/null); then
"$_h" 76 "$_lh" "${_a[@]}" 3>&1 1>&2 2>&3) && _rc=0 || _rc=$?
if [[ $_rc -ne 0 ]] || [[ -z "${_o//\"}" ]]; then
# ESC / cancel / empty selection → use pre-checked defaults
for _j in "${!_n[@]}"; do
[[ "${_s[$_j]}" == "ON" ]] && printf '%s\n' "${_n[$_j]}"
done
@@ -629,7 +634,7 @@ if $INSTALL_AI && $SVC_SEARXNG; then
# Engines auto-disabled by configure script for moderate/strict.
# If user re-enables one in the menu we pass --enable-engines to override.
_SX_AUTOFF=(mojeek yandex baidu naver invidious piped peertube sepiasearch)
_SX_AUTOFF=(mojeek yandex "yandex images" baidu naver invidious piped peertube sepiasearch)
if command -v whiptail &>/dev/null && [[ -t 0 ]]; then
# ── Web search ─────────────────────────────────────────────────────────
@@ -667,6 +672,8 @@ if $INSTALL_AI && $SVC_SEARXNG; then
"pinterest" "Pinterest" ON \
"flickr" "Flickr" ON \
"wikcommons.images" "Wikimedia Commons Images" ON \
"artic" "Art Institute of Chicago" ON \
"yandex images" "Yandex Images [no safe-search]" "$(_sxst 'yandex images')" \
"imgur" "Imgur [adult content]" "$(_sxst imgur)" \
"deviantart" "DeviantArt [adult content]" "$(_sxst deviantart)" \
"artstation" "ArtStation [adult content]" "$(_sxst artstation)" \
@@ -739,7 +746,7 @@ if $INSTALL_AI && $SVC_SEARXNG; then
"google images" "bing images" "duckduckgo images" "brave images" "qwant images"
"startpage images" "mojeek images" "presearch images"
"openverse" "unsplash" "pexels" "pixabay images" "pinterest" "flickr"
"wikcommons.images" "imgur" "deviantart" "artstation" "adobe stock"
"wikcommons.images" "artic" "yandex images" "imgur" "deviantart" "artstation" "adobe stock"
# Videos
"youtube" "bing videos" "brave videos" "duckduckgo videos" "google videos" "qwant videos"
"dailymotion" "media.ccc.de" "wikcommons.videos"
+13 -6
View File
@@ -66,7 +66,8 @@ _sxst() {
[[ "$SEARXNG_SAFE_LEVEL" == "none" ]] && echo ON && return
case "$1" in
mojeek|"mojeek images"|"mojeek news"|\
yandex|baidu|naver|\
yandex|"yandex images"|\
baidu|naver|\
invidious|piped|peertube|sepiasearch|\
vimeo|bitchute|rumble|odysee|\
imgur|deviantart|artstation) echo OFF ;;
@@ -86,11 +87,15 @@ _sxmenu() {
done
local _h=$(( ${#_n[@]} + 9 > 24 ? 24 : ${#_n[@]} + 9 ))
local _lh=$(( ${#_n[@]} < 14 ? ${#_n[@]} : 14 ))
local _o _j
if ! _o=$(whiptail --backtitle "SearXNG — $SEARXNG_SAFE_LEVEL" \
local _o _rc _j
# Note: NO 2>/dev/null after the FD swap — that redirect would overwrite
# the pipe (FD2 after swap) with /dev/null, silently discarding selections.
_o=$(whiptail --backtitle "SearXNG — $SEARXNG_SAFE_LEVEL" \
--title "$_t" --checklist \
"SPACE = toggle ENTER = confirm ESC = use defaults" \
"$_h" 76 "$_lh" "${_a[@]}" 3>&1 1>&2 2>&3 2>/dev/null); then
"$_h" 76 "$_lh" "${_a[@]}" 3>&1 1>&2 2>&3) && _rc=0 || _rc=$?
if [[ $_rc -ne 0 ]] || [[ -z "${_o//\"}" ]]; then
# ESC / cancel / empty selection → use pre-checked defaults
for _j in "${!_n[@]}"; do
[[ "${_s[$_j]}" == "ON" ]] && printf '%s\n' "${_n[$_j]}"
done
@@ -99,7 +104,7 @@ _sxmenu() {
for _id in $_o; do _id="${_id//\"/}"; printf '%s\n' "${_n[$(( _id-1 ))]}"; done
}
_SX_AUTOFF=(mojeek yandex baidu naver invidious piped peertube sepiasearch)
_SX_AUTOFF=(mojeek yandex "yandex images" baidu naver invidious piped peertube sepiasearch)
if command -v whiptail &>/dev/null && [[ -t 0 ]]; then
# ── Web search ─────────────────────────────────────────────────────────────
@@ -137,6 +142,8 @@ if command -v whiptail &>/dev/null && [[ -t 0 ]]; then
"pinterest" "Pinterest" ON \
"flickr" "Flickr" ON \
"wikcommons.images" "Wikimedia Commons Images" ON \
"artic" "Art Institute of Chicago" ON \
"yandex images" "Yandex Images [no safe-search]" "$(_sxst 'yandex images')" \
"imgur" "Imgur [adult content]" "$(_sxst imgur)" \
"deviantart" "DeviantArt [adult content]" "$(_sxst deviantart)" \
"artstation" "ArtStation [adult content]" "$(_sxst artstation)" \
@@ -209,7 +216,7 @@ if command -v whiptail &>/dev/null && [[ -t 0 ]]; then
"google images" "bing images" "duckduckgo images" "brave images" "qwant images"
"startpage images" "mojeek images" "presearch images"
"openverse" "unsplash" "pexels" "pixabay images" "pinterest" "flickr"
"wikcommons.images" "imgur" "deviantart" "artstation" "adobe stock"
"wikcommons.images" "artic" "yandex images" "imgur" "deviantart" "artstation" "adobe stock"
# Videos
"youtube" "bing videos" "brave videos" "duckduckgo videos" "google videos" "qwant videos"
"dailymotion" "media.ccc.de" "wikcommons.videos"