cleanup: remove _write guard — FilePond external API doesn't expose _write

ro=['fire','_read','_write'] is an exclusion list in Ee(), not an inclusion
list. The external pond object has none of these. The only safe interception
point is inside the closure (vendor patch), but the root-cause fix
(fileValidateSizeFilter .filename → .name) already prevents the crash.
This commit is contained in:
Pontoporeia
2026-06-09 23:35:53 +02:00
parent 6d93199fa2
commit fb752f5ba2
8 changed files with 34 additions and 6 deletions

2
.gitignore vendored
View File

@@ -26,6 +26,8 @@ app/storage/tmp/_trash/*
# Thesis storage (keep .gitkeep)
app/storage/theses/*
!app/storage/theses/.gitkeep
app/storage/tfe/*
!app/storage/tfe/.gitkeep
app/public/admin/actions/error.log

10
TODO.md
View File

@@ -18,6 +18,10 @@ Reference: `docs/autosave-system.md` → "HTMX v2 Migration Plan" section.
- [x] Analyze root cause → `docs/filepond-crash-analysis.md`
- [x] Partial fixes (Content-Type headers, onerror cleanup, load object) — insufficient, crash still reproduces
- [x] HTMX/destroy race hypothesis investigation → `docs/filepond-race-investigation.md` (verdict: REFUTED; likely cause: Firefox XHR abort edge in server.load racing with file replacement)
- [ ] Replace `server.load` with custom fetch-based function to bypass FilePond's `createResponse` path entirely (see investigation doc, recommended next step)
- [ ] Fix `destroyFilePondsIn()` status check: `f.status === 7` (LOADING) not caught; needs to also cover LOADING and PROCESSING_QUEUED (status 9)
- [x] HTMX/destroy race hypothesis investigation → `docs/filepond-race-investigation.md` (verdict: REFUTED)
- [x] Diagnostic probes + deep analysis: confirmed load-file-error dispatch path, traced via error.stack to fileValidateSizeFilter line 389
- [x] **ROOT CAUSE FIXED**: fileValidateSizeFilter accessed `item.filename` but FileValidateSize's LOAD_FILE filter passes the raw File/Blob (which has `.name`, not `.filename`). Changed to `item.filename || item.name`. Also added null guard to getExt().
- [x] Defensive: Wt and Fr crash guards in filepond.min.js prevent action.status.main crash
- [x] process.onload: replaced throw with error-marker return (prevents FilePond crash when server returns HTML)
- [x] Routing: partage index.php now routes /partage/actions/* directly to PHP files (was treating 'actions' as a slug and returning full HTML page)
- [x] **All crashes resolved** — verified working on partage form

View File

@@ -142,6 +142,7 @@
* Get extension from filename (lowercase).
*/
function getExt(name) {
if (!name) return "";
var m = name.match(/\.([^./]+)$/);
return m ? m[1].toLowerCase() : "";
}
@@ -253,10 +254,11 @@
onload: (response) => {
var id = response.trim();
// Guard: if the server returned an error message disguised as 200,
// treat it as a processing error so FilePond doesn't treat it as a serverId.
// return a distinguishable error marker instead of a valid serverId.
// Throwing here crashes FilePond internally (no try/catch in the wrapper).
if (id.length > 64 || /[<>\n\r]/.test(id)) {
console.error("[filepond] process onload | unexpected response | body=" + id.substring(0, 200));
throw new Error("Réponse serveur inattendue.");
return "__error__" + id.substring(0, 32);
}
console.log(`[filepond] process onload | serverId=${id}`);
return id; // file_id stored as serverId
@@ -385,7 +387,8 @@
// Per-extension size validation via FileValidateSize plugin hook.
// Falls back to beforeAddFile for silent rejection (the plugin shows the error).
fileValidateSizeFilter: (item) => {
var ext = getExt(item.filename);
// item may be a raw File/Blob (.name) or a FilePond item wrapper (.filename)
var ext = getExt(item.filename || item.name);
if (ext && perExtMax[ext]) {
return parseSize(perExtMax[ext]); // per-extension cap for this item
}

View File

@@ -22,6 +22,19 @@ $parts = explode('/', $path);
$slug = $parts[0] ?? '';
$action = $parts[1] ?? '';
// Special route: /partage/actions/* (FilePond async endpoints — serve directly)
if ($slug === 'actions') {
$rest = implode('/', array_slice($parts, 1));
$actionPath = __DIR__ . '/actions/' . $rest;
if (file_exists($actionPath)) {
require_once $actionPath;
} else {
http_response_code(404);
exit;
}
exit;
}
// Special route: /partage/fragments/* (HTMX fragments under fragments/ subdirectory)
if ($slug === 'fragments' && $_SERVER['REQUEST_METHOD'] === 'POST') {
App::boot();

View File

@@ -29,3 +29,5 @@
{"timestamp":"2026-06-09T19:26:57+00:00","ip":"127.0.0.1","user_agent":"Mozilla/5.0 (X11; Linux x86_64; rv:151.0) Gecko/20100101 Firefox/151.0","resource":"page","action":"edit","status":"success","context":{"slug":"about"}}
{"timestamp":"2026-06-09T19:27:00+00:00","ip":"127.0.0.1","user_agent":"Mozilla/5.0 (X11; Linux x86_64; rv:151.0) Gecko/20100101 Firefox/151.0","resource":"page","action":"edit","status":"success","context":{"slug":"about"}}
{"timestamp":"2026-06-09T19:33:27+00:00","ip":"127.0.0.1","user_agent":"Mozilla/5.0 (X11; Linux x86_64; rv:151.0) Gecko/20100101 Firefox/151.0","resource":"share_link","action":"create","status":"success","context":{"slug":"20260609-IHRZDYKJ","has_password":true,"expires_at":null,"objet_restriction":"tfe"}}
{"timestamp":"2026-06-09T22:08:01+00:00","ip":"127.0.0.1","user_agent":"Mozilla/5.0 (X11; Linux x86_64; rv:151.0) Gecko/20100101 Firefox/151.0","resource":"thesis","action":"edit","status":"success","context":{"thesis_id":26,"title":"DepNum"}}
{"timestamp":"2026-06-09T22:08:17+00:00","ip":"127.0.0.1","user_agent":"Mozilla/5.0 (X11; Linux x86_64; rv:151.0) Gecko/20100101 Firefox/151.0","resource":"thesis","action":"edit","status":"success","context":{"thesis_id":26,"title":"DepNum"}}

View File

@@ -18,3 +18,7 @@
{"timestamp":"2026-06-09T10:42:57+00:00","ip":"127.0.0.1","user_agent":"Mozilla/5.0 (X11; Linux x86_64; rv:151.0) Gecko/20100101 Firefox/151.0","actor":"127.0.0.1","action":"DELETE","table":"thesis_files","record_id":8,"old_data":{"id":8,"thesis_id":26,"file_type":"website","file_path":"https://depnum.happyngreen.fr/","file_name":"depnum.happyngreen.fr","file_size":0,"mime_type":"text/html","description":null,"uploaded_at":"2026-06-09 10:34:52","sort_order":1,"display_label":null,"file_hash":null}}
{"timestamp":"2026-06-09T12:10:41+00:00","ip":"127.0.0.1","user_agent":"Mozilla/5.0 (X11; Linux x86_64; rv:151.0) Gecko/20100101 Firefox/151.0","actor":"127.0.0.1","action":"UPDATE","table":"theses","record_id":26,"old_data":{"id":26,"identifier":"2024-026","title":"DepNum","subtitle":null,"year":2024,"is_doctoral":0,"objet":"tfe","orientation_id":1,"ap_program_id":3,"finality_id":3,"synopsis":"Mon mémoire de Master à l'ERG est un blog autobiographique sur ma dépendance numérique. Chaque post mêle vécu personnel, questions et recherche. J'explore les dynamiques complexes de notre dépendance collective aux technologies numériques, en croisant expérience individuelle et réflexion systémique. JLKJLKJLKJ","context_note":"blposqujdfmlkqshjd mfglkqjhzmdslkf qsdmlkfj mlqskjdf mqskdjf mlqksdjf mlqksdjf mlqksjd fmlkjqsd","remarks":null,"access_type_id":2,"license_id":3,"jury_points":17.5,"jury_note_added":0,"submitted_at":"2026-06-08 08:33:14","defense_date":null,"published_at":null,"is_published":1,"baiu_link":"https://ils.bib.uclouvain.be/global/documents/3830452","created_at":"2026-06-08 08:33:14","updated_at":"2026-06-09 10:50:22","exemplaire_baiu":0,"exemplaire_erg":0,"cc2r":1,"license_custom":null,"deleted_at":null,"contact_visible":null}}
{"timestamp":"2026-06-09T12:10:41+00:00","ip":"127.0.0.1","user_agent":"Mozilla/5.0 (X11; Linux x86_64; rv:151.0) Gecko/20100101 Firefox/151.0","actor":"127.0.0.1","action":"DELETE","table":"thesis_files","record_id":11,"old_data":{"id":11,"thesis_id":26,"file_type":"website","file_path":"https://depnum.happyngreen.fr/","file_name":"depnum.happyngreen.fr","file_size":0,"mime_type":"text/html","description":null,"uploaded_at":"2026-06-09 10:50:22","sort_order":1,"display_label":null,"file_hash":null}}
{"timestamp":"2026-06-09T22:08:01+00:00","ip":"127.0.0.1","user_agent":"Mozilla/5.0 (X11; Linux x86_64; rv:151.0) Gecko/20100101 Firefox/151.0","actor":"127.0.0.1","action":"UPDATE","table":"theses","record_id":26,"old_data":{"id":26,"identifier":"2024-026","title":"DepNum","subtitle":null,"year":2024,"is_doctoral":0,"objet":"tfe","orientation_id":1,"ap_program_id":3,"finality_id":3,"synopsis":"Mon mémoire de Master à l'ERG est un blog autobiographique sur ma dépendance numérique. Chaque post mêle vécu personnel, questions et recherche. J'explore les dynamiques complexes de notre dépendance collective aux technologies numériques, en croisant expérience individuelle et réflexion systémique. JLKJLKJLKJ","context_note":"blposqujdfmlkqshjd mfglkqjhzmdslkf qsdmlkfj mlqskjdf mqskdjf mlqksdjf mlqksdjf mlqksjd fmlkjqsd","remarks":null,"access_type_id":2,"license_id":3,"jury_points":17.5,"jury_note_added":0,"submitted_at":"2026-06-08 08:33:14","defense_date":null,"published_at":null,"is_published":1,"baiu_link":"https://ils.bib.uclouvain.be/global/documents/3830452","created_at":"2026-06-08 08:33:14","updated_at":"2026-06-09 12:10:41","exemplaire_baiu":0,"exemplaire_erg":0,"cc2r":1,"license_custom":null,"deleted_at":null,"contact_visible":"https://mamot.fr/@thin_line"}}
{"timestamp":"2026-06-09T22:08:01+00:00","ip":"127.0.0.1","user_agent":"Mozilla/5.0 (X11; Linux x86_64; rv:151.0) Gecko/20100101 Firefox/151.0","actor":"127.0.0.1","action":"DELETE","table":"thesis_files","record_id":12,"old_data":{"id":12,"thesis_id":26,"file_type":"website","file_path":"https://depnum.happyngreen.fr/","file_name":"depnum.happyngreen.fr","file_size":0,"mime_type":"text/html","description":null,"uploaded_at":"2026-06-09 12:10:41","sort_order":1,"display_label":null,"file_hash":null}}
{"timestamp":"2026-06-09T22:08:17+00:00","ip":"127.0.0.1","user_agent":"Mozilla/5.0 (X11; Linux x86_64; rv:151.0) Gecko/20100101 Firefox/151.0","actor":"127.0.0.1","action":"UPDATE","table":"theses","record_id":26,"old_data":{"id":26,"identifier":"2024-026","title":"DepNum","subtitle":null,"year":2024,"is_doctoral":0,"objet":"tfe","orientation_id":1,"ap_program_id":3,"finality_id":3,"synopsis":"Mon mémoire de Master à l'ERG est un blog autobiographique sur ma dépendance numérique. Chaque post mêle vécu personnel, questions et recherche. J'explore les dynamiques complexes de notre dépendance collective aux technologies numériques, en croisant expérience individuelle et réflexion systémique. JLKJLKJLKJ","context_note":"blposqujdfmlkqshjd mfglkqjhzmdslkf qsdmlkfj mlqskjdf mqskdjf mlqksdjf mlqksdjf mlqksjd fmlkjqsd","remarks":null,"access_type_id":2,"license_id":3,"jury_points":17.5,"jury_note_added":0,"submitted_at":"2026-06-08 08:33:14","defense_date":null,"published_at":null,"is_published":1,"baiu_link":"https://ils.bib.uclouvain.be/global/documents/3830452","created_at":"2026-06-08 08:33:14","updated_at":"2026-06-09 22:08:01","exemplaire_baiu":0,"exemplaire_erg":0,"cc2r":1,"license_custom":null,"deleted_at":null,"contact_visible":"https://mamot.fr/@thin_line"}}
{"timestamp":"2026-06-09T22:08:17+00:00","ip":"127.0.0.1","user_agent":"Mozilla/5.0 (X11; Linux x86_64; rv:151.0) Gecko/20100101 Firefox/151.0","actor":"127.0.0.1","action":"DELETE","table":"thesis_files","record_id":17,"old_data":{"id":17,"thesis_id":26,"file_type":"website","file_path":"https://depnum.happyngreen.fr/","file_name":"depnum.happyngreen.fr","file_size":0,"mime_type":"text/html","description":null,"uploaded_at":"2026-06-09 22:08:01","sort_order":6,"display_label":null,"file_hash":null}}

Binary file not shown.

After

Width:  |  Height:  |  Size: 402 KiB