#!/usr/bin/env bash # STEP052 - Porting Presenze 215.6 # # Audit del controller realmente chiamato dalla stampa Silvelox. # # appCtrl.js di ax_print_manager imposta: # var absname = 'ax_stampe'; # # Quindi le chiamate makeTables/setPrintStatus/getUsersList vanno a: # ax_attendance/ax_stampe/ctrl/controllerCtrl.php # # Modalita': AUDIT ONLY. # Nessuna modifica a file, database o servizi. # # Server atteso: 215.6 / ax-accessi set -Eeuo pipefail umask 077 STEP_NAME="STEP052_2156_SILVELOX_AX_STAMPE_REAL_DATA_BUILDER_AUDIT_ONLY_VERIFIED_20260731" EXPECTED_HOST="${EXPECTED_HOST:-ax-accessi}" EXPECTED_IP_FRAGMENT="${EXPECTED_IP_FRAGMENT:-192.168.215.6}" TARGET_ROOT="${TARGET_ROOT:-/var/www/html/presenze.silvelox}" PRINT_MANAGER_ROOT="${PRINT_MANAGER_ROOT:-$TARGET_ROOT/components/templates/custom_templates/ax_attendance/ax_print_manager}" REAL_ROOT="${REAL_ROOT:-$TARGET_ROOT/components/templates/custom_templates/ax_attendance/ax_stampe}" PRINT_APP="${PRINT_APP:-$PRINT_MANAGER_ROOT/app/appCtrl.js}" REAL_CONTROLLER="${REAL_CONTROLLER:-$REAL_ROOT/ctrl/controllerCtrl.php}" REAL_HELPER="${REAL_HELPER:-$REAL_ROOT/ctrl/helper.php}" ALLOW_TEST="${ALLOW_TEST:-0}" STAMP="$(date +%Y%m%d_%H%M%S)" OUTPUT_ZIP="$PWD/${STEP_NAME}_${STAMP}.zip" WORKDIR="$(mktemp -d "$PWD/.${STEP_NAME}.XXXXXX")" REPORT="$WORKDIR/${STEP_NAME}_REPORT.txt" SOURCE_DIR="$WORKDIR/source" INVENTORY="$WORKDIR/source_inventory.tsv" PHP_SYMBOLS="$WORKDIR/php_classes_functions.tsv" RELEVANT_MATCHES="$WORKDIR/relevant_matches.tsv" SOURCE_CONTEXT="$WORKDIR/relevant_source_context.txt" CALL_FLOW="$WORKDIR/javascript_call_flow.txt" INCLUDES="$WORKDIR/php_includes.txt" FINDINGS="$WORKDIR/automatic_findings.txt" PHP_ANALYZER="$WORKDIR/analyze_php.php" CONTEXT_EXTRACTOR="$WORKDIR/extract_context.php" cleanup() { rm -rf -- "$WORKDIR" } on_error() { local rc=$? local line="${1:-?}" trap - ERR printf 'ERRORE linea %s, codice %s\n' "$line" "$rc" >&2 exit "$rc" } trap cleanup EXIT INT TERM trap 'on_error "$LINENO"' ERR progress() { printf '%s\n' "$1" printf '\n[%s] %s\n' "$(date '+%H:%M:%S')" "$1" >> "$REPORT" } HOST_NOW="$(hostname 2>/dev/null || true)" IPS_NOW="$(hostname -I 2>/dev/null || true)" if [[ "$ALLOW_TEST" != "1" ]]; then if [[ "$HOST_NOW" != "$EXPECTED_HOST" && "$IPS_NOW" != *"$EXPECTED_IP_FRAGMENT"* ]]; then echo "ERRORE: server errato; atteso 215.6 / ax-accessi." >&2 exit 10 fi fi for required in "$PRINT_APP" "$REAL_CONTROLLER"; do [[ -f "$required" ]] || { echo "ERRORE: file richiesto non trovato: $required" >&2 exit 11 } done PHP_BIN="$(command -v php5.6 || command -v php || true)" [[ -n "$PHP_BIN" ]] || { echo "ERRORE: PHP CLI non disponibile." >&2 exit 12 } grep -Fq "var absname = 'ax_stampe';" "$PRINT_APP" || { echo "ERRORE: appCtrl.js non contiene absname='ax_stampe' nel formato verificato." >&2 exit 13 } mkdir -p "$SOURCE_DIR" for file in \ "$INVENTORY" "$PHP_SYMBOLS" "$RELEVANT_MATCHES" \ "$SOURCE_CONTEXT" "$CALL_FLOW" "$INCLUDES" "$FINDINGS"; do : > "$file" done { echo "$STEP_NAME" echo "DATA: $(date --iso-8601=seconds 2>/dev/null || date)" echo "SERVER: $HOST_NOW" echo "IP: $IPS_NOW" echo "PORTALE: $TARGET_ROOT" echo "APP STAMPA: $PRINT_APP" echo "ROOT REALE: $REAL_ROOT" echo "CONTROLLER REALE: $REAL_CONTROLLER" echo "MODALITA': AUDIT ONLY" echo "NESSUNA MODIFICA ESEGUITA" } > "$REPORT" progress "[1/6] Verifica del routing reale ax_print_manager -> ax_stampe" { echo "===== APP CTRL: ROUTING REALE =====" grep -nE \ "var absname|customTemplates.*absname|makeTables|setPrintStatus|getUsersList|dataReportTable" \ "$PRINT_APP" || true } > "$CALL_FLOW" cat "$CALL_FLOW" >> "$REPORT" progress "[2/6] Inventario e acquisizione dei sorgenti ax_stampe" declare -a SOURCE_FILES=("$PRINT_APP" "$REAL_CONTROLLER") if [[ -f "$REAL_HELPER" ]]; then SOURCE_FILES+=("$REAL_HELPER") fi while IFS= read -r file; do [[ -f "$file" ]] || continue found=0 for existing in "${SOURCE_FILES[@]}"; do if [[ "$existing" == "$file" ]]; then found=1 break fi done [[ "$found" -eq 1 ]] || SOURCE_FILES+=("$file") done < <( find "$REAL_ROOT" -maxdepth 4 -type f -size -3M \ \( -iname '*.php' -o -iname '*.js' -o -iname '*.html' \ -o -iname '*.tpl' -o -iname '*.json' \) \ -print 2>/dev/null | sort ) { printf 'size\tmtime\tmode\towner\tsha256\tpath\n' for file in "${SOURCE_FILES[@]}"; do printf '%s\t%s\t%s\t%s\t%s\t%s\n' \ "$(stat -c '%s' "$file")" \ "$(stat -c '%y' "$file")" \ "$(stat -c '%a' "$file")" \ "$(stat -c '%U:%G' "$file")" \ "$(sha256sum "$file" | awk '{print $1}')" \ "$file" rel="${file#"$TARGET_ROOT"/}" if [[ "$rel" == "$file" ]]; then rel="external/$(basename "$file")" fi mkdir -p "$SOURCE_DIR/$(dirname "$rel")" cp -a -- "$file" "$SOURCE_DIR/$rel" done } > "$INVENTORY" cat "$INVENTORY" >> "$REPORT" progress "[3/6] Lint PHP, classi, metodi e include reali" cat > "$PHP_ANALYZER" <<'PHP' > "$REPORT" 2>&1 PHP_FILES+=("$file") ;; esac done "$PHP_BIN" "$PHP_ANALYZER" "${PHP_FILES[@]}" > "$PHP_SYMBOLS" for file in "${PHP_FILES[@]}"; do grep -nE \ 'include(_once)?[[:space:]]|require(_once)?[[:space:]]' \ "$file" 2>/dev/null \ | sed "s#^#$file:#" || true done > "$INCLUDES" { echo echo "===== CLASSI E FUNZIONI =====" cat "$PHP_SYMBOLS" echo echo "===== INCLUDE E REQUIRE =====" cat "$INCLUDES" } >> "$REPORT" progress "[4/6] Ricerca del flusso ORD/ABSE e costruzione JSON" PATTERN='makeTables|setPrintStatus|getUsersList|dataReportTable[.]json|json_data|file_put_contents|json_encode|ax_new_time_day|ax_new_time_causali_month|ax_new_time_causali|ax_new_time([^_A-Za-z0-9]|$)|time_day|cauys_day|generaldata|ordinarie|assenze|straordinarie|maggiorazioni|overturno|bancaore|causType|causTime' for file in "${SOURCE_FILES[@]}"; do case "$file" in *.php|*.js) grep -nEi "$PATTERN" "$file" 2>/dev/null \ | while IFS=: read -r line text; do printf '%s\t%s\t%s\n' "$file" "$line" "$text" done || true ;; esac done > "$RELEVANT_MATCHES" cat > "$CONTEXT_EXTRACTOR" <<'PHP' $previous + 1) { echo "\n===== " . $file . " da riga " . $number . " =====\n"; } printf( "%6d %s", $number, $lines[$number - 1] ); $previous = $number; } PHP for file in "${SOURCE_FILES[@]}"; do case "$file" in *.php|*.js) "$PHP_BIN" "$CONTEXT_EXTRACTOR" \ "$file" \ "$RELEVANT_MATCHES" \ >> "$SOURCE_CONTEXT" ;; esac done { echo echo "===== MATCH RILEVANTI =====" cat "$RELEVANT_MATCHES" echo echo "===== CONTESTO SORGENTE =====" cat "$SOURCE_CONTEXT" } >> "$REPORT" progress "[5/6] Verifica automatica dei metodi realmente richiesti" MAKE_TABLES_COUNT="$( awk -F '\t' '$2=="FUNCTION" && $4=="makeTables"{count++} END{print count+0}' \ "$PHP_SYMBOLS" )" SET_PRINT_COUNT="$( awk -F '\t' '$2=="FUNCTION" && $4=="setPrintStatus"{count++} END{print count+0}' \ "$PHP_SYMBOLS" )" GET_USERS_COUNT="$( awk -F '\t' '$2=="FUNCTION" && $4=="getUsersList"{count++} END{print count+0}' \ "$PHP_SYMBOLS" )" TIME_DAY_MATCHES="$( grep -Eic 'ax_new_time_day|time_day' \ "$RELEVANT_MATCHES" 2>/dev/null || true )" CAUS_MATCHES="$( grep -Eic 'ax_new_time_causali|cauys_day|causType|causTime' \ "$RELEVANT_MATCHES" 2>/dev/null || true )" JSON_MATCHES="$( grep -Eic 'dataReportTable[.]json|file_put_contents|json_encode' \ "$RELEVANT_MATCHES" 2>/dev/null || true )" { echo "Metodo makeTables trovato: $MAKE_TABLES_COUNT" echo "Metodo setPrintStatus trovato: $SET_PRINT_COUNT" echo "Metodo getUsersList trovato: $GET_USERS_COUNT" echo "Riferimenti time_day/ax_new_time_day: $TIME_DAY_MATCHES" echo "Riferimenti causali: $CAUS_MATCHES" echo "Riferimenti scrittura JSON: $JSON_MATCHES" echo echo "CONTROLLER REALE ANALIZZATO: $REAL_CONTROLLER" echo "ESITO: AUDIT COMPLETATO" echo "NESSUNA MODIFICA ESEGUITA" } > "$FINDINGS" cat "$FINDINGS" >> "$REPORT" progress "[6/6] Creazione ZIP" ( cd "$WORKDIR" zip -q -9 -r "$OUTPUT_ZIP" \ "$(basename "$REPORT")" \ "$(basename "$INVENTORY")" \ "$(basename "$PHP_SYMBOLS")" \ "$(basename "$RELEVANT_MATCHES")" \ "$(basename "$SOURCE_CONTEXT")" \ "$(basename "$CALL_FLOW")" \ "$(basename "$INCLUDES")" \ "$(basename "$FINDINGS")" \ source ) zip -T "$OUTPUT_ZIP" >/dev/null echo "STEP052 COMPLETATO" echo "ZIP: $OUTPUT_ZIP"