File: //remove_htaccess_hacked/remove_htaccess_awk.sh
#!/usr/bin/env bash
set -euo pipefail
IFS=$'\n\t'
MODE="${1:-dry}" # dry | apply
BACKUP_EXT=".bak"
TMPDIR="$(mktemp -d)"
echo "Mode: $MODE"
echo "Temp dir: $TMPDIR"
# AWK program:
# - legge file e raccoglie blocchi <FilesMatch ...> ... </FilesMatch>
# - se (apertura contiene .(py|exe|php|suspected) OR inner contiene that) AND inner contiene "deny from all" -> rimuove
# - OR se inner contiene wp-blog-header.php AND inner contains "allow from all" -> rimuove
# - confronto case-insensitive
AWK_PROG='
BEGIN {
IGNORECASE = 1;
inblock = 0;
block = "";
openline = "";
}
{
line = $0;
# preserve original lines in array to print later
if (inblock == 0) {
if (match(line, /^[[:space:]]*<FilesMatch\b/)) {
inblock = 1;
block = line "\n";
openline = line;
} else {
print line;
}
} else {
block = block line "\n";
if (match(line, /<\/FilesMatch>/)) {
# abbiamo il blocco completo in 'block', testiamo criteri
# estraiamo attributi dall'apertura (apriamo tra <FilesMatch e >)
attrs = openline;
# normalizziamo lowercase per test
low = tolower(block);
low_attrs = tolower(attrs);
remove = 0;
# criterio 1: pattern .(py|exe|php|suspected) presente in attrs o nel block
if (low_attrs ~ /\.\\(py|exe|php|suspected/ || low ~ /\.\\(py|exe|php|suspected/) {
if (low ~ /deny[[:space:]]+from[[:space:]]+all/) { remove = 1; }
}
# criterio 2: wp-blog-header.php presente e allow from all
if (low ~ /wp-blog-header\.php/ && low ~ /allow[[:space:]]+from[[:space:]]+all/) { remove = 1; }
if (remove == 1) {
# skip printing block (i.e. remove it)
# do nothing
} else {
# print block as-is
printf "%s", block;
}
# reset
inblock = 0;
block = "";
openline = "";
}
}
}
END {
# se file termina mentre siamo in block (mancante </FilesMatch>), ri-scrivi block
if (inblock == 1) {
printf "%s", block;
}
}
'
# trova file .htaccess
mapfile -d '' FILES < <(find . -type f -name ".htaccess" -print0)
if [ "${#FILES[@]}" -eq 0 ]; then
echo "Nessun file .htaccess trovato."
rm -rf "$TMPDIR"
exit 0
fi
echo "Trovati ${#FILES[@]} file .htaccess"
for f in "${FILES[@]}"; do
out="$TMPDIR/$(basename "$f").out"
# AWK legge il file e produce l'output senza il blocco se corrisponde
awk "$AWK_PROG" "$f" > "$out" || { echo "Errore AWK su $f"; rm -f "$out"; continue; }
# Se identico -> niente da fare
if cmp -s "$f" "$out"; then
rm -f "$out"
continue
fi
if [ "$MODE" = "dry" ]; then
echo "=== DRY diff per $f ==="
diff -u --label "orig: $f" --label "new: $f.new" "$f" "$out" | sed -n '1,200p' || true
echo "=== fine diff ==="
rm -f "$out"
else
cp --preserve=mode,timestamps "$f" "$f${BACKUP_EXT}"
mv "$out" "$f"
echo "Aggiornato: $f (backup: $f${BACKUP_EXT})"
fi
done
rm -rf "$TMPDIR"
echo "Completato."
exit 0