HEX
Server: Apache/2.4.66 (Ubuntu)
System: Linux nic2 5.15.0-177-generic #187-Ubuntu SMP Sat Apr 11 22:54:33 UTC 2026 x86_64
User: www-data (33)
PHP: 8.2.30
Disabled: NONE
Upload Files
File: //remove_htaccess_hacked/remove_htaccess_debug_fixed.sh
#!/usr/bin/env bash
set -o errexit
set -o nounset
set -o pipefail

# Verbose/tracing: impostare TRACE=1 nell'ambiente per vedere i comandi eseguiti
TRACE="${TRACE:-0}"
if [ "$TRACE" -eq 1 ]; then
  set -x
fi

MODE="${1:-dry}"   # dry (default) | apply
LOGFILE="${2:-./remove_htaccess_debug_fixed.log}"
TMPDIR="$(mktemp -d)"
# pattern corretti per quick-grep (nota doppio backslash per preservare \. nella regex)
BLOCK_MATCH_SHORT='\\.(py|exe|php|suspected)'
BLOCK_MATCH_LONG='wp-blog-header\.php'

# Trap per errori non gestiti
trap 'rc=$?; echo "ERROR: script terminated with code $rc" | tee -a "$LOGFILE"; echo "Last 50 lines of log:" | tee -a "$LOGFILE"; tail -n 50 "$LOGFILE" || true; rm -rf "$TMPDIR"; exit $rc' ERR INT TERM

echo "[$(date --iso-8601=seconds)] Start script (mode=$MODE). Log: $LOGFILE" | tee "$LOGFILE"
echo "Temp dir: $TMPDIR" | tee -a "$LOGFILE"

# Funzione helper per stampare snippet con numeri di linea e hex (diagnostica)
dump_snippet() {
  local file="$1"; local start="$2"; local lines="${3:-20}"
  echo "----- snippet from $file (line $start, $lines lines) -----" | tee -a "$LOGFILE"
  sed -n "${start},$((start+lines-1))p" "$file" | sed -n '1,200p' | nl -ba -w3 -s': ' | tee -a "$LOGFILE"
  echo "----- hexdump (first 256 bytes) -----" | tee -a "$LOGFILE"
  head -c 256 "$file" | hexdump -C | tee -a "$LOGFILE"
  echo "--------------------------------------" | tee -a "$LOGFILE"
}

# Perl program robusto che:
# - slurp file, normalizza CRLF -> LF
# - trova tutti i blocchi <FilesMatch ...>...</FilesMatch>
# - rimuove quelli che corrispondono ai criteri (short+deny o long+allow)
PERL_PROGRAM='
use strict;
use warnings;
local $/ = undef;
my $content = <>;               # slurp file
$content =~ s/\r\n?/\n/g;       # normalize CRLF -> LF
my $orig = $content;
my $removed = 0;

# match all <FilesMatch ...>...</FilesMatch> blocks
while ($content =~ m{<FilesMatch\b([^>]*)>(.*?)</FilesMatch>}gis) {
  my $attrs = $1;
  my $inner = $2;
  my $test = lc($attrs . " " . $inner);
  # criteria: (1) contains .(py|exe|php or suspected) and "deny from all"
  #           (2) contains wp-blog-header.php and "allow from all"
  if ($test =~ qr/\.\(py\|exe\|php\|suspected/ && $test =~ /deny from all/) {
    # remove the first occurrence of this exact block (case-insensitive)
    $content =~ s{<FilesMatch\Q$attrs\E>\Q$inner\E</FilesMatch>}{}si;
    $removed++;
    next;
  }
  if ($test =~ /wp-blog-header\.php/ && $test =~ /allow from all/) {
    $content =~ s{<FilesMatch\Q$attrs\E>\Q$inner\E</FilesMatch>}{}si;
    $removed++;
    next;
  }
}

# collapse multiple blank lines
$content =~ s/\n{3,}/\n\n/g;

# print modified content only if we removed >=1 block
if ($removed) {
  print $content;
  exit 0;
} else {
  exit 1;
}
'

# trova file .htaccess (gestisce spazi e caratteri speciali nei nomi)
mapfile -d '' FILES < <(find . -type f -name ".htaccess" -print0)

if [ "${#FILES[@]}" -eq 0 ]; then
  echo "[$(date --iso-8601=seconds)] Nessun file .htaccess trovato." | tee -a "$LOGFILE"
  rm -rf "$TMPDIR"
  exit 0
fi

echo "[$(date --iso-8601=seconds)] Trovati ${#FILES[@]} file .htaccess" | tee -a "$LOGFILE"

modified_count=0
checked_count=0

for f in "${FILES[@]}"; do
  checked_count=$((checked_count+1))
  echo "Processing [$checked_count/${#FILES[@]}]: $f" | tee -a "$LOGFILE"

  # quick checks: usa grep -E (extended) e -i (case-insensitive)
  if ! grep -Eiq "$BLOCK_MATCH_SHORT|$BLOCK_MATCH_LONG" "$f"; then
    echo "  -> No quick pattern match (skip): non contiene '$BLOCK_MATCH_SHORT' né '$BLOCK_MATCH_LONG'." | tee -a "$LOGFILE"
    continue
  fi

  echo "  -> Quick match passato: mostro prime 40 righe per controllo" | tee -a "$LOGFILE"
  sed -n '1,40p' "$f" | nl -ba -w3 -s': ' | tee -a "$LOGFILE"

  out_tmp="$TMPDIR/out.$$.$(basename "$f")"
  if perl -0777 -e "$PERL_PROGRAM" "$f" > "$out_tmp" 2>>"$LOGFILE"; then
    # perl ha rimosso almeno un blocco (exit 0 e output)
    if cmp -s "$out_tmp" "$f"; then
      echo "  -> Perl ha detto che ha rimosso ma file identico: possibile problema encoding. Mostro snippet." | tee -a "$LOGFILE"
      dump_snippet "$f" 1 80
      rm -f "$out_tmp"
      continue
    fi

    if [ "$MODE" = "dry" ]; then
      echo "  -> DRY RUN: il file verrebbe modificato (blocco rimosso). Mostro diff (prima 200 righe):" | tee -a "$LOGFILE"
      diff -u "$f" "$out_tmp" | sed -n '1,200p' | tee -a "$LOGFILE"
      modified_count=$((modified_count+1))
      rm -f "$out_tmp"
      continue
    fi

    # apply: backup e mv
    cp --preserve=mode,timestamps "$f" "$f.bak"
    mv "$out_tmp" "$f"
    echo "  -> APPLY: aggiornato. Backup creato: $f.bak" | tee -a "$LOGFILE"
    modified_count=$((modified_count+1))
  else
    rc=$?
    if [ "$rc" -eq 1 ]; then
      echo "  -> Perl: nessuna modifica fatta (exit 1). Probabilmente non c'era il blocco corrispondente." | tee -a "$LOGFILE"
    else
      echo "  -> Perl terminato con codice $rc. Controlla $LOGFILE per errori di Perl." | tee -a "$LOGFILE"
      tail -n 100 "$LOGFILE" | sed -n '1,200p' | tee -a "$LOGFILE"
    fi
    rm -f "$out_tmp"
  fi
done

echo "[$(date --iso-8601=seconds)] Controllati: $checked_count. Modificati: $modified_count." | tee -a "$LOGFILE"
rm -rf "$TMPDIR"
echo "Fine." | tee -a "$LOGFILE"
exit 0