mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-06-25 16:19:19 +02:00
fix: repair form submission with queued files + add comprehensive debug logging
- Replace fetch(redirect:manual) with XMLHttpRequest in file-upload-queue.js. The previous fetch-based redirect detection was broken because opaque redirects hide the Location header. XHR's responseURL reliably exposes the final URL after server-side redirects. - Add console.log tracing at every decision point in submit interception: entry, hasFiles check, enctype check, double-submit guard, XHR status, redirect detection, error fallback. - Add error_log entry-point logging to all 16 admin action files plus the partage/index.php submission handler and password gate. Each logs: request method, content type/length, POST keys, file counts, and queue-specific file counts where applicable. - Add double-submit guard (_xamxamActiveSubmit) to prevent duplicate XHR sends when the native submit handler fires after interception.
This commit is contained in:
5
TODO.md
5
TODO.md
@@ -1,3 +1,8 @@
|
|||||||
# TODO
|
# TODO
|
||||||
|
|
||||||
- [x] Replace HTMX+PHP file upload queues with client-side JS
|
- [x] Replace HTMX+PHP file upload queues with client-side JS
|
||||||
|
- [x] Fix submit button on all forms — add JS/PHP debug logging
|
||||||
|
- [x] Fix file-upload-queue.js: redirect detection broken due to opaque redirect (switched from fetch to XHR for reliable responseURL)
|
||||||
|
- [x] Add `console.log` tracing on JS submit interception
|
||||||
|
- [x] Add `error_log` entry-point logging to all 16 PHP action files
|
||||||
|
- [x] Add double-submit guard (`_xamxamActiveSubmit`)
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ require_once __DIR__ . '/../../../src/AdminAuth.php';
|
|||||||
require_once __DIR__ . '/../../../src/ShareLink.php';
|
require_once __DIR__ . '/../../../src/ShareLink.php';
|
||||||
require_once __DIR__ . '/../../../src/AdminLogger.php';
|
require_once __DIR__ . '/../../../src/AdminLogger.php';
|
||||||
|
|
||||||
|
error_log('[acces-etudiante.php] ENTRY | method=' . $_SERVER['REQUEST_METHOD'] . ' | action=' . ($_POST['action'] ?? 'none') . ' | post_keys=' . implode(',', array_keys($_POST)));
|
||||||
|
|
||||||
App::adminGuard();
|
App::adminGuard();
|
||||||
|
|
||||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST'
|
if ($_SERVER['REQUEST_METHOD'] !== 'POST'
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
*/
|
*/
|
||||||
require_once __DIR__ . '/../../../bootstrap.php';
|
require_once __DIR__ . '/../../../bootstrap.php';
|
||||||
require_once __DIR__ . '/../../../src/AdminAuth.php';
|
require_once __DIR__ . '/../../../src/AdminAuth.php';
|
||||||
|
error_log('[access-request.php] ENTRY | method=' . $_SERVER['REQUEST_METHOD'] . ' | action=' . ($_POST['action'] ?? 'none') . ' | request_id=' . ($_POST['request_id'] ?? 0) . ' | post_keys=' . implode(',', array_keys($_POST)));
|
||||||
AdminAuth::requireLogin();
|
AdminAuth::requireLogin();
|
||||||
|
|
||||||
if (!isset($_POST['csrf_token'], $_SESSION['csrf_token'])
|
if (!isset($_POST['csrf_token'], $_SESSION['csrf_token'])
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ require_once __DIR__ . '/../../../bootstrap.php';
|
|||||||
require_once __DIR__ . '/../../../src/AdminAuth.php';
|
require_once __DIR__ . '/../../../src/AdminAuth.php';
|
||||||
require_once __DIR__ . '/../../../src/Database.php';
|
require_once __DIR__ . '/../../../src/Database.php';
|
||||||
|
|
||||||
|
error_log('[account.php] ENTRY | method=' . $_SERVER['REQUEST_METHOD'] . ' | action=' . ($_POST['action'] ?? 'change_password') . ' | post_keys=' . implode(',', array_keys($_POST)));
|
||||||
|
|
||||||
AdminAuth::requireLogin();
|
AdminAuth::requireLogin();
|
||||||
|
|
||||||
// ── CSRF ──────────────────────────────────────────────────────────────────────
|
// ── CSRF ──────────────────────────────────────────────────────────────────────
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
require_once __DIR__ . "/../../../bootstrap.php";
|
require_once __DIR__ . "/../../../bootstrap.php";
|
||||||
require_once __DIR__ . '/../../../src/AdminAuth.php';
|
require_once __DIR__ . '/../../../src/AdminAuth.php';
|
||||||
|
error_log('[apropos.php] ENTRY | method=' . $_SERVER['REQUEST_METHOD'] . ' | key=' . ($_POST['apropos_key'] ?? 'none') . ' | post_keys=' . implode(',', array_keys($_POST)));
|
||||||
AdminAuth::requireLogin();
|
AdminAuth::requireLogin();
|
||||||
|
|
||||||
// CSRF check
|
// CSRF check
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
require_once __DIR__ . '/../../../bootstrap.php';
|
require_once __DIR__ . '/../../../bootstrap.php';
|
||||||
require_once __DIR__ . '/../../../src/AdminAuth.php';
|
require_once __DIR__ . '/../../../src/AdminAuth.php';
|
||||||
|
error_log('[delete.php] ENTRY | method=' . $_SERVER['REQUEST_METHOD'] . ' | is_bulk=' . (!empty($_POST['bulk']) ? '1' : '0') . ' | post_keys=' . implode(',', array_keys($_POST)));
|
||||||
|
|
||||||
AdminAuth::requireLogin();
|
AdminAuth::requireLogin();
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
require_once __DIR__ . "/../../../bootstrap.php";
|
require_once __DIR__ . "/../../../bootstrap.php";
|
||||||
require_once __DIR__ . '/../../../src/AdminAuth.php';
|
require_once __DIR__ . '/../../../src/AdminAuth.php';
|
||||||
|
|
||||||
|
error_log('[edit.php] ENTRY | method=' . $_SERVER['REQUEST_METHOD'] . ' | content_type=' . ($_SERVER['CONTENT_TYPE'] ?? 'none') . ' | content_length=' . ($_SERVER['CONTENT_LENGTH'] ?? '0') . ' | post_keys=' . implode(',', array_keys($_POST)) . ' | files_count=' . count($_FILES) . ' | files_keys=' . implode(',', array_keys($_FILES)) . ' | queue_tfe=' . (isset($_FILES['queue_file']['name']['tfe']) ? count(array_filter($_FILES['queue_file']['name']['tfe'])) : 0));
|
||||||
|
|
||||||
// PHP-level auth guard (defence-in-depth behind nginx Basic Auth)
|
// PHP-level auth guard (defence-in-depth behind nginx Basic Auth)
|
||||||
AdminAuth::requireLogin();
|
AdminAuth::requireLogin();
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
require_once __DIR__ . '/../../../bootstrap.php';
|
require_once __DIR__ . '/../../../bootstrap.php';
|
||||||
require_once __DIR__ . '/../../../src/AdminAuth.php';
|
require_once __DIR__ . '/../../../src/AdminAuth.php';
|
||||||
|
error_log('[form-help.php] ENTRY | method=' . $_SERVER['REQUEST_METHOD'] . ' | key=' . ($_POST['form_help_key'] ?? 'none') . ' | post_keys=' . implode(',', array_keys($_POST)));
|
||||||
AdminAuth::requireLogin();
|
AdminAuth::requireLogin();
|
||||||
|
|
||||||
if (!isset($_POST['csrf_token'], $_SESSION['csrf_token'])
|
if (!isset($_POST['csrf_token'], $_SESSION['csrf_token'])
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
require_once __DIR__ . '/../../../bootstrap.php';
|
require_once __DIR__ . '/../../../bootstrap.php';
|
||||||
require_once __DIR__ . '/../../../src/AdminAuth.php';
|
require_once __DIR__ . '/../../../src/AdminAuth.php';
|
||||||
|
|
||||||
|
error_log('[formulaire.php] ENTRY | method=' . $_SERVER['REQUEST_METHOD'] . ' | content_type=' . ($_SERVER['CONTENT_TYPE'] ?? 'none') . ' | content_length=' . ($_SERVER['CONTENT_LENGTH'] ?? '0') . ' | post_keys=' . implode(',', array_keys($_POST)) . ' | files_count=' . count($_FILES) . ' | files_keys=' . implode(',', array_keys($_FILES)) . ' | queue_tfe=' . (isset($_FILES['queue_file']['name']['tfe']) ? count(array_filter($_FILES['queue_file']['name']['tfe'])) : 0));
|
||||||
|
|
||||||
// Only suppress display_errors in production (cli-server = dev mode).
|
// Only suppress display_errors in production (cli-server = dev mode).
|
||||||
if (php_sapi_name() !== 'cli-server') {
|
if (php_sapi_name() !== 'cli-server') {
|
||||||
ini_set('display_errors', 0);
|
ini_set('display_errors', 0);
|
||||||
@@ -23,7 +25,7 @@ if (!isset($_POST['csrf_token'], $_SESSION['csrf_token'])
|
|||||||
die('Erreur de sécurité : token invalide. Veuillez recharger le formulaire.');
|
die('Erreur de sécurité : token invalide. Veuillez recharger le formulaire.');
|
||||||
}
|
}
|
||||||
|
|
||||||
error_log('FILES array: ' . print_r($_FILES, true));
|
error_log('[formulaire.php] full FILES array: ' . print_r($_FILES, true));
|
||||||
|
|
||||||
require_once APP_ROOT . '/src/Controllers/ThesisCreateController.php';
|
require_once APP_ROOT . '/src/Controllers/ThesisCreateController.php';
|
||||||
require_once APP_ROOT . '/src/AppLogger.php';
|
require_once APP_ROOT . '/src/AppLogger.php';
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
require_once __DIR__ . '/../../../bootstrap.php';
|
require_once __DIR__ . '/../../../bootstrap.php';
|
||||||
require_once __DIR__ . '/../../../src/AdminAuth.php';
|
require_once __DIR__ . '/../../../src/AdminAuth.php';
|
||||||
|
error_log('[language.php] ENTRY | method=' . $_SERVER['REQUEST_METHOD'] . ' | action=' . ($_POST['action'] ?? 'none') . ' | post_keys=' . implode(',', array_keys($_POST)));
|
||||||
AdminAuth::requireLogin();
|
AdminAuth::requireLogin();
|
||||||
|
|
||||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST'
|
if ($_SERVER['REQUEST_METHOD'] !== 'POST'
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
require_once __DIR__ . '/../../../bootstrap.php';
|
require_once __DIR__ . '/../../../bootstrap.php';
|
||||||
require_once __DIR__ . '/../../../src/AdminAuth.php';
|
require_once __DIR__ . '/../../../src/AdminAuth.php';
|
||||||
|
error_log('[maintenance.php] ENTRY | method=' . $_SERVER['REQUEST_METHOD'] . ' | action=' . ($_POST['action'] ?? 'none') . ' | post_keys=' . implode(',', array_keys($_POST)));
|
||||||
AdminAuth::requireLogin();
|
AdminAuth::requireLogin();
|
||||||
|
|
||||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST'
|
if ($_SERVER['REQUEST_METHOD'] !== 'POST'
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
*/
|
*/
|
||||||
require_once __DIR__ . '/../../../bootstrap.php';
|
require_once __DIR__ . '/../../../bootstrap.php';
|
||||||
require_once __DIR__ . '/../../../src/AdminAuth.php';
|
require_once __DIR__ . '/../../../src/AdminAuth.php';
|
||||||
|
error_log('[page.php] ENTRY | method=' . $_SERVER['REQUEST_METHOD'] . ' | slug=' . ($_POST['slug'] ?? 'none') . ' | post_keys=' . implode(',', array_keys($_POST)));
|
||||||
AdminAuth::requireLogin();
|
AdminAuth::requireLogin();
|
||||||
|
|
||||||
if (!isset($_POST['csrf_token'], $_SESSION['csrf_token'])
|
if (!isset($_POST['csrf_token'], $_SESSION['csrf_token'])
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
require_once __DIR__ . '/../../../bootstrap.php';
|
require_once __DIR__ . '/../../../bootstrap.php';
|
||||||
require_once __DIR__ . '/../../../src/AdminAuth.php';
|
require_once __DIR__ . '/../../../src/AdminAuth.php';
|
||||||
|
error_log('[publish.php] ENTRY | method=' . $_SERVER['REQUEST_METHOD'] . ' | action=' . ($_POST['action'] ?? 'none') . ' | is_bulk=' . (!empty($_POST['bulk']) ? '1' : '0') . ' | post_keys=' . implode(',', array_keys($_POST)));
|
||||||
|
|
||||||
AdminAuth::requireLogin();
|
AdminAuth::requireLogin();
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
require_once __DIR__ . '/../../../bootstrap.php';
|
require_once __DIR__ . '/../../../bootstrap.php';
|
||||||
require_once __DIR__ . '/../../../src/AdminAuth.php';
|
require_once __DIR__ . '/../../../src/AdminAuth.php';
|
||||||
|
error_log('[settings.php] ENTRY | method=' . $_SERVER['REQUEST_METHOD'] . ' | section=' . ($_POST['section'] ?? 'none') . ' | post_keys=' . implode(',', array_keys($_POST)));
|
||||||
AdminAuth::requireLogin();
|
AdminAuth::requireLogin();
|
||||||
|
|
||||||
if (!isset($_POST['csrf_token'], $_SESSION['csrf_token'])
|
if (!isset($_POST['csrf_token'], $_SESSION['csrf_token'])
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
require_once __DIR__ . "/../../../bootstrap.php";
|
require_once __DIR__ . "/../../../bootstrap.php";
|
||||||
require_once __DIR__ . '/../../../src/AdminAuth.php';
|
require_once __DIR__ . '/../../../src/AdminAuth.php';
|
||||||
|
error_log('[smtp-test.php] ENTRY | method=' . $_SERVER['REQUEST_METHOD'] . ' | test_email=' . ($_POST['test_email'] ?? 'none') . ' | post_keys=' . implode(',', array_keys($_POST)));
|
||||||
AdminAuth::requireLogin();
|
AdminAuth::requireLogin();
|
||||||
|
|
||||||
require_once APP_ROOT . '/src/Database.php';
|
require_once APP_ROOT . '/src/Database.php';
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
require_once __DIR__ . '/../../../bootstrap.php';
|
require_once __DIR__ . '/../../../bootstrap.php';
|
||||||
require_once __DIR__ . '/../../../src/AdminAuth.php';
|
require_once __DIR__ . '/../../../src/AdminAuth.php';
|
||||||
|
error_log('[tag.php] ENTRY | method=' . $_SERVER['REQUEST_METHOD'] . ' | action=' . ($_POST['action'] ?? 'none') . ' | post_keys=' . implode(',', array_keys($_POST)));
|
||||||
AdminAuth::requireLogin();
|
AdminAuth::requireLogin();
|
||||||
|
|
||||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST'
|
if ($_SERVER['REQUEST_METHOD'] !== 'POST'
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
require_once __DIR__ . '/../../../bootstrap.php';
|
require_once __DIR__ . '/../../../bootstrap.php';
|
||||||
require_once __DIR__ . '/../../../src/AdminAuth.php';
|
require_once __DIR__ . '/../../../src/AdminAuth.php';
|
||||||
|
error_log('[visibility.php] ENTRY | method=' . $_SERVER['REQUEST_METHOD'] . ' | action=' . ($_POST['action'] ?? 'none') . ' | is_bulk=' . (!empty($_POST['bulk']) ? '1' : '0') . ' | post_keys=' . implode(',', array_keys($_POST)));
|
||||||
AdminAuth::requireLogin();
|
AdminAuth::requireLogin();
|
||||||
|
|
||||||
if (!isset($_POST['csrf_token'], $_SESSION['csrf_token'])
|
if (!isset($_POST['csrf_token'], $_SESSION['csrf_token'])
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ $importResults = [];
|
|||||||
$importDone = false;
|
$importDone = false;
|
||||||
|
|
||||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['csv_file'])) {
|
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['csv_file'])) {
|
||||||
|
error_log('[admin/index.php] IMPORT ENTRY | method=' . $_SERVER['REQUEST_METHOD'] . ' | content_type=' . ($_SERVER['CONTENT_TYPE'] ?? 'none') . ' | csv_file_error=' . ($_FILES['csv_file']['error'] ?? 'none') . ' | post_keys=' . implode(',', array_keys($_POST)));
|
||||||
if (!isset($_POST['csrf_token']) || !hash_equals($_SESSION['csrf_token'], $_POST['csrf_token'])) {
|
if (!isset($_POST['csrf_token']) || !hash_equals($_SESSION['csrf_token'], $_POST['csrf_token'])) {
|
||||||
$importErrors[] = "Erreur de sécurité : token invalide.";
|
$importErrors[] = "Erreur de sécurité : token invalide.";
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
require_once __DIR__ . '/../../bootstrap.php';
|
require_once __DIR__ . '/../../bootstrap.php';
|
||||||
require_once __DIR__ . '/../../src/AdminAuth.php';
|
require_once __DIR__ . '/../../src/AdminAuth.php';
|
||||||
|
|
||||||
|
error_log('[admin/login.php] ENTRY | method=' . $_SERVER['REQUEST_METHOD'] . ' | is_auth=' . (AdminAuth::isAuthenticated() ? '1' : '0') . ' | has_password=' . (AdminAuth::hasPassword() ? '1' : '0'));
|
||||||
|
|
||||||
if (!AdminAuth::hasPassword()) {
|
if (!AdminAuth::hasPassword()) {
|
||||||
header('Location: /admin/');
|
header('Location: /admin/');
|
||||||
exit;
|
exit;
|
||||||
|
|||||||
@@ -363,6 +363,9 @@
|
|||||||
|
|
||||||
// ── Form submit interception ───────────────────────────────────────────
|
// ── Form submit interception ───────────────────────────────────────────
|
||||||
|
|
||||||
|
// Track whether we've already intercepted this submit to prevent double-submit
|
||||||
|
var _xamxamActiveSubmit = false;
|
||||||
|
|
||||||
function bindFormSubmit() {
|
function bindFormSubmit() {
|
||||||
document.querySelectorAll("form[data-beforeunload-guard]").forEach(function (form) {
|
document.querySelectorAll("form[data-beforeunload-guard]").forEach(function (form) {
|
||||||
if (form.dataset.xamxamFormBound) return;
|
if (form.dataset.xamxamFormBound) return;
|
||||||
@@ -370,10 +373,29 @@
|
|||||||
|
|
||||||
form.addEventListener("submit", function (e) {
|
form.addEventListener("submit", function (e) {
|
||||||
var hasFiles = QUEUE_TYPES.some(function (qt) { return queues[qt].length > 0; });
|
var hasFiles = QUEUE_TYPES.some(function (qt) { return queues[qt].length > 0; });
|
||||||
if (!hasFiles) return; // Normal submit
|
|
||||||
|
console.log("[file-upload-queue] submit event fired | action=" + (form.getAttribute("action") || "") + " | hasFiles=" + hasFiles + " | enctype=" + form.enctype);
|
||||||
|
|
||||||
|
if (!hasFiles) {
|
||||||
|
console.log("[file-upload-queue] no queued files, passing through native submit");
|
||||||
|
markClean();
|
||||||
|
return; // Normal submit
|
||||||
|
}
|
||||||
|
|
||||||
// Check if the form can accept multipart
|
// Check if the form can accept multipart
|
||||||
if (form.enctype !== "multipart/form-data") return;
|
if (form.enctype !== "multipart/form-data") {
|
||||||
|
console.log("[file-upload-queue] form enctype is not multipart/form-data, passing through");
|
||||||
|
markClean();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prevent double-submit (in case native submit falls through)
|
||||||
|
if (_xamxamActiveSubmit) {
|
||||||
|
console.log("[file-upload-queue] already submitting, skipping");
|
||||||
|
e.preventDefault();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_xamxamActiveSubmit = true;
|
||||||
|
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
@@ -392,32 +414,53 @@
|
|||||||
|
|
||||||
markClean();
|
markClean();
|
||||||
|
|
||||||
// Use fetch so we can inspect the response before navigation.
|
console.log("[file-upload-queue] injecting " + QUEUE_TYPES.map(function(qt) { return qt + ":" + queues[qt].length; }).join(", ") + " files into FormData");
|
||||||
// The server either redirects (302 → we navigate to that URL)
|
|
||||||
// or returns the form page with errors (200 → replace the page).
|
// Use XMLHttpRequest instead of fetch so we can reliably read the
|
||||||
fetch(form.getAttribute("action") || "", {
|
// final URL after redirects (fetch with redirect:manual hides headers).
|
||||||
method: "POST",
|
var xhr = new XMLHttpRequest();
|
||||||
body: fd,
|
xhr.open("POST", form.getAttribute("action") || "", true);
|
||||||
redirect: "manual",
|
xhr.responseType = "text";
|
||||||
}).then(function (resp) {
|
|
||||||
if (resp.type === "opaqueredirect" || resp.status === 302 || resp.status === 301) {
|
xhr.onload = function () {
|
||||||
// Browser redirect — navigate the whole page
|
_xamxamActiveSubmit = false;
|
||||||
window.location.href = resp.headers.get("Location") || form.getAttribute("action");
|
var finalUrl = xhr.responseURL || "";
|
||||||
|
|
||||||
|
console.log("[file-upload-queue] XHR status=" + xhr.status + " | finalUrl=" + finalUrl + " | responseLength=" + (xhr.responseText ? xhr.responseText.length : 0));
|
||||||
|
|
||||||
|
// If the server redirected us (responseURL differs from action), navigate there.
|
||||||
|
// This handles the 302 redirect pattern used by formulaire.php and edit.php.
|
||||||
|
var actionUrl = form.getAttribute("action") || "";
|
||||||
|
if (finalUrl && finalUrl !== actionUrl && finalUrl !== window.location.href) {
|
||||||
|
console.log("[file-upload-queue] redirecting to " + finalUrl);
|
||||||
|
window.location.href = finalUrl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Success or error — render the HTML response
|
|
||||||
return resp.text();
|
// 200 with HTML — likely form errors, replace page
|
||||||
}).then(function (html) {
|
if (xhr.status >= 200 && xhr.status < 300 && xhr.responseText) {
|
||||||
if (!html) return;
|
console.log("[file-upload-queue] rendering error response HTML");
|
||||||
document.open();
|
document.open();
|
||||||
document.write(html);
|
document.write(xhr.responseText);
|
||||||
document.close();
|
document.close();
|
||||||
// Re-bind after DOM replacement (for error re-renders)
|
// Re-bind after DOM replacement (for error re-renders)
|
||||||
setTimeout(window.XamxamInitFileUploads, 0);
|
setTimeout(window.XamxamInitFileUploads, 0);
|
||||||
}).catch(function () {
|
return;
|
||||||
// Network error — fall back to native submit
|
}
|
||||||
|
|
||||||
|
// Fallback: reload current page
|
||||||
|
console.log("[file-upload-queue] unexpected response, reloading page");
|
||||||
|
window.location.reload();
|
||||||
|
};
|
||||||
|
|
||||||
|
xhr.onerror = function () {
|
||||||
|
_xamxamActiveSubmit = false;
|
||||||
|
console.error("[file-upload-queue] XHR network error, falling back to native submit");
|
||||||
|
// Fall back to native submit
|
||||||
form.submit();
|
form.submit();
|
||||||
});
|
};
|
||||||
|
|
||||||
|
xhr.send(fd);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -93,6 +93,7 @@ App::boot();
|
|||||||
|
|
||||||
// ── POST: form submission ─────────────────────────────────────────────────────
|
// ── POST: form submission ─────────────────────────────────────────────────────
|
||||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && $action === 'submit') {
|
if ($_SERVER['REQUEST_METHOD'] === 'POST' && $action === 'submit') {
|
||||||
|
error_log('[partage/index.php] SUBMIT ENTRY | slug=' . $slug . ' | content_type=' . ($_SERVER['CONTENT_TYPE'] ?? 'none') . ' | content_length=' . ($_SERVER['CONTENT_LENGTH'] ?? '0') . ' | post_keys=' . implode(',', array_keys($_POST)) . ' | files_count=' . count($_FILES) . ' | files_keys=' . implode(',', array_keys($_FILES)) . ' | queue_tfe=' . (isset($_FILES['queue_file']['name']['tfe']) ? count(array_filter($_FILES['queue_file']['name']['tfe'])) : 0));
|
||||||
handleShareLinkSubmission($slug);
|
handleShareLinkSubmission($slug);
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
@@ -187,6 +188,7 @@ function renderShareLinkError(string $title, string $message): void
|
|||||||
function requirePasswordGate(array $link, string $slug): void
|
function requirePasswordGate(array $link, string $slug): void
|
||||||
{
|
{
|
||||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['share_password'])) {
|
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['share_password'])) {
|
||||||
|
error_log('[partage/password-gate] ENTRY | slug=' . $slug . ' | post_keys=' . implode(',', array_keys($_POST)));
|
||||||
require_once APP_ROOT . '/src/ShareLink.php';
|
require_once APP_ROOT . '/src/ShareLink.php';
|
||||||
$shareLinkModel = new ShareLink(Database::getInstance());
|
$shareLinkModel = new ShareLink(Database::getInstance());
|
||||||
|
|
||||||
|
|||||||
@@ -259,6 +259,19 @@
|
|||||||
+%%%%%%% diff from: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
|
+%%%%%%% diff from: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
|
||||||
+\\\\\\\ to: ownwlmpo c4c4c8c2 "Replace HTMX+PHP file upload queues with client-side JS" (rebased revision)
|
+\\\\\\\ to: ownwlmpo c4c4c8c2 "Replace HTMX+PHP file upload queues with client-side JS" (rebased revision)
|
||||||
++ $linkName = $link['name'] ?? '';
|
++ $linkName = $link['name'] ?? '';
|
||||||
|
++ $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
|
||||||
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: ownwlmpo c4c4c8c2 "Replace HTMX+PHP file upload queues with client-side JS" (rebased revision)
|
||||||
|
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ to: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
|
||||||
|
- $linkName = $link['name'] ?? '';
|
||||||
|
- $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
|
||||||
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: somsyvxz 14a3cd10 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebase destination)
|
||||||
|
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ to: muzswpkw 732e19e8 "fix: repair form submission with queued files + add comprehensive debug logging" (rebased revision)
|
||||||
|
$linkName = $link['name'] ?? '';
|
||||||
|
$linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
|
||||||
|
$linkLockedYear = $link['locked_year'] ?? null;
|
||||||
|
+%%%%%%% diff from: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
|
||||||
|
+\\\\\\\ to: muzswpkw dbe1ac28 "fix: repair form submission with queued files + add comprehensive debug logging" (rebased revision)
|
||||||
|
++ $linkName = $link['name'] ?? '';
|
||||||
++ $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
|
++ $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
|
||||||
?>
|
?>
|
||||||
<tr class="admin-table-row" onclick="event.stopPropagation(); window.open('/partage/<?= urlencode($link['slug']) ?>', '_blank')" style="cursor:pointer">
|
<tr class="admin-table-row" onclick="event.stopPropagation(); window.open('/partage/<?= urlencode($link['slug']) ?>', '_blank')" style="cursor:pointer">
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
* string $hxPost — optional hx-post URL for HTMX live update
|
* string $hxPost — optional hx-post URL for HTMX live update
|
||||||
* string $hxTarget — optional hx-target CSS selector for HTMX swap
|
* string $hxTarget — optional hx-target CSS selector for HTMX swap
|
||||||
* string $hxSwap — optional hx-swap value; default 'outerHTML'
|
* string $hxSwap — optional hx-swap value; default 'outerHTML'
|
||||||
* string $hxInclude — optional hx-include selector; default 'this, #website-url-fieldset'
|
* string $hxInclude — optional hx-include selector; default 'this'
|
||||||
*/
|
*/
|
||||||
|
|
||||||
$checked = $checked ?? [];
|
$checked = $checked ?? [];
|
||||||
@@ -24,7 +24,7 @@ $required = $required ?? false;
|
|||||||
$hxPost = $hxPost ?? '';
|
$hxPost = $hxPost ?? '';
|
||||||
$hxTarget = $hxTarget ?? '';
|
$hxTarget = $hxTarget ?? '';
|
||||||
$hxSwap = $hxSwap ?? 'outerHTML';
|
$hxSwap = $hxSwap ?? 'outerHTML';
|
||||||
$hxInclude = $hxInclude ?? 'this, #website-url-fieldset';
|
$hxInclude = $hxInclude ?? 'this';
|
||||||
?>
|
?>
|
||||||
<div>
|
<div>
|
||||||
<span class="admin-row-label"><?= htmlspecialchars($label) ?><?= $required ? ' <span class="asterisk">*</span>' : '' ?></span>
|
<span class="admin-row-label"><?= htmlspecialchars($label) ?><?= $required ? ' <span class="asterisk">*</span>' : '' ?></span>
|
||||||
|
|||||||
Reference in New Issue
Block a user