Attachment Integrity Check (CLI) 1.0.0

XF 2.3 Attachment Integrity Check (CLI) 1.0.0

Add-on xenforo 2

Ressources et modules complémentaires pour XenForo 2

Styles xenforo 2

Styles / Thèmes et apparence pour xenforo 2

Templates xenforo 2

Codes pour modifier les templates sur xenforo 2

Section Premium

Add-on et Styles pour membre Premium
  • ⚠️ Section Premium. Réserver aux Membres Premium ⚠️
Attachment Integrity Check (CLI) 1.0.0

XF 2.3 Attachment Integrity Check (CLI) 1.0.0

Catégorie Catégorie Add-Ons
Titre du sujet Titre du sujet Attachment Integrity Check (CLI) 1.0.0
Auteur de la discussion Auteur de la discussion laurent68
Date de début Date de début
Réponses Réponses 0
Affichages Affichages 4
Réaction Réaction 0
Dernier message par Dernier message par laurent68

laurent68

Fondateur

Staff
fondateur
Réputation: 100%
Discussions
5 048
Messages
13 203
Solutions
85
J'aime
8 087
Points
198
Additional requirements :
- SSH / command-line access. The script refuses to run over HTTP.
- PHP 8.0+ (whatever your XenForo installation already requires).
- The file_key column on xf_attachment_data. The script verifies this at startup and
aborts if it is missing rather than guessing at paths.
- Roughly 100 MB RAM per 50,000 attachments when using --index.
- Works with local storage and with remote/off-host Flysystem adapters (S3, R2, etc).
- No add-on installation. Standalone script placed in the forum root.

Attachment Integrity Check

When an attachment's file goes missing but its database row survives, XenForo still renders the attachment link. Clicking it throws a 500 and fills your error log with:

Code:
League\Flysystem\FileNotFoundException: File not found at path: attachments/236/236888-0dcb....data
src/XF/Pub/View/Attachment/View.php:27

There is no built-in way to find these in bulk, and no way to tell a genuinely lost attachment from one whose file is still sitting in storage under a stale key.

This happens after a database restore, a storage migration, a failed S3/R2 sync, a partially restored backup, or just years of accumulated failed deletes.

What it does

Every attachment is classified as one of three things:
  • OK — the file is present exactly where XenForo expects it.
  • RELINK — the file is missing from its expected path, but a file for this data_id exists under a different file_key and its md5 matches the stored file_hash. The upload is intact; only the database pointer is stale. Repairable with no data loss.
  • MISSING — no file at all, or a candidate exists whose md5 does not match, meaning the id was reused by a later upload and that file belongs to somebody else. Nothing recoverable.
That md5 check matters. Relinking on filename alone would staple a stranger's screenshot into somebody's post.

Three modes
  • Scan — walks the database asking "where is the file?" and writes a CSV. Read-only.
  • Orphans — the inverse. Walks storage asking "which row owns this file?", finding files stranded by a database rollback that a normal scan cannot see, because those rows no longer exist. Read-only.
  • Apply — consumes the scan CSV, re-verifies every row against storage again, then repairs. Deletes only if you explicitly ask.
Usage

Drop the script in your forum root, next to index.php. Then:
Code:
php xf-missing-attachments.php --index --report=scan.csv

That is read-only and changes nothing. --index does a single recursive listing of your storage and answers every lookup from memory — on remote storage that turns ~200,000 network round-trips into ~200 list calls.

Review the CSV. Then back up:
Code:
mysqldump YOUR_DB xf_attachment xf_attachment_data > attach-backup.sql

Repair without deleting anything:
Code:
php xf-missing-attachments.php --apply=scan.csv --index

Repair and purge the dead rows:
Code:
php xf-missing-attachments.php --apply=scan.csv --index --delete

Safety

This tool can delete database rows, so it is built on the assumption that it might be wrong.
  • Scanning never writes. Deleting takes a separate run, a separate flag, and a CSV you have had the chance to read.
  • Every row is re-verified against live storage immediately before it is touched. A stale or hand-edited CSV cannot cause damage.
  • Empty index aborts. If storage is unreachable or the prefix is wrong, every row would look MISSING. That is fatal and --force does not override it.
  • Ratio guard. A plan that would delete more than 20% of all attachments is refused — that pattern means a storage fault, not data loss.
  • Count guard. --max-delete (default 2000) blocks unexpectedly large plans.
  • Deletes go through the entity layer, so attach_count is maintained by XenForo's own attachment handler for every content type, including those from other add-ons.
  • Unknown arguments are rejected rather than silently ignored.
  • Reports cannot be written to a web-accessible path — they list every attachment on your forum. They go to internal_data/attachment-audit/.
  • Refuses to run over HTTP.
What it never touches:
posts and threads are not modified. An [ATTACH] tag whose attachment no longer exists renders as nothing, so the post keeps its text and simply loses a broken image. No thread is ever deleted. Orphaned storage files are reported but never removed — deleting those would destroy the only remaining copy.

Important compatibility note

XenForo derives the stored path from xf_attachment_data.file_key, not file_hash. Both are 32-character hex strings, so confusing the two is easy — and the consequence is that every attachment gets classified MISSING. If you are writing your own tooling for this, that is the trap.

The script checks for the column at startup and aborts if absent rather than guessing.

Testing

Validated against a live forum with 201,465 attachments on XenForo 2.3 with remote off-host storage, plus a fixture suite covering relink, id-reuse rejection, attach_count maintenance, orphan detection, idempotency, and every guard listed above. A full 200k-row scan takes under two minutes.

Released under BSD 2-Clause. Fork it, extend it, ship it in your own tooling.

Télécharger V1.0.0 :
 
Contenu similaire Les plus vues Voir plus
Retour
Haut Bas