#!/usr/bin/env bash # STEP051 - Porting Presenze 215.6 # # Audit esatto del costruttore JSON usato dalla stampa Silvelox. # # Acquisisce e analizza: # - ax_print_manager/ctrl/helper.php; # - funzione makeTables(); # - scrittura dataReportTable.json; # - costruzione di time_day, cauys_day e totali; # - query a ax_new_time_day, ax_new_time, ax_new_time_causali; # - eventuali copie alternative locali dello stesso helper. # # Modalita': AUDIT ONLY. # Nessuna modifica a file, database o servizi. # # Server atteso: 215.6 / ax-accessi set -Eeuo pipefail umask 077 STEP_NAME="STEP051_2156_SILVELOX_PRINT_JSON_BUILDER_EXACT_FLOW_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_ROOT="${PRINT_ROOT:-$TARGET_ROOT/components/templates/custom_templates/ax_attendance/ax_print_manager}" HELPER="${HELPER:-$PRINT_ROOT/ctrl/helper.php}" CONTROLLER="${CONTROLLER:-$PRINT_ROOT/ctrl/controllerCtrl.php}" APP_JS="${APP_JS:-$PRINT_ROOT/app/appCtrl.js}" JSON_FILE="${JSON_FILE:-$TARGET_ROOT/json_data/dataReportTable.json}" 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" MATCHES="$WORKDIR/exact_matches.txt" MAKE_TABLES="$WORKDIR/makeTables_function.txt" DEPENDENCIES="$WORKDIR/makeTables_dependencies.txt" JSON_SCHEMA="$WORKDIR/current_json_schema.txt" COPY_LIST="$WORKDIR/helper_copies.txt" COPY_DIFF="$WORKDIR/helper_copy_diffs.txt" FINDINGS="$WORKDIR/automatic_findings.txt" EXTRACTOR="$WORKDIR/extract_function.php" JSON_ANALYZER="$WORKDIR/analyze_json.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 "$HELPER" "$CONTROLLER" "$APP_JS" "$JSON_FILE"; 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 } mkdir -p "$SOURCE_DIR" for file in \ "$INVENTORY" "$MATCHES" "$MAKE_TABLES" \ "$DEPENDENCIES" "$JSON_SCHEMA" "$COPY_LIST" \ "$COPY_DIFF" "$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 "PRINT MANAGER: $PRINT_ROOT" echo "HELPER REALE: $HELPER" echo "JSON REALE: $JSON_FILE" echo "MODALITA': AUDIT ONLY" echo "NESSUNA MODIFICA ESEGUITA" } > "$REPORT" progress "[1/6] Verifica file reali e acquisizione sorgenti" { printf 'size\tmtime\tmode\towner\tsha256\tpath\n' for file in "$HELPER" "$CONTROLLER" "$APP_JS" "$JSON_FILE"; 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" done } > "$INVENTORY" "$PHP_BIN" -l "$HELPER" >> "$REPORT" 2>&1 "$PHP_BIN" -l "$CONTROLLER" >> "$REPORT" 2>&1 grep -Fq "include_once 'helper.php';" "$CONTROLLER" || { echo "ERRORE: controllerCtrl.php non include helper.php nel formato atteso." >&2 exit 13 } cp -a -- "$HELPER" "$SOURCE_DIR/helper.php" cp -a -- "$CONTROLLER" "$SOURCE_DIR/controllerCtrl.php" cp -a -- "$APP_JS" "$SOURCE_DIR/appCtrl.js" cp -a -- "$JSON_FILE" "$SOURCE_DIR/dataReportTable.json" cat "$INVENTORY" >> "$REPORT" progress "[2/6] Estrazione esatta di makeTables()" cat > "$EXTRACTOR" <<'PHP' "$MAKE_TABLES" 2> "$WORKDIR/extract_error.txt"; then : else rc=$? cat "$WORKDIR/extract_error.txt" >&2 exit "$rc" fi [[ -s "$MAKE_TABLES" ]] || { echo "ERRORE: funzione makeTables estratta vuota." >&2 exit 14 } { echo echo "===== FUNZIONE makeTables() =====" nl -ba "$MAKE_TABLES" } >> "$REPORT" progress "[3/6] Riferimenti esatti a tabelle, JSON e dataset" grep -nEi \ 'makeTables|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([^_]|$)|time_day|cauys_day|generaldata|ordinarie|assenze|straordinarie|maggiorazioni|overturno|bancaore' \ "$HELPER" \ > "$MATCHES" || true cat "$MATCHES" >> "$REPORT" # Estrae i nomi delle funzioni richiamate direttamente da makeTables(). grep -Eo '\$this->[A-Za-z_][A-Za-z0-9_]*[[:space:]]*\(' \ "$MAKE_TABLES" \ | sed -E 's/^\$this->//; s/[[:space:]]*\($//' \ | sort -u \ > "$WORKDIR/dependency_names.txt" || true while IFS= read -r function_name; do [[ -n "$function_name" ]] || continue echo echo "===== DIPENDENZA: $function_name =====" if "$PHP_BIN" "$EXTRACTOR" "$HELPER" "$function_name" \ > "$WORKDIR/dependency.tmp" 2>/dev/null; then nl -ba "$WORKDIR/dependency.tmp" else echo "Funzione non estraibile da helper.php" fi done < "$WORKDIR/dependency_names.txt" \ > "$DEPENDENCIES" cat "$DEPENDENCIES" >> "$REPORT" progress "[4/6] Analisi della struttura JSON realmente prodotta" cat > "$JSON_ANALYZER" <<'PHP' $unused) { if ((string) $key !== (string) $expected) { return false; } $expected++; } return true; } function walk($value, $path, $depth) { if ($depth > 8 || !is_array($value)) { return; } $kind = isListArray($value) ? 'LIST' : 'OBJECT'; echo ( $path === '' ? '' : $path ) . "\t" . $kind . "\tcount=" . count($value) . "\n"; if ($kind === 'LIST' && count($value) > 0) { $first = reset($value); if (is_array($first)) { $keys = array_keys($first); sort($keys, SORT_NATURAL | SORT_FLAG_CASE); echo ( $path === '' ? '' : $path ) . "\tFIRST_ROW_KEYS\t" . implode(',', $keys) . "\n"; } } $visited = 0; foreach ($value as $key => $child) { if (is_array($child)) { $childPath = $path === '' ? (string) $key : $path . '.' . $key; walk($child, $childPath, $depth + 1); } $visited++; if ($visited >= 1000) { break; } } } walk($data, '', 0); PHP "$PHP_BIN" "$JSON_ANALYZER" "$JSON_FILE" \ > "$JSON_SCHEMA" cat "$JSON_SCHEMA" >> "$REPORT" progress "[5/6] Ricerca di copie locali dello stesso helper" find "$PRINT_ROOT/.." \ -maxdepth 5 \ -type f \ \( -name 'helper.php' -o -name 'helper*.php' \) \ -size -3M \ -print 2>/dev/null \ | sort -u \ > "$COPY_LIST" while IFS= read -r candidate; do [[ -f "$candidate" ]] || continue [[ "$candidate" != "$HELPER" ]] || continue if grep -Fq 'function makeTables' "$candidate"; then { echo echo "===== $candidate =====" stat -c '%s %y %a %U:%G %n' "$candidate" sha256sum "$candidate" diff -u "$candidate" "$HELPER" \ | head -n 4000 || true } >> "$COPY_DIFF" fi done < "$COPY_LIST" cat "$COPY_LIST" >> "$REPORT" cat "$COPY_DIFF" >> "$REPORT" progress "[6/6] Riepilogo e creazione ZIP" MAKE_TABLES_LINES="$(wc -l < "$MAKE_TABLES")" MATCH_COUNT="$(grep -c . "$MATCHES" 2>/dev/null || true)" DEPENDENCY_COUNT="$( grep -c . "$WORKDIR/dependency_names.txt" 2>/dev/null || true )" COPY_COUNT="$( grep -c '===== ' "$COPY_DIFF" 2>/dev/null || true )" WRITES_JSON="NO" USES_DAY="NO" USES_CAUS="NO" grep -Eq 'dataReportTable[.]json|file_put_contents' \ "$MAKE_TABLES" "$DEPENDENCIES" && WRITES_JSON="YES" || true grep -Fq 'ax_new_time_day' \ "$MAKE_TABLES" "$DEPENDENCIES" && USES_DAY="YES" || true grep -Fq 'ax_new_time_causali' \ "$MAKE_TABLES" "$DEPENDENCIES" && USES_CAUS="YES" || true { echo "Righe makeTables(): $MAKE_TABLES_LINES" echo "Riferimenti rilevanti: $MATCH_COUNT" echo "Dipendenze dirette estratte: $DEPENDENCY_COUNT" echo "Copie alternative con makeTables(): $COPY_COUNT" echo "Scrittura JSON individuata nel flusso: $WRITES_JSON" echo "Uso ax_new_time_day nel flusso: $USES_DAY" echo "Uso ax_new_time_causali nel flusso: $USES_CAUS" echo echo "ESITO: AUDIT COMPLETATO" echo "NESSUNA MODIFICA ESEGUITA" } > "$FINDINGS" cat "$FINDINGS" >> "$REPORT" ( cd "$WORKDIR" zip -q -9 -r "$OUTPUT_ZIP" \ "$(basename "$REPORT")" \ "$(basename "$INVENTORY")" \ "$(basename "$MATCHES")" \ "$(basename "$MAKE_TABLES")" \ "$(basename "$DEPENDENCIES")" \ "$(basename "$JSON_SCHEMA")" \ "$(basename "$COPY_LIST")" \ "$(basename "$COPY_DIFF")" \ "$(basename "$FINDINGS")" \ source ) zip -T "$OUTPUT_ZIP" >/dev/null echo "STEP051 COMPLETATO" echo "ZIP: $OUTPUT_ZIP"