Webmin and the Standard Module Choice
Have you ever woken up and wondered why people that are so smart can make such incredibly stupid choices?
Scenario
Webmin installed on OpenWRT with no "Standard module" choice from the Webmin Modules Form. Apparently that 'feature' / choice was removed a while ago with no consideration for "Generic Linux" installs. Cool. NOT!
Solution
And the code that'll do everything automatically;
#!/bin/ash
WEBMIN_ROOT="/usr/local/webmin"
WEBMIN_CONF="/etc/webmin"
WEBMIN_MOD="$WEBMIN_ROOT/webmin"
CATALOG="$WEBMIN_MOD/standard-local.txt"
LANG="$WEBMIN_MOD/lang/en"
STAGE="/tmp/webmin-standard-fix.$$"
BASE="https://raw.githubusercontent.com/webmin/webmin/2.020/webmin"
MODULE_INDEX="http://download.webmin.com/download/modules"
fail() {
echo "FAILED: $1"
rm -rf "$STAGE"
exit 1
}
mkdir -p "$STAGE" "$WEBMIN_CONF/webmin" || fail "mkdir failed"
[ -d "$WEBMIN_MOD" ] || fail "$WEBMIN_MOD does not exist"
[ -f "$LANG" ] || fail "$LANG does not exist"
wget -O "$STAGE/edit_mods.cgi" "$BASE/edit_mods.cgi" || fail "download edit_mods.cgi"
wget -O "$STAGE/install_mod.cgi" "$BASE/install_mod.cgi" || fail "download install_mod.cgi"
wget -O "$STAGE/standard_chooser.cgi" "$BASE/standard_chooser.cgi" || fail "download standard_chooser.cgi"
[ -s "$STAGE/edit_mods.cgi" ] || fail "edit_mods.cgi is empty"
[ -s "$STAGE/install_mod.cgi" ] || fail "install_mod.cgi is empty"
[ -s "$STAGE/standard_chooser.cgi" ] || fail "standard_chooser.cgi is empty"
sed -i 's|\$file = &transname(\$info->\[2\]);|\$file = \&transname(\&file_basename($info->[2]));|' "$STAGE/install_mod.cgi" || fail "patch install_mod.cgi"
grep -Fq 'file_basename($info->[2])' "$STAGE/install_mod.cgi" || fail "install_mod.cgi URL filename patch missing"
wget -O - "$MODULE_INDEX/" 2>/dev/null | \
sed -n 's/.*href="\([^"]*\.wbm\.gz\)".*/\1/p' | \
while read F; do
M="${F%.wbm.gz}"
printf "%s\t0\t%s/%s\t*\t%s\n" "$M" "$MODULE_INDEX" "$F" "$M"
done | sort > "$STAGE/standard-local.txt"
[ -s "$STAGE/standard-local.txt" ] || fail "standard-local.txt build failed"
cp "$STAGE/edit_mods.cgi" "$WEBMIN_MOD/edit_mods.cgi" || fail "install edit_mods.cgi"
cp "$STAGE/install_mod.cgi" "$WEBMIN_MOD/install_mod.cgi" || fail "install install_mod.cgi"
cp "$STAGE/standard_chooser.cgi" "$WEBMIN_MOD/standard_chooser.cgi" || fail "install standard_chooser.cgi"
cp "$STAGE/standard-local.txt" "$CATALOG" || fail "install standard-local.txt"
chmod 755 "$WEBMIN_MOD/edit_mods.cgi" "$WEBMIN_MOD/install_mod.cgi" "$WEBMIN_MOD/standard_chooser.cgi" || fail "chmod CGI files"
sed -i '/^# BEGIN LOCAL STANDARD MODULE CATALOG$/,/^# END LOCAL STANDARD MODULE CATALOG$/d' "$WEBMIN_MOD/webmin-lib.pl" || fail "remove old local catalog override"
cat >> "$WEBMIN_MOD/webmin-lib.pl" <<'EOF'
# BEGIN LOCAL STANDARD MODULE CATALOG
sub list_standard_modules {
my $local = "/usr/local/webmin/webmin/standard-local.txt";
my @rv;
open(TEMP, "<".$local) || return "Cannot read ".$local;
while(<TEMP>) {
s/\r|\n//g;
next if (!/\S/ || /^\s*#/);
my @l = split(/\t+/, $_);
push(@rv, \@l);
}
close(TEMP);
return \@rv;
}
sub standard_chooser_button {
return &popup_window_button("standard_chooser.cgi", 800, 500, 1, [ [ "ifield", $_[0], "mod" ] ]);
}
1;
# END LOCAL STANDARD MODULE CATALOG
EOF
sed -i '/^mods_standard=/d;/^mods_standard2=/d' "$LANG" || fail "remove old label entries"
cat >> "$LANG" <<'EOF'
mods_standard=Standard module
mods_standard2=Standard module
EOF
touch "$WEBMIN_CONF/webmin/config" || fail "touch Webmin config"
sed -i '/^standard_url=/d' "$WEBMIN_CONF/webmin/config" || fail "remove standard_url"
rm -f /www/webmin-standard.txt /tmp/patch-webmin-standard.pl /tmp/webmin-lib.pl.new
if [ -x /etc/init.d/webmin ]; then
/etc/init.d/webmin restart || fail "restart Webmin"
else
"$WEBMIN_ROOT/restart" || fail "restart Webmin"
fi
rm -rf "$STAGE"
echo "OK: Webmin Standard module chooser restored"
echo "OK: Catalog: $CATALOG"