diff --git a/web/admin/accounts.php b/web/admin/accounts.php index 4ea48cd..32a690a 100644 --- a/web/admin/accounts.php +++ b/web/admin/accounts.php @@ -123,6 +123,12 @@ html_navbar('accounts');
+
+ + QR Codes téléversement + +
+
diff --git a/web/admin/qrcode.php b/web/admin/qrcode.php new file mode 100644 index 0000000..96fed9b --- /dev/null +++ b/web/admin/qrcode.php @@ -0,0 +1,106 @@ +query('SELECT id, username, display_name FROM accounts WHERE active = 1 ORDER BY username')->fetchAll(); + +html_head('QR Codes Upload'); +html_navbar('accounts'); +?> +
+
+
QR Codes — Téléversement mobile
+
+ + Comptes + + +
+
+ +
+ + Imprimez et affichez ces QR codes au comptoir. Le client scanne avec son téléphone et envoie ses documents directement. +
+ +
+ +
+
+
+
+ Tous les postes +
+

Le client choisit le poste sur la page

+
+ +
+
+
+ + +
+
+
+
+ + +
+ +

+ +

Accès direct à ce poste

+ +
+ +
+
+
+ +
+
+ + + + + + diff --git a/web/api/upload.php b/web/api/upload.php new file mode 100644 index 0000000..821f41a --- /dev/null +++ b/web/api/upload.php @@ -0,0 +1,104 @@ + 'Méthode non autorisée']); + exit; +} + +$accountId = (int)($_POST['account_id'] ?? 0); +if (!$accountId) { + http_response_code(400); + echo json_encode(['error' => 'Compte non spécifié']); + exit; +} + +$st = db()->prepare('SELECT id, username, smb_path, webhook_url FROM accounts WHERE id = ? AND active = 1'); +$st->execute([$accountId]); +$account = $st->fetch(); +if (!$account) { + http_response_code(404); + echo json_encode(['error' => 'Compte introuvable ou inactif']); + exit; +} + +if (empty($_FILES['files']) || !is_array($_FILES['files']['name'])) { + http_response_code(400); + echo json_encode(['error' => 'Aucun fichier envoyé']); + exit; +} + +$destDir = $account['smb_path']; +if (!is_dir($destDir)) mkdir($destDir, 0750, true); + +$st = db()->prepare('INSERT INTO source_file (account_id, title, sender, file_name) VALUES (?, ?, ?, ?)'); +$st->execute([$account['id'], 'Dépôt comptoir', 'Téléversement mobile', 'upload_' . time()]); +$sourceId = (int)db()->lastInsertId(); + +$uploaded = 0; +$errors = []; +$fileCount = count($_FILES['files']['name']); + +for ($i = 0; $i < $fileCount; $i++) { + if ($_FILES['files']['error'][$i] !== UPLOAD_ERR_OK) { + $errors[] = $_FILES['files']['name'][$i] . ' : erreur upload'; + continue; + } + + $origName = $_FILES['files']['name'][$i]; + $tmpPath = $_FILES['files']['tmp_name'][$i]; + + $safeName = preg_replace('/[^a-zA-Z0-9._\- ]/', '_', $origName); + $destPath = $destDir . '/' . $safeName; + + if (file_exists($destPath)) { + $ext = pathinfo($safeName, PATHINFO_EXTENSION); + $base = pathinfo($safeName, PATHINFO_FILENAME); + $destPath = $destDir . '/' . $base . '_' . time() . ($ext ? '.' . $ext : ''); + $safeName = basename($destPath); + } + + if (move_uploaded_file($tmpPath, $destPath)) { + chmod($destPath, 0644); + db()->prepare('INSERT INTO files (source_file_id, file_name, path) VALUES (?, ?, ?)') + ->execute([$sourceId, $safeName, $destPath]); + $uploaded++; + } else { + $errors[] = $origName . ' : échec écriture'; + } +} + +if ($uploaded === 0) { + db()->prepare('DELETE FROM source_file WHERE id = ?')->execute([$sourceId]); + http_response_code(500); + echo json_encode(['error' => 'Aucun fichier enregistré', 'details' => $errors]); + exit; +} + +if (!empty($account['webhook_url'])) { + $ctx = stream_context_create(['http' => [ + 'method' => 'POST', + 'header' => "Content-Type: application/json\r\n", + 'content' => json_encode([ + 'account' => $account['username'], + 'subject' => 'Dépôt comptoir', + 'from' => 'Téléversement mobile', + 'source_id' => $sourceId, + 'files' => $uploaded, + 'received_at' => date('c'), + ]), + 'timeout' => 5, + 'ignore_errors' => true, + ]]); + @file_get_contents($account['webhook_url'], false, $ctx); +} + +echo json_encode([ + 'success' => true, + 'uploaded' => $uploaded, + 'account' => $account['username'], + 'errors' => $errors, +]); diff --git a/web/upload.php b/web/upload.php new file mode 100644 index 0000000..e8b8983 --- /dev/null +++ b/web/upload.php @@ -0,0 +1,407 @@ +query('SELECT id, username, display_name FROM accounts WHERE active = 1 ORDER BY username')->fetchAll(); +$preselect = $_GET['to'] ?? ''; +?> + + + + + + + Envoyer un document — CopyMail + + + + + +
+ CopyMail +
+ + +
+
+ Sélectionnez le poste +
+
+ +
+ +
+ + +
+ Aucun poste disponible. +
+ +
+
+ + + + + + + + +
+ +
+ + + + +