File: //remove_htaccess_hacked/remove_all_htaccess_recursive.sh
#!/usr/bin/env bash
set -euo pipefail
IFS=$'\n\t'
SELF="$(basename "$0")"
MODE="${1:-help}"
BACKUP_EXT=".bak"
TMPDIR="$(mktemp -d)"
usage() {
cat <<USAGE
Usage:
$SELF list
$SELF dry
$SELF apply
$SELF help
USAGE
}
# Perl program (file trasformazione): rimuove i blocchi FilesMatch esatti come da tuo esempio,
# tollera apici singoli/doppi, maiuscole/minuscole, spazi/tab, CRLF/LF.
cat > "$TMPDIR/remove_block.pl" <<'PERL'
#!/usr/bin/env perl
use strict;
use warnings;
local $/ = undef;
my $text = <>; $text =~ s/\r\n?/\n/g;
# Rimuovi tutti i blocchi <FilesMatch ...>...</FilesMatch> se:
# - l'apertura contiene la sequenza .(py|exe|php|php5|php7|suspected)$
# - il corpo contiene sia "Order allow,deny" che "Deny from all"
# Matching case-insensitive, non-greedy for body.
$text =~ s{
(<FilesMatch\b # opening tag start
[^>]*? # any attrs up to quote
(["']) # quote in $2
[^>]*? # anything
\.\(py\|exe\|php\|php5\|php7\|suspected\)\$ # the extension group
[^>]*? # remainder of opening tag
\2 # matching closing quote
[^>]*?> # end opening tag
)
(.*?) # inner body (non-greedy)
(</FilesMatch>) # closing tag
}{
my ($open,$body,$close) = ($1,$3,$4);
my $low = lc($body);
if ($low =~ /order\s+allow\s*,\s*deny/ && $low =~ /deny\s+from\s+all/) {
"" # remove full block
} else {
$open . $body . $close; # keep
}
}isgex;
# normalize blank lines & ensure final newline
$text =~ s/\n{3,}/\n\n/g;
$text .= "\n" unless $text =~ /\n\z/;
print $text;
PERL
chmod +x "$TMPDIR/remove_block.pl"
# find all .htaccess recursively
find_htaccess() {
find . -type f -name ".htaccess" -print0
}
# list
if [ "$MODE" = "list" ]; then
echo "Elenco .htaccess (ricorsivo):"
find . -type f -name ".htaccess" -print | sed -n '1,200p'
rm -rf "$TMPDIR"
exit 0
fi
if [ "$MODE" = "help" ]; then
usage
rm -rf "$TMPDIR"
exit 0
fi
if [ "$MODE" != "dry" ] && [ "$MODE" != "apply" ]; then
usage
rm -rf "$TMPDIR"
exit 1
fi
# iterate all .htaccess files found recursively
while IFS= read -r -d '' file; do
out="$TMPDIR/$(echo "$file" | sed 's|/|_|g').out"
if ! "$TMPDIR/remove_block.pl" "$file" > "$out"; then
# perl returned non-zero => no change (we treat as no-match), but still keep going
rm -f "$out"
printf "%s : No match (nessuna modifica)\n" "$file"
continue
fi
if cmp -s "$file" "$out"; then
rm -f "$out"
printf "%s : No match (nessuna modifica)\n" "$file"
continue
fi
if [ "$MODE" = "dry" ]; then
echo "=== DIFF (dry) : $file ==="
diff -u --label "orig: $file" --label "new: $file.new" "$file" "$out" | sed -n '1,200p' || true
echo "=== end diff ==="
rm -f "$out"
else
cp --preserve=mode,timestamps "$file" "${file}${BACKUP_EXT}"
mv "$out" "$file"
printf "%s : Modificato (backup: %s%s)\n" "$file" "$file" "$BACKUP_EXT"
fi
done < <(find_htaccess)
rm -rf "$TMPDIR"
echo "Operazione completata."
exit 0