Derniere version de site au 4/10/2026
This commit is contained in:
1 parent
21f34c64c9
commit
dbb8e299a0
35 files changed
+8697
-1242
No files matched your search
+264
-220
@@ -1,219 +1,263 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
require_once __DIR__ . '/../includes/bootstrap_global.php';
|
||||
declare (strict_types = 1);
|
||||
require_once __DIR__ . '/../includes/bootstrap_global.php';
|
||||
|
||||
// ===== Helpers header (identiques à index.php) =====
|
||||
function is_client_logged_in(): bool {
|
||||
$role = $_SESSION['role'] ?? ($_SESSION['user_type'] ?? '');
|
||||
if (!empty($_SESSION['user_id']) && $role === 'client') return true;
|
||||
if (!empty($_SESSION['client_id'])) return true;
|
||||
if (!empty($_SESSION['reference_id']) && $role === 'client') return true;
|
||||
if (!empty($_SESSION['user_id']) && $role === 'praticien') return true;
|
||||
if (!empty($_SESSION['praticien_id'])) return true;
|
||||
if (!empty($_SESSION['reference_id']) && $role === 'praticien') return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
function include_header_clean(string $absPath): void {
|
||||
global $translations, $lang;
|
||||
ob_start();
|
||||
include $absPath; // /public/includes/header.php
|
||||
$buf = ob_get_clean() ?: '';
|
||||
|
||||
// 0) DOCTYPE + <html>…</html>
|
||||
$buf = preg_replace('~<!doctype\s+html[^>]*>~i', '', $buf);
|
||||
$buf = preg_replace('~</?html\b[^>]*>~i', '', $buf);
|
||||
|
||||
// 1) retirer <head>…</head> et <body> ouverts/fermés
|
||||
$buf = preg_replace('~<head\b[^>]*>.*?</head>~is', '', $buf);
|
||||
$buf = preg_replace('~</?body\b[^>]*>~i', '', $buf);
|
||||
|
||||
// 2) retirer les <link> CSS “globaux” pour éviter d’écraser la home
|
||||
$buf = preg_replace('~<link[^>]+href="[^"]*(bootstrap[^"]*\.css|mobil_style\.css|site_style\.css|fonts\.googleapis)[^"]*"[^>]*>~i', '', $buf);
|
||||
|
||||
// 3) retirer le <script> Bootstrap CDN (on le charge déjà en bas de la page)
|
||||
$buf = preg_replace('~<script[^>]+src="[^"]*bootstrap[^"]*bundle[^"]*\.js[^"]*"[^>]*>\s*</script>~i', '', $buf);
|
||||
|
||||
echo $buf; // garde <header> + tes scripts inline utiles
|
||||
}
|
||||
|
||||
/* ---------- Utils ---------- */
|
||||
function envget(string $k): string {
|
||||
return trim((string)($_ENV[$k] ?? $_SERVER[$k] ?? getenv($k) ?? ''));
|
||||
}
|
||||
|
||||
function t(array $translations, string $key, string $fallback = ''): string {
|
||||
$val = $translations[$key] ?? '';
|
||||
if ($val === '') return $fallback;
|
||||
return (string)$val;
|
||||
}
|
||||
|
||||
$LOG_DIR = __DIR__ . '/tmp';
|
||||
$LOG_FILE = $LOG_DIR . '/contact.log';
|
||||
if (!is_dir($LOG_DIR)) { @mkdir($LOG_DIR, 0770, true); } // dossier local, pas servi publiquement
|
||||
|
||||
/* ---------- CSRF ---------- */
|
||||
if (empty($_SESSION['pub_csrf'])) {
|
||||
$_SESSION['pub_csrf'] = bin2hex(random_bytes(32));
|
||||
}
|
||||
$CSRF = $_SESSION['pub_csrf'];
|
||||
|
||||
// --- reCAPTCHA v2 (lecture robuste) ---
|
||||
$rcCfg = [];
|
||||
$cfgPath = __DIR__ . '/includes/recaptcha.php';
|
||||
if (is_file($cfgPath)) {
|
||||
$rcCfg = require $cfgPath; // ['site' => '...', 'secret' => '...']
|
||||
}
|
||||
|
||||
$RECAPTCHA_SITE_KEY = trim((string)($rcCfg['site'] ?? envget('RECAPTCHA_SITE_KEY') ?? ''));
|
||||
$RECAPTCHA_SECRET_KEY = trim((string)($rcCfg['secret'] ?? envget('RECAPTCHA_SECRET_KEY') ?? ''));
|
||||
|
||||
// Considère la clé "valide" si longueur réaliste (>= 20) – évite les faux négatifs
|
||||
$HAS_SITE = (strlen($RECAPTCHA_SITE_KEY) >= 20);
|
||||
$HAS_SECRET = (strlen($RECAPTCHA_SECRET_KEY) >= 20);
|
||||
|
||||
// (optionnel) forcer l’affichage en test: /contact.php?testcaptcha=1
|
||||
if (($_GET['testcaptcha'] ?? '') === '1') $HAS_SITE = true;
|
||||
|
||||
/* ---------- État page ---------- */
|
||||
$errors = [];
|
||||
$sent = false;
|
||||
|
||||
/* ---------- POST ---------- */
|
||||
if (($_SERVER['REQUEST_METHOD'] ?? '') === 'POST') {
|
||||
|
||||
// CSRF
|
||||
if (!hash_equals($_SESSION['pub_csrf'] ?? '', $_POST['csrf'] ?? '')) {
|
||||
$errors[] = t($translations, 'contact_err_security', 'Security error. Refresh and try again.');
|
||||
}
|
||||
|
||||
// Honeypot anti-bot
|
||||
if (!empty($_POST['website'] ?? '')) {
|
||||
$errors[] = t($translations, 'contact_err_spam', 'Spam suspected.');
|
||||
}
|
||||
|
||||
// Données utilisateur
|
||||
$prenom = trim($_POST['prenom'] ?? '');
|
||||
$nom = trim($_POST['nom'] ?? '');
|
||||
$email = trim($_POST['email'] ?? '');
|
||||
$sujet = trim($_POST['sujet'] ?? '');
|
||||
$message = trim($_POST['message'] ?? '');
|
||||
|
||||
// Validations
|
||||
if (mb_strlen($prenom) < 2) $errors[] = t($translations, 'contact_err_prenom', 'Please enter your first name.');
|
||||
if (mb_strlen($nom) < 2) $errors[] = t($translations, 'contact_err_nom', 'Please enter your last name.');
|
||||
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) $errors[] = t($translations, 'contact_err_email', 'Please enter a valid email.');
|
||||
if (mb_strlen($sujet) < 3) $errors[] = t($translations, 'contact_err_sujet', 'Subject is too short.');
|
||||
if (mb_strlen($message) < 10) $errors[] = t($translations, 'contact_err_message', 'Message is too short.');
|
||||
|
||||
// reCAPTCHA serveur
|
||||
if ($HAS_SECRET) {
|
||||
$token = $_POST['g-recaptcha-response'] ?? '';
|
||||
if ($token === '') {
|
||||
$errors[] = t($translations, 'contact_err_captcha_required', 'Please confirm you are not a robot.');
|
||||
} else {
|
||||
$resp = @file_get_contents(
|
||||
'https://www.google.com/recaptcha/api/siteverify?secret=' . urlencode($RECAPTCHA_SECRET_KEY) .
|
||||
'&response=' . urlencode($token) .
|
||||
'&remoteip=' . urlencode($_SERVER['REMOTE_ADDR'] ?? '')
|
||||
);
|
||||
$ver = $resp ? json_decode($resp, true) : ['success' => false];
|
||||
if (empty($ver['success'])) $errors[] = t($translations, 'contact_err_captcha_failed', 'reCAPTCHA verification failed.');
|
||||
// ===== Helpers header (identiques à index.php) =====
|
||||
function is_client_logged_in(): bool
|
||||
{
|
||||
$role = $_SESSION['role'] ?? ($_SESSION['user_type'] ?? '');
|
||||
if (! empty($_SESSION['user_id']) && $role === 'client') {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Envoi
|
||||
if (!$errors) {
|
||||
$to = 'contact@uslugi.fr';
|
||||
if (! empty($_SESSION['client_id'])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$subjectPrefix = t($translations, 'contact_send_subject_prefix', 'Contact form message — ');
|
||||
$subject = $subjectPrefix . $sujet;
|
||||
if (! empty($_SESSION['reference_id']) && $role === 'client') {
|
||||
return true;
|
||||
}
|
||||
|
||||
$mailH3 = t($translations, 'contact_mail_h3', 'New message from uslugi.fr');
|
||||
$lblName = t($translations, 'contact_mail_label_name', 'Name');
|
||||
$lblEmail = t($translations, 'contact_mail_label_email', 'Email');
|
||||
$lblSubject = t($translations, 'contact_mail_label_subject', 'Subject');
|
||||
$lblMessage = t($translations, 'contact_mail_label_message', 'Message');
|
||||
if (! empty($_SESSION['user_id']) && $role === 'praticien') {
|
||||
return true;
|
||||
}
|
||||
|
||||
$html = '
|
||||
<h3>'.htmlspecialchars($mailH3, ENT_QUOTES, 'UTF-8').'</h3>
|
||||
<p><strong>'.htmlspecialchars($lblName, ENT_QUOTES, 'UTF-8').':</strong> '.htmlspecialchars($prenom).' '.htmlspecialchars($nom).'</p>
|
||||
<p><strong>'.htmlspecialchars($lblEmail, ENT_QUOTES, 'UTF-8').':</strong> '.htmlspecialchars($email).'</p>
|
||||
<p><strong>'.htmlspecialchars($lblSubject, ENT_QUOTES, 'UTF-8').':</strong> '.htmlspecialchars($sujet).'</p>
|
||||
<p><strong>'.htmlspecialchars($lblMessage, ENT_QUOTES, 'UTF-8').':</strong><br>'.nl2br(htmlspecialchars($message)).'</p>
|
||||
if (! empty($_SESSION['praticien_id'])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (! empty($_SESSION['reference_id']) && $role === 'praticien') {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function include_header_clean(string $absPath): void
|
||||
{
|
||||
global $translations, $lang;
|
||||
ob_start();
|
||||
include $absPath; // /public/includes/header.php
|
||||
$buf = ob_get_clean() ?: '';
|
||||
|
||||
// 0) DOCTYPE + <html>…</html>
|
||||
$buf = preg_replace('~<!doctype\s+html[^>]*>~i', '', $buf);
|
||||
$buf = preg_replace('~</?html\b[^>]*>~i', '', $buf);
|
||||
|
||||
// 1) retirer <head>…</head> et <body> ouverts/fermés
|
||||
$buf = preg_replace('~<head\b[^>]*>.*?</head>~is', '', $buf);
|
||||
$buf = preg_replace('~</?body\b[^>]*>~i', '', $buf);
|
||||
|
||||
// 2) retirer les <link> CSS “globaux” pour éviter d’écraser la home
|
||||
$buf = preg_replace('~<link[^>]+href="[^"]*(bootstrap[^"]*\.css|mobil_style\.css|site_style\.css|fonts\.googleapis)[^"]*"[^>]*>~i', '', $buf);
|
||||
|
||||
// 3) retirer le <script> Bootstrap CDN (on le charge déjà en bas de la page)
|
||||
$buf = preg_replace('~<script[^>]+src="[^"]*bootstrap[^"]*bundle[^"]*\.js[^"]*"[^>]*>\s*</script>~i', '', $buf);
|
||||
|
||||
echo $buf; // garde <header> + tes scripts inline utiles
|
||||
}
|
||||
|
||||
/* ---------- Utils ---------- */
|
||||
function envget(string $k): string
|
||||
{
|
||||
return trim((string) ($_ENV[$k] ?? $_SERVER[$k] ?? getenv($k) ?? ''));
|
||||
}
|
||||
|
||||
function t(array $translations, string $key, string $fallback = ''): string
|
||||
{
|
||||
$val = $translations[$key] ?? '';
|
||||
if ($val === '') {
|
||||
return $fallback;
|
||||
}
|
||||
|
||||
return (string) $val;
|
||||
}
|
||||
|
||||
$LOG_DIR = __DIR__ . '/tmp';
|
||||
$LOG_FILE = $LOG_DIR . '/contact.log';
|
||||
if (! is_dir($LOG_DIR)) {@mkdir($LOG_DIR, 0770, true);} // dossier local, pas servi publiquement
|
||||
|
||||
/* ---------- CSRF ---------- */
|
||||
if (empty($_SESSION['pub_csrf'])) {
|
||||
$_SESSION['pub_csrf'] = bin2hex(random_bytes(32));
|
||||
}
|
||||
$CSRF = $_SESSION['pub_csrf'];
|
||||
|
||||
// --- reCAPTCHA v2 (lecture robuste) ---
|
||||
$rcCfg = [];
|
||||
$cfgPath = __DIR__ . '/includes/recaptcha.php';
|
||||
if (is_file($cfgPath)) {
|
||||
$rcCfg = require $cfgPath; // ['site' => '...', 'secret' => '...']
|
||||
}
|
||||
|
||||
$RECAPTCHA_SITE_KEY = trim((string) ($rcCfg['site'] ?? envget('RECAPTCHA_SITE_KEY') ?? ''));
|
||||
$RECAPTCHA_SECRET_KEY = trim((string) ($rcCfg['secret'] ?? envget('RECAPTCHA_SECRET_KEY') ?? ''));
|
||||
|
||||
// Considère la clé "valide" si longueur réaliste (>= 20) – évite les faux négatifs
|
||||
$HAS_SITE = (strlen($RECAPTCHA_SITE_KEY) >= 20);
|
||||
$HAS_SECRET = (strlen($RECAPTCHA_SECRET_KEY) >= 20);
|
||||
|
||||
// (optionnel) forcer l’affichage en test: /contact.php?testcaptcha=1
|
||||
if (($_GET['testcaptcha'] ?? '') === '1') {
|
||||
$HAS_SITE = true;
|
||||
}
|
||||
|
||||
/* ---------- État page ---------- */
|
||||
$errors = [];
|
||||
$sent = false;
|
||||
|
||||
/* ---------- POST ---------- */
|
||||
if (($_SERVER['REQUEST_METHOD'] ?? '') === 'POST') {
|
||||
|
||||
// CSRF
|
||||
if (! hash_equals($_SESSION['pub_csrf'] ?? '', $_POST['csrf'] ?? '')) {
|
||||
$errors[] = t($translations, 'contact_err_security', 'Security error. Refresh and try again.');
|
||||
}
|
||||
|
||||
// Honeypot anti-bot
|
||||
if (! empty($_POST['website'] ?? '')) {
|
||||
$errors[] = t($translations, 'contact_err_spam', 'Spam suspected.');
|
||||
}
|
||||
|
||||
// Données utilisateur
|
||||
$prenom = trim($_POST['prenom'] ?? '');
|
||||
$nom = trim($_POST['nom'] ?? '');
|
||||
$email = trim($_POST['email'] ?? '');
|
||||
$sujet = trim($_POST['sujet'] ?? '');
|
||||
$message = trim($_POST['message'] ?? '');
|
||||
|
||||
// Validations
|
||||
if (mb_strlen($prenom) < 2) {
|
||||
$errors[] = t($translations, 'contact_err_prenom', 'Please enter your first name.');
|
||||
}
|
||||
|
||||
if (mb_strlen($nom) < 2) {
|
||||
$errors[] = t($translations, 'contact_err_nom', 'Please enter your last name.');
|
||||
}
|
||||
|
||||
if (! filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
||||
$errors[] = t($translations, 'contact_err_email', 'Please enter a valid email.');
|
||||
}
|
||||
|
||||
if (mb_strlen($sujet) < 3) {
|
||||
$errors[] = t($translations, 'contact_err_sujet', 'Subject is too short.');
|
||||
}
|
||||
|
||||
if (mb_strlen($message) < 10) {
|
||||
$errors[] = t($translations, 'contact_err_message', 'Message is too short.');
|
||||
}
|
||||
|
||||
// reCAPTCHA serveur
|
||||
if ($HAS_SECRET) {
|
||||
$token = $_POST['g-recaptcha-response'] ?? '';
|
||||
if ($token === '') {
|
||||
$errors[] = t($translations, 'contact_err_captcha_required', 'Please confirm you are not a robot.');
|
||||
} else {
|
||||
$resp = @file_get_contents(
|
||||
'https://www.google.com/recaptcha/api/siteverify?secret=' . urlencode($RECAPTCHA_SECRET_KEY) .
|
||||
'&response=' . urlencode($token) .
|
||||
'&remoteip=' . urlencode($_SERVER['REMOTE_ADDR'] ?? '')
|
||||
);
|
||||
$ver = $resp ? json_decode($resp, true) : ['success' => false];
|
||||
if (empty($ver['success'])) {
|
||||
$errors[] = t($translations, 'contact_err_captcha_failed', 'reCAPTCHA verification failed.');
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Envoi
|
||||
if (! $errors) {
|
||||
$to = 'contact@uslugi.fr';
|
||||
|
||||
$subjectPrefix = t($translations, 'contact_send_subject_prefix', 'Contact form message — ');
|
||||
$subject = $subjectPrefix . $sujet;
|
||||
|
||||
$mailH3 = t($translations, 'contact_mail_h3', 'New message from uslugi.fr');
|
||||
$lblName = t($translations, 'contact_mail_label_name', 'Name');
|
||||
$lblEmail = t($translations, 'contact_mail_label_email', 'Email');
|
||||
$lblSubject = t($translations, 'contact_mail_label_subject', 'Subject');
|
||||
$lblMessage = t($translations, 'contact_mail_label_message', 'Message');
|
||||
|
||||
$html = '
|
||||
<h3>' . htmlspecialchars($mailH3, ENT_QUOTES, 'UTF-8') . '</h3>
|
||||
<p><strong>' . htmlspecialchars($lblName, ENT_QUOTES, 'UTF-8') . ':</strong> ' . htmlspecialchars($prenom) . ' ' . htmlspecialchars($nom) . '</p>
|
||||
<p><strong>' . htmlspecialchars($lblEmail, ENT_QUOTES, 'UTF-8') . ':</strong> ' . htmlspecialchars($email) . '</p>
|
||||
<p><strong>' . htmlspecialchars($lblSubject, ENT_QUOTES, 'UTF-8') . ':</strong> ' . htmlspecialchars($sujet) . '</p>
|
||||
<p><strong>' . htmlspecialchars($lblMessage, ENT_QUOTES, 'UTF-8') . ':</strong><br>' . nl2br(htmlspecialchars($message)) . '</p>
|
||||
';
|
||||
|
||||
$text = $mailH3 . "\n"
|
||||
. $lblName . ": $prenom $nom\n"
|
||||
. $lblEmail . ": $email\n"
|
||||
. $lblSubject . ": $sujet\n\n"
|
||||
. $lblMessage . ":\n$message\n";
|
||||
$text = $mailH3 . "\n"
|
||||
. $lblName . ": $prenom $nom\n"
|
||||
. $lblEmail . ": $email\n"
|
||||
. $lblSubject . ": $sujet\n\n"
|
||||
. $lblMessage . ":\n$message\n";
|
||||
|
||||
try {
|
||||
// From et Reply-To (tableaux) comme attendus par ton wrapper
|
||||
$fromEmail = 'no-reply@uslugi.fr';
|
||||
$fromName = 'USLUGI.FR';
|
||||
try {
|
||||
// From et Reply-To (tableaux) comme attendus par ton wrapper
|
||||
$fromEmail = 'no-reply@uslugi.fr';
|
||||
$fromName = 'USLUGI.FR';
|
||||
|
||||
$replyEmail = filter_var($email, FILTER_VALIDATE_EMAIL) ? $email : 'contact@uslugi.fr';
|
||||
$replyName = trim($prenom.' '.$nom) ?: 'USLUGI.FR';
|
||||
$replyEmail = filter_var($email, FILTER_VALIDATE_EMAIL) ? $email : 'contact@uslugi.fr';
|
||||
$replyName = trim($prenom . ' ' . $nom) ?: 'USLUGI.FR';
|
||||
|
||||
// Appel wrapper: retourne [bool $ok, ?string $err]
|
||||
[$ok, $err] = uslugi_mail(
|
||||
$to,
|
||||
$subject,
|
||||
$html,
|
||||
$text,
|
||||
[
|
||||
'from' => [$fromEmail, $fromName],
|
||||
'reply_to' => [$replyEmail, $replyName],
|
||||
// 'bcc' => ['tonmail@gmail.com'],
|
||||
]
|
||||
);
|
||||
// Appel wrapper: retourne [bool $ok, ?string $err]
|
||||
[$ok, $err] = uslugi_mail(
|
||||
$to,
|
||||
$subject,
|
||||
$html,
|
||||
$text,
|
||||
[
|
||||
'from' => [$fromEmail, $fromName],
|
||||
'reply_to' => [$replyEmail, $replyName],
|
||||
// 'bcc' => ['tonmail@gmail.com'],
|
||||
]
|
||||
);
|
||||
|
||||
if ($ok !== true) {
|
||||
throw new RuntimeException('Wrapper mail send failed.');
|
||||
}
|
||||
if ($ok !== true) {
|
||||
throw new RuntimeException('Wrapper mail send failed.');
|
||||
}
|
||||
|
||||
// OK
|
||||
$sent = true;
|
||||
$_POST = [];
|
||||
@file_put_contents($LOG_FILE, sprintf(
|
||||
"[%s] OK to=%s subj=%s reply=%s ip=%s\n",
|
||||
date('c'), $to, $sujet, $email, $_SERVER['REMOTE_ADDR'] ?? '-'
|
||||
), FILE_APPEND);
|
||||
// OK
|
||||
$sent = true;
|
||||
$_POST = [];
|
||||
@file_put_contents($LOG_FILE, sprintf(
|
||||
"[%s] OK to=%s subj=%s reply=%s ip=%s\n",
|
||||
date('c'), $to, $sujet, $email, $_SERVER['REMOTE_ADDR'] ?? '-'
|
||||
), FILE_APPEND);
|
||||
|
||||
} catch (Throwable $e) {
|
||||
error_log('MAIL ERROR: ' . $e->getMessage());
|
||||
@file_put_contents($LOG_FILE, sprintf(
|
||||
"[%s] ERR to=%s subj=%s\n",
|
||||
date('c'), $to, $sujet
|
||||
), FILE_APPEND);
|
||||
} catch (Throwable $e) {
|
||||
error_log('MAIL ERROR: ' . $e->getMessage());
|
||||
@file_put_contents($LOG_FILE, sprintf(
|
||||
"[%s] ERR to=%s subj=%s\n",
|
||||
date('c'), $to, $sujet
|
||||
), FILE_APPEND);
|
||||
|
||||
// Message utilisateur générique (jamais d’info sensible à l’écran)
|
||||
$errors[] = t($translations, 'contact_err_send_failed', 'Failed to send message. Please try later.');
|
||||
// Message utilisateur générique (jamais d’info sensible à l’écran)
|
||||
$errors[] = t($translations, 'contact_err_send_failed', 'Failed to send message. Please try later.');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Lang HTML
|
||||
$langHtml = preg_match('~^[a-z]{2}(-[A-Z]{2})?$~', (string)($lang ?? '')) ? (string)$lang : 'ru';
|
||||
// Lang HTML
|
||||
$langHtml = preg_match('~^[a-z]{2}(-[A-Z]{2})?$~', (string) ($lang ?? '')) ? (string) $lang : 'ru';
|
||||
?>
|
||||
<!doctype html>
|
||||
<html lang="<?= htmlspecialchars($langHtml, ENT_QUOTES, 'UTF-8') ?>">
|
||||
<html lang="<?php echo htmlspecialchars($langHtml, ENT_QUOTES, 'UTF-8') ?>">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title><?= htmlspecialchars($translations['seo_contact_title'], ENT_QUOTES, 'UTF-8') ?></title>
|
||||
<meta name="description" content="<?= htmlspecialchars($translations['seo_contact_desc'], ENT_QUOTES, 'UTF-8') ?>">
|
||||
<meta name="keywords" content="<?= htmlspecialchars($translations['seo_contact_keywords'], ENT_QUOTES, 'UTF-8') ?>">
|
||||
<title><?php echo htmlspecialchars($translations['seo_contact_title'], ENT_QUOTES, 'UTF-8') ?></title>
|
||||
<meta name="description" content="<?php echo htmlspecialchars($translations['seo_contact_desc'], ENT_QUOTES, 'UTF-8') ?>">
|
||||
<meta name="keywords" content="<?php echo htmlspecialchars($translations['seo_contact_keywords'], ENT_QUOTES, 'UTF-8') ?>">
|
||||
<meta name="author" content="Uslugi.fr">
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
|
||||
|
||||
<link rel="stylesheet" href="/css/bootstrap.min.css">
|
||||
|
||||
<link rel="stylesheet" href="<?= asset('/includes/site_style.css') ?>">
|
||||
<link rel="stylesheet" href="<?= asset('/includes/custom_style.css') ?>">
|
||||
<link rel="stylesheet" href="<?= asset('/includes/mobil_style.css') ?>">
|
||||
|
||||
<link rel="stylesheet" href="<?php echo asset('/includes/site_style.css') ?>">
|
||||
<link rel="stylesheet" href="<?php echo asset('/includes/custom_style.css') ?>">
|
||||
<link rel="stylesheet" href="<?php echo asset('/includes/mobil_style.css') ?>">
|
||||
<style>
|
||||
/* HERO bleu et cadre */
|
||||
.hero-contact{ background:#8CA9FF; padding: clamp(16px,4vw,32px); }
|
||||
@@ -242,9 +286,9 @@ $langHtml = preg_match('~^[a-z]{2}(-[A-Z]{2})?$~', (string)($lang ?? '')) ? (str
|
||||
</head>
|
||||
<body>
|
||||
<?php if (is_client_logged_in()): ?>
|
||||
<?php
|
||||
require_once __DIR__ . '/public/includes/init_pr_cl.php';
|
||||
include_header_clean(__DIR__ . '/public/includes/header.php'); ?>
|
||||
<?php
|
||||
require_once __DIR__ . '/public/includes/init_pr_cl.php';
|
||||
include_header_clean(__DIR__ . '/public/includes/header.php'); ?>
|
||||
<?php else: ?>
|
||||
<header class="site-header">
|
||||
<div class="container">
|
||||
@@ -264,8 +308,8 @@ $langHtml = preg_match('~^[a-z]{2}(-[A-Z]{2})?$~', (string)($lang ?? '')) ? (str
|
||||
</div>
|
||||
<nav class="header-actions">
|
||||
<a class="btn-login" href="/connexion.php">
|
||||
<span class="d-sm-none"><?php echo htmlspecialchars($translations['btn_se_connecter'] ?? 'Connexion', ENT_QUOTES, 'UTF-8')?></span>
|
||||
<span class="d-none d-sm-inline"><?php echo htmlspecialchars($translations['ja_spec'] ?? 'Je suis spécialiste', ENT_QUOTES, 'UTF-8')?></span>
|
||||
<span class="d-sm-none"><?php echo htmlspecialchars($translations['btn_se_connecter'] ?? 'Connexion', ENT_QUOTES, 'UTF-8') ?></span>
|
||||
<span class="d-none d-sm-inline"><?php echo htmlspecialchars($translations['ja_spec'] ?? 'Je suis spécialiste', ENT_QUOTES, 'UTF-8') ?></span>
|
||||
</a>
|
||||
|
||||
<div class="dropdown">
|
||||
@@ -275,15 +319,15 @@ $langHtml = preg_match('~^[a-z]{2}(-[A-Z]{2})?$~', (string)($lang ?? '')) ? (str
|
||||
data-bs-toggle="dropdown"
|
||||
data-bs-auto-close="true"
|
||||
aria-expanded="false"
|
||||
aria-label="<?php echo htmlspecialchars(t($translations, 'howitworks_help_aria', 'Help'), ENT_QUOTES, 'UTF-8')?>">
|
||||
aria-label="<?php echo htmlspecialchars(t($translations, 'howitworks_help_aria', 'Help'), ENT_QUOTES, 'UTF-8') ?>">
|
||||
?
|
||||
</button>
|
||||
|
||||
<ul class="dropdown-menu dropdown-menu-end shadow help-menu menu-panel">
|
||||
<li><a href="/how-it-work.php"><?php echo htmlspecialchars($translations['kak_rabotaet'] ?? 'Как это работает', ENT_QUOTES, 'UTF-8')?></a></li>
|
||||
<li><a href="/about.php"><?php echo htmlspecialchars($translations['pro_nas'] ?? 'О нас', ENT_QUOTES, 'UTF-8')?></a></li>
|
||||
<li><a href="/faq.php"><?php echo htmlspecialchars($translations['faq'] ?? 'FAQ', ENT_QUOTES, 'UTF-8')?></a></li>
|
||||
<li><a href="/contact.php"><?php echo htmlspecialchars($translations['nam_pisat'] ?? 'Написать нам', ENT_QUOTES, 'UTF-8')?></a></li>
|
||||
<li><a href="/how-it-work.php"><?php echo htmlspecialchars($translations['kak_rabotaet'] ?? 'Как это работает', ENT_QUOTES, 'UTF-8') ?></a></li>
|
||||
<li><a href="/about.php"><?php echo htmlspecialchars($translations['pro_nas'] ?? 'О нас', ENT_QUOTES, 'UTF-8') ?></a></li>
|
||||
<li><a href="/faq.php"><?php echo htmlspecialchars($translations['faq'] ?? 'FAQ', ENT_QUOTES, 'UTF-8') ?></a></li>
|
||||
<li><a href="/contact.php"><?php echo htmlspecialchars($translations['nam_pisat'] ?? 'Написать нам', ENT_QUOTES, 'UTF-8') ?></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@@ -297,65 +341,65 @@ $langHtml = preg_match('~^[a-z]{2}(-[A-Z]{2})?$~', (string)($lang ?? '')) ? (str
|
||||
<section class="hero-contact">
|
||||
<div class="container contact-wrap">
|
||||
<div class="contact-frame">
|
||||
<h1><?= htmlspecialchars(t($translations, 'contact_h1', 'Contact us'), ENT_QUOTES, 'UTF-8') ?></h1>
|
||||
<p class="muted"><?= htmlspecialchars(t($translations, 'contact_intro', 'Fill the form — we will reply as soon as possible.'), ENT_QUOTES, 'UTF-8') ?></p>
|
||||
<h1><?php echo htmlspecialchars(t($translations, 'contact_h1', 'Contact us'), ENT_QUOTES, 'UTF-8') ?></h1>
|
||||
<p class="muted"><?php echo htmlspecialchars(t($translations, 'contact_intro', 'Fill the form — we will reply as soon as possible.'), ENT_QUOTES, 'UTF-8') ?></p>
|
||||
|
||||
<?php if (!empty($errors)): ?>
|
||||
<?php if (! empty($errors)): ?>
|
||||
<div class="alert alert-danger" role="alert">
|
||||
<?= implode('<br>', array_map(static fn($s) => htmlspecialchars((string)$s, ENT_QUOTES, 'UTF-8'), $errors)) ?>
|
||||
<?php echo implode('<br>', array_map(static fn($s) => htmlspecialchars((string) $s, ENT_QUOTES, 'UTF-8'), $errors)) ?>
|
||||
</div>
|
||||
<?php elseif ($sent): ?>
|
||||
<div class="alert alert-success" role="alert">
|
||||
<?= htmlspecialchars(t($translations, 'contact_success_sent', 'Thank you! Your message has been sent.'), ENT_QUOTES, 'UTF-8') ?>
|
||||
<?php echo htmlspecialchars(t($translations, 'contact_success_sent', 'Thank you! Your message has been sent.'), ENT_QUOTES, 'UTF-8') ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<form method="post" action="" novalidate>
|
||||
<input type="hidden" name="csrf" value="<?= htmlspecialchars($CSRF, ENT_QUOTES, 'UTF-8') ?>">
|
||||
<input type="hidden" name="csrf" value="<?php echo htmlspecialchars($CSRF, ENT_QUOTES, 'UTF-8') ?>">
|
||||
<!-- Honeypot invisible -->
|
||||
<input type="text" name="website" autocomplete="off" tabindex="-1"
|
||||
style="position:absolute;left:-9999px;opacity:0" aria-hidden="true">
|
||||
|
||||
<div class="row g-3">
|
||||
<div class="col-12">
|
||||
<label class="form-label"><?= htmlspecialchars(t($translations, 'contact_label_nom', 'Last name'), ENT_QUOTES, 'UTF-8') ?></label>
|
||||
<label class="form-label"><?php echo htmlspecialchars(t($translations, 'contact_label_nom', 'Last name'), ENT_QUOTES, 'UTF-8') ?></label>
|
||||
<input type="text" name="nom" class="form-control"
|
||||
value="<?= htmlspecialchars($_POST['nom'] ?? '', ENT_QUOTES, 'UTF-8') ?>" required>
|
||||
value="<?php echo htmlspecialchars($_POST['nom'] ?? '', ENT_QUOTES, 'UTF-8') ?>" required>
|
||||
</div>
|
||||
|
||||
<div class="col-12">
|
||||
<label class="form-label"><?= htmlspecialchars(t($translations, 'contact_label_prenom', 'First name'), ENT_QUOTES, 'UTF-8') ?></label>
|
||||
<label class="form-label"><?php echo htmlspecialchars(t($translations, 'contact_label_prenom', 'First name'), ENT_QUOTES, 'UTF-8') ?></label>
|
||||
<input type="text" name="prenom" class="form-control"
|
||||
value="<?= htmlspecialchars($_POST['prenom'] ?? '', ENT_QUOTES, 'UTF-8') ?>" required>
|
||||
value="<?php echo htmlspecialchars($_POST['prenom'] ?? '', ENT_QUOTES, 'UTF-8') ?>" required>
|
||||
</div>
|
||||
|
||||
<div class="col-12">
|
||||
<label class="form-label"><?= htmlspecialchars(t($translations, 'contact_label_email', 'Email'), ENT_QUOTES, 'UTF-8') ?></label>
|
||||
<label class="form-label"><?php echo htmlspecialchars(t($translations, 'contact_label_email', 'Email'), ENT_QUOTES, 'UTF-8') ?></label>
|
||||
<input type="email" name="email" class="form-control" inputmode="email"
|
||||
placeholder="<?= htmlspecialchars(t($translations, 'contact_email_placeholder', 'name@example.com'), ENT_QUOTES, 'UTF-8') ?>"
|
||||
value="<?= htmlspecialchars($_POST['email'] ?? '', ENT_QUOTES, 'UTF-8') ?>" required>
|
||||
placeholder="<?php echo htmlspecialchars(t($translations, 'contact_email_placeholder', 'name@example.com'), ENT_QUOTES, 'UTF-8') ?>"
|
||||
value="<?php echo htmlspecialchars($_POST['email'] ?? '', ENT_QUOTES, 'UTF-8') ?>" required>
|
||||
</div>
|
||||
|
||||
<div class="col-12">
|
||||
<label class="form-label"><?= htmlspecialchars(t($translations, 'contact_label_sujet', 'Subject'), ENT_QUOTES, 'UTF-8') ?></label>
|
||||
<label class="form-label"><?php echo htmlspecialchars(t($translations, 'contact_label_sujet', 'Subject'), ENT_QUOTES, 'UTF-8') ?></label>
|
||||
<input type="text" name="sujet" class="form-control"
|
||||
value="<?= htmlspecialchars($_POST['sujet'] ?? '', ENT_QUOTES, 'UTF-8') ?>" required>
|
||||
value="<?php echo htmlspecialchars($_POST['sujet'] ?? '', ENT_QUOTES, 'UTF-8') ?>" required>
|
||||
</div>
|
||||
|
||||
<div class="col-12">
|
||||
<label class="form-label"><?= htmlspecialchars(t($translations, 'contact_label_message', 'Message'), ENT_QUOTES, 'UTF-8') ?></label>
|
||||
<textarea name="message" class="form-control" required><?= htmlspecialchars($_POST['message'] ?? '', ENT_QUOTES, 'UTF-8') ?></textarea>
|
||||
<label class="form-label"><?php echo htmlspecialchars(t($translations, 'contact_label_message', 'Message'), ENT_QUOTES, 'UTF-8') ?></label>
|
||||
<textarea name="message" class="form-control" required><?php echo htmlspecialchars($_POST['message'] ?? '', ENT_QUOTES, 'UTF-8') ?></textarea>
|
||||
</div>
|
||||
|
||||
<?php if ($HAS_SITE): ?>
|
||||
<div class="col-12">
|
||||
<div class="g-recaptcha" data-sitekey="<?= htmlspecialchars($RECAPTCHA_SITE_KEY, ENT_QUOTES, 'UTF-8') ?>"></div>
|
||||
<div class="g-recaptcha" data-sitekey="<?php echo htmlspecialchars($RECAPTCHA_SITE_KEY, ENT_QUOTES, 'UTF-8') ?>"></div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="col-12 d-flex justify-content-end">
|
||||
<button type="submit" class="btn btn-red">
|
||||
<?= htmlspecialchars(t($translations, 'contact_btn_submit', 'Send'), ENT_QUOTES, 'UTF-8') ?>
|
||||
<?php echo htmlspecialchars(t($translations, 'contact_btn_submit', 'Send'), ENT_QUOTES, 'UTF-8') ?>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -368,7 +412,7 @@ $langHtml = preg_match('~^[a-z]{2}(-[A-Z]{2})?$~', (string)($lang ?? '')) ? (str
|
||||
|
||||
<footer class="site-footer">
|
||||
<div class="container">
|
||||
<p><?= $translations['copyr'] ?></p>
|
||||
<p><?php echo $translations['copyr'] ?></p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
|
||||
Reference in new issue
Block a user