develop dans master - première version stable #9
develop
into master
2 years ago
@ -0,0 +1,16 @@
|
|||||||
|
FROM debian:11
|
||||||
|
RUN apt update -y && apt install -y --no-install-recommends openssl apache2 php libapache2-mod-php sqlite3 php-sqlite3 && \
|
||||||
|
apt clean && \
|
||||||
|
rm -rf /var/lib/apt/lists/* && \
|
||||||
|
mkdir -p /etc/postfix/ && \
|
||||||
|
rm /var/www/html/index.html && \
|
||||||
|
openssl req -x509 -nodes -days 5000 -newkey rsa:4096 -out /etc/ssl/certs/ssl-cert-snakeoil.pem -keyout /etc/ssl/private/ssl-cert-snakeoil.key -subj "/C=FR/ST=Paris/L=Paris/O=Courtail/OU=Courtail/CN=127.0.0.1" && \
|
||||||
|
a2enmod ssl && \
|
||||||
|
a2ensite default-ssl.conf
|
||||||
|
COPY . /var/www/html/
|
||||||
|
RUN mv /var/www/html/outils/conf/php.ini /etc/php/7.4/apache2 && \
|
||||||
|
mv /var/www/html/outils/conf/apache2.conf /etc/apache2/ && \
|
||||||
|
chmod +x /var/www/html/outils/genenv.sh && \
|
||||||
|
/var/www/html/outils/genenv.sh
|
||||||
|
|
||||||
|
CMD /usr/sbin/apachectl -D FOREGROUND
|
@ -1,3 +1,65 @@
|
|||||||
# Courtail
|
# Courtail
|
||||||
|
|
||||||
Interface WEB d'administration pour le serveur de courriel : https://doc.ycharbi.fr/index.php/Serveur_de_courriels
|
Interface WEB d'administration pour le serveur de courriel *Postfix* dont la documentation est disponible sur [doc.ycharbi.fr](https://doc.ycharbi.fr/index.php/Serveur_de_courriels).
|
||||||
|
|
||||||
|
## Fonctionnalités
|
||||||
|
|
||||||
|
L'objectif de Courtail est de permettre le paramétrage de certaines fonctionnalités de messagerie tel que :
|
||||||
|
|
||||||
|
* ajout, activation/désactivation, suppression des alias virtuels
|
||||||
|
* ajout, activation/désactivation, suppression des domaines
|
||||||
|
* ajout, activation/désactivation, suppression des adresses en liste noire
|
||||||
|
* changement de mot de passe des utilisateurs
|
||||||
|
* exportation/importation des alias virtuels d'un utilisateur
|
||||||
|
* exportation/importation des données (à la carte) du site
|
||||||
|
|
||||||
|
Deux types d'utilisateurs sont supportés et ont un accès différent à ces fonctionnalités :
|
||||||
|
|
||||||
|
* Administrateur : à accès à la totalité des fonctions du site et peut se faire passer momentanément pour un autre utilisateur afin de modifier ses paramètres sans avoir à s'y connecter
|
||||||
|
* Utilisateur : n'a accès qu'à ses propres alias virtuels. Il peux en créer, les activer/désactiver, les supprimer, les sauvegarder et les restaurer. Il ne peut également modifier que son propre mot de passe en fournissant son actuel
|
||||||
|
|
||||||
|
## Dépendances du projet
|
||||||
|
|
||||||
|
Pour Debian 11 (Bullseye) :
|
||||||
|
|
||||||
|
`apt install --no-install-recommends apache2 php php-sqlite3`
|
||||||
|
|
||||||
|
## Environnement de développement
|
||||||
|
|
||||||
|
L'outil est déployable rapidement dans un environnement de test ou via Docker.
|
||||||
|
|
||||||
|
Un schéma logique de celui-ci est disponible [ici](outils/schémas/Courtail-schéma.pdf).
|
||||||
|
|
||||||
|
### Via Docker
|
||||||
|
|
||||||
|
Après avoir dupliqué le projet, réaliser les commandes suivantes :
|
||||||
|
|
||||||
|
`bash ./outils/rundocker.sh`
|
||||||
|
|
||||||
|
La page WEB est disponible sur [http://127.0.0.1:8080](http://127.0.0.1:8080) et [https://127.0.0.1:4443](http://127.0.0.1:8080).
|
||||||
|
|
||||||
|
#### Utilisateurs par défaut
|
||||||
|
|
||||||
|
Plusieurs utilisateurs sont créés dans notre exemple :
|
||||||
|
|
||||||
|
|Utilisateurs |Mot de passe|Rôle |
|
||||||
|
|---------------|------------|--------------|
|
||||||
|
|demo@exemple.fr|demo |Administrateur|
|
||||||
|
|toto@exemple.fr|toto |Administrateur|
|
||||||
|
|tata@exemple.fr|tata |Utilisateur |
|
||||||
|
|
||||||
|
*La définition d'un domaine par défaut dans la section dédiée du site permet l'usage d'identifiants courts (demo = demo@exemple.fr).*
|
||||||
|
|
||||||
|
## Galeries
|
||||||
|
|
||||||
|
![Page de connexion](outils/galerie/courtail-galerie-1.png)
|
||||||
|
|
||||||
|
![Page gestion des alias virtuels](outils/galerie/courtail-galerie-2.png)
|
||||||
|
|
||||||
|
![Page gestion des domaines](outils/galerie/courtail-galerie-3.png)
|
||||||
|
|
||||||
|
![Page liste noire des destinataires](outils/galerie/courtail-galerie-4.png)
|
||||||
|
|
||||||
|
![Page liste noire des expéditeurs](outils/galerie/courtail-galerie-5.png)
|
||||||
|
|
||||||
|
![Page des paramètres](outils/galerie/courtail-galerie-6.png)
|
||||||
|
@ -0,0 +1,485 @@
|
|||||||
|
/*!
|
||||||
|
* Bootstrap Reboot v5.1.3 (https://getbootstrap.com/)
|
||||||
|
* Copyright 2011-2021 The Bootstrap Authors
|
||||||
|
* Copyright 2011-2021 Twitter, Inc.
|
||||||
|
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||||
|
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
|
||||||
|
*/
|
||||||
|
:root {
|
||||||
|
--bs-blue: #0d6efd;
|
||||||
|
--bs-indigo: #6610f2;
|
||||||
|
--bs-purple: #6f42c1;
|
||||||
|
--bs-pink: #d63384;
|
||||||
|
--bs-red: #dc3545;
|
||||||
|
--bs-orange: #fd7e14;
|
||||||
|
--bs-yellow: #ffc107;
|
||||||
|
--bs-green: #198754;
|
||||||
|
--bs-teal: #20c997;
|
||||||
|
--bs-cyan: #0dcaf0;
|
||||||
|
--bs-white: #fff;
|
||||||
|
--bs-gray: #6c757d;
|
||||||
|
--bs-gray-dark: #343a40;
|
||||||
|
--bs-gray-100: #f8f9fa;
|
||||||
|
--bs-gray-200: #e9ecef;
|
||||||
|
--bs-gray-300: #dee2e6;
|
||||||
|
--bs-gray-400: #ced4da;
|
||||||
|
--bs-gray-500: #adb5bd;
|
||||||
|
--bs-gray-600: #6c757d;
|
||||||
|
--bs-gray-700: #495057;
|
||||||
|
--bs-gray-800: #343a40;
|
||||||
|
--bs-gray-900: #212529;
|
||||||
|
--bs-primary: #0d6efd;
|
||||||
|
--bs-secondary: #6c757d;
|
||||||
|
--bs-success: #198754;
|
||||||
|
--bs-info: #0dcaf0;
|
||||||
|
--bs-warning: #ffc107;
|
||||||
|
--bs-danger: #dc3545;
|
||||||
|
--bs-light: #f8f9fa;
|
||||||
|
--bs-dark: #212529;
|
||||||
|
--bs-primary-rgb: 13, 110, 253;
|
||||||
|
--bs-secondary-rgb: 108, 117, 125;
|
||||||
|
--bs-success-rgb: 25, 135, 84;
|
||||||
|
--bs-info-rgb: 13, 202, 240;
|
||||||
|
--bs-warning-rgb: 255, 193, 7;
|
||||||
|
--bs-danger-rgb: 220, 53, 69;
|
||||||
|
--bs-light-rgb: 248, 249, 250;
|
||||||
|
--bs-dark-rgb: 33, 37, 41;
|
||||||
|
--bs-white-rgb: 255, 255, 255;
|
||||||
|
--bs-black-rgb: 0, 0, 0;
|
||||||
|
--bs-body-color-rgb: 33, 37, 41;
|
||||||
|
--bs-body-bg-rgb: 255, 255, 255;
|
||||||
|
--bs-font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", "Liberation Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
||||||
|
--bs-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
||||||
|
--bs-gradient: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0));
|
||||||
|
--bs-body-font-family: var(--bs-font-sans-serif);
|
||||||
|
--bs-body-font-size: 1rem;
|
||||||
|
--bs-body-font-weight: 400;
|
||||||
|
--bs-body-line-height: 1.5;
|
||||||
|
--bs-body-color: #212529;
|
||||||
|
--bs-body-bg: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
*,
|
||||||
|
*::before,
|
||||||
|
*::after {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-reduced-motion: no-preference) {
|
||||||
|
:root {
|
||||||
|
scroll-behavior: smooth;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
font-family: var(--bs-body-font-family);
|
||||||
|
font-size: var(--bs-body-font-size);
|
||||||
|
font-weight: var(--bs-body-font-weight);
|
||||||
|
line-height: var(--bs-body-line-height);
|
||||||
|
color: var(--bs-body-color);
|
||||||
|
text-align: var(--bs-body-text-align);
|
||||||
|
background-color: var(--bs-body-bg);
|
||||||
|
-webkit-text-size-adjust: 100%;
|
||||||
|
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
margin: 1rem 0;
|
||||||
|
color: inherit;
|
||||||
|
background-color: currentColor;
|
||||||
|
border: 0;
|
||||||
|
opacity: 0.25;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr:not([size]) {
|
||||||
|
height: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h6, h5, h4, h3, h2, h1 {
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
font-weight: 500;
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: calc(1.375rem + 1.5vw);
|
||||||
|
}
|
||||||
|
@media (min-width: 1200px) {
|
||||||
|
h1 {
|
||||||
|
font-size: 2.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: calc(1.325rem + 0.9vw);
|
||||||
|
}
|
||||||
|
@media (min-width: 1200px) {
|
||||||
|
h2 {
|
||||||
|
font-size: 2rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: calc(1.3rem + 0.6vw);
|
||||||
|
}
|
||||||
|
@media (min-width: 1200px) {
|
||||||
|
h3 {
|
||||||
|
font-size: 1.75rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
h4 {
|
||||||
|
font-size: calc(1.275rem + 0.3vw);
|
||||||
|
}
|
||||||
|
@media (min-width: 1200px) {
|
||||||
|
h4 {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
h5 {
|
||||||
|
font-size: 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h6 {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
abbr[title],
|
||||||
|
abbr[data-bs-original-title] {
|
||||||
|
-webkit-text-decoration: underline dotted;
|
||||||
|
text-decoration: underline dotted;
|
||||||
|
cursor: help;
|
||||||
|
-webkit-text-decoration-skip-ink: none;
|
||||||
|
text-decoration-skip-ink: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
address {
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
font-style: normal;
|
||||||
|
line-height: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
ol,
|
||||||
|
ul {
|
||||||
|
padding-left: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
ol,
|
||||||
|
ul,
|
||||||
|
dl {
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
ol ol,
|
||||||
|
ul ul,
|
||||||
|
ol ul,
|
||||||
|
ul ol {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
dt {
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
dd {
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote {
|
||||||
|
margin: 0 0 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
b,
|
||||||
|
strong {
|
||||||
|
font-weight: bolder;
|
||||||
|
}
|
||||||
|
|
||||||
|
small {
|
||||||
|
font-size: 0.875em;
|
||||||
|
}
|
||||||
|
|
||||||
|
mark {
|
||||||
|
padding: 0.2em;
|
||||||
|
background-color: #fcf8e3;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub,
|
||||||
|
sup {
|
||||||
|
position: relative;
|
||||||
|
font-size: 0.75em;
|
||||||
|
line-height: 0;
|
||||||
|
vertical-align: baseline;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub {
|
||||||
|
bottom: -0.25em;
|
||||||
|
}
|
||||||
|
|
||||||
|
sup {
|
||||||
|
top: -0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #0d6efd;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
a:hover {
|
||||||
|
color: #0a58ca;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:not([href]):not([class]), a:not([href]):not([class]):hover {
|
||||||
|
color: inherit;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre,
|
||||||
|
code,
|
||||||
|
kbd,
|
||||||
|
samp {
|
||||||
|
font-family: var(--bs-font-monospace);
|
||||||
|
font-size: 1em;
|
||||||
|
direction: ltr /* rtl:ignore */;
|
||||||
|
unicode-bidi: bidi-override;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
display: block;
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
overflow: auto;
|
||||||
|
font-size: 0.875em;
|
||||||
|
}
|
||||||
|
pre code {
|
||||||
|
font-size: inherit;
|
||||||
|
color: inherit;
|
||||||
|
word-break: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
code {
|
||||||
|
font-size: 0.875em;
|
||||||
|
color: #d63384;
|
||||||
|
word-wrap: break-word;
|
||||||
|
}
|
||||||
|
a > code {
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
kbd {
|
||||||
|
padding: 0.2rem 0.4rem;
|
||||||
|
font-size: 0.875em;
|
||||||
|
color: #fff;
|
||||||
|
background-color: #212529;
|
||||||
|
border-radius: 0.2rem;
|
||||||
|
}
|
||||||
|
kbd kbd {
|
||||||
|
padding: 0;
|
||||||
|
font-size: 1em;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
figure {
|
||||||
|
margin: 0 0 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
img,
|
||||||
|
svg {
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
caption-side: bottom;
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
|
|
||||||
|
caption {
|
||||||
|
padding-top: 0.5rem;
|
||||||
|
padding-bottom: 0.5rem;
|
||||||
|
color: #6c757d;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
th {
|
||||||
|
text-align: inherit;
|
||||||
|
text-align: -webkit-match-parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
thead,
|
||||||
|
tbody,
|
||||||
|
tfoot,
|
||||||
|
tr,
|
||||||
|
td,
|
||||||
|
th {
|
||||||
|
border-color: inherit;
|
||||||
|
border-style: solid;
|
||||||
|
border-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
button:focus:not(:focus-visible) {
|
||||||
|
outline: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
input,
|
||||||
|
button,
|
||||||
|
select,
|
||||||
|
optgroup,
|
||||||
|
textarea {
|
||||||
|
margin: 0;
|
||||||
|
font-family: inherit;
|
||||||
|
font-size: inherit;
|
||||||
|
line-height: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
button,
|
||||||
|
select {
|
||||||
|
text-transform: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
[role=button] {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
word-wrap: normal;
|
||||||
|
}
|
||||||
|
select:disabled {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
[list]::-webkit-calendar-picker-indicator {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
button,
|
||||||
|
[type=button],
|
||||||
|
[type=reset],
|
||||||
|
[type=submit] {
|
||||||
|
-webkit-appearance: button;
|
||||||
|
}
|
||||||
|
button:not(:disabled),
|
||||||
|
[type=button]:not(:disabled),
|
||||||
|
[type=reset]:not(:disabled),
|
||||||
|
[type=submit]:not(:disabled) {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-moz-focus-inner {
|
||||||
|
padding: 0;
|
||||||
|
border-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
textarea {
|
||||||
|
resize: vertical;
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldset {
|
||||||
|
min-width: 0;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
legend {
|
||||||
|
float: left;
|
||||||
|
width: 100%;
|
||||||
|
padding: 0;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
font-size: calc(1.275rem + 0.3vw);
|
||||||
|
line-height: inherit;
|
||||||
|
}
|
||||||
|
@media (min-width: 1200px) {
|
||||||
|
legend {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
legend + * {
|
||||||
|
clear: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-datetime-edit-fields-wrapper,
|
||||||
|
::-webkit-datetime-edit-text,
|
||||||
|
::-webkit-datetime-edit-minute,
|
||||||
|
::-webkit-datetime-edit-hour-field,
|
||||||
|
::-webkit-datetime-edit-day-field,
|
||||||
|
::-webkit-datetime-edit-month-field,
|
||||||
|
::-webkit-datetime-edit-year-field {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-inner-spin-button {
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
[type=search] {
|
||||||
|
outline-offset: -2px;
|
||||||
|
-webkit-appearance: textfield;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* rtl:raw:
|
||||||
|
[type="tel"],
|
||||||
|
[type="url"],
|
||||||
|
[type="email"],
|
||||||
|
[type="number"] {
|
||||||
|
direction: ltr;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
::-webkit-search-decoration {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-color-swatch-wrapper {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-file-upload-button {
|
||||||
|
font: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
::file-selector-button {
|
||||||
|
font: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-file-upload-button {
|
||||||
|
font: inherit;
|
||||||
|
-webkit-appearance: button;
|
||||||
|
}
|
||||||
|
|
||||||
|
output {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
iframe {
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
summary {
|
||||||
|
display: list-item;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
progress {
|
||||||
|
vertical-align: baseline;
|
||||||
|
}
|
||||||
|
|
||||||
|
[hidden] {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*# sourceMappingURL=bootstrap-reboot.css.map */
|
@ -0,0 +1,482 @@
|
|||||||
|
/*!
|
||||||
|
* Bootstrap Reboot v5.1.3 (https://getbootstrap.com/)
|
||||||
|
* Copyright 2011-2021 The Bootstrap Authors
|
||||||
|
* Copyright 2011-2021 Twitter, Inc.
|
||||||
|
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||||
|
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
|
||||||
|
*/
|
||||||
|
:root {
|
||||||
|
--bs-blue: #0d6efd;
|
||||||
|
--bs-indigo: #6610f2;
|
||||||
|
--bs-purple: #6f42c1;
|
||||||
|
--bs-pink: #d63384;
|
||||||
|
--bs-red: #dc3545;
|
||||||
|
--bs-orange: #fd7e14;
|
||||||
|
--bs-yellow: #ffc107;
|
||||||
|
--bs-green: #198754;
|
||||||
|
--bs-teal: #20c997;
|
||||||
|
--bs-cyan: #0dcaf0;
|
||||||
|
--bs-white: #fff;
|
||||||
|
--bs-gray: #6c757d;
|
||||||
|
--bs-gray-dark: #343a40;
|
||||||
|
--bs-gray-100: #f8f9fa;
|
||||||
|
--bs-gray-200: #e9ecef;
|
||||||
|
--bs-gray-300: #dee2e6;
|
||||||
|
--bs-gray-400: #ced4da;
|
||||||
|
--bs-gray-500: #adb5bd;
|
||||||
|
--bs-gray-600: #6c757d;
|
||||||
|
--bs-gray-700: #495057;
|
||||||
|
--bs-gray-800: #343a40;
|
||||||
|
--bs-gray-900: #212529;
|
||||||
|
--bs-primary: #0d6efd;
|
||||||
|
--bs-secondary: #6c757d;
|
||||||
|
--bs-success: #198754;
|
||||||
|
--bs-info: #0dcaf0;
|
||||||
|
--bs-warning: #ffc107;
|
||||||
|
--bs-danger: #dc3545;
|
||||||
|
--bs-light: #f8f9fa;
|
||||||
|
--bs-dark: #212529;
|
||||||
|
--bs-primary-rgb: 13, 110, 253;
|
||||||
|
--bs-secondary-rgb: 108, 117, 125;
|
||||||
|
--bs-success-rgb: 25, 135, 84;
|
||||||
|
--bs-info-rgb: 13, 202, 240;
|
||||||
|
--bs-warning-rgb: 255, 193, 7;
|
||||||
|
--bs-danger-rgb: 220, 53, 69;
|
||||||
|
--bs-light-rgb: 248, 249, 250;
|
||||||
|
--bs-dark-rgb: 33, 37, 41;
|
||||||
|
--bs-white-rgb: 255, 255, 255;
|
||||||
|
--bs-black-rgb: 0, 0, 0;
|
||||||
|
--bs-body-color-rgb: 33, 37, 41;
|
||||||
|
--bs-body-bg-rgb: 255, 255, 255;
|
||||||
|
--bs-font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", "Liberation Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
||||||
|
--bs-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
||||||
|
--bs-gradient: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0));
|
||||||
|
--bs-body-font-family: var(--bs-font-sans-serif);
|
||||||
|
--bs-body-font-size: 1rem;
|
||||||
|
--bs-body-font-weight: 400;
|
||||||
|
--bs-body-line-height: 1.5;
|
||||||
|
--bs-body-color: #212529;
|
||||||
|
--bs-body-bg: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
*,
|
||||||
|
*::before,
|
||||||
|
*::after {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-reduced-motion: no-preference) {
|
||||||
|
:root {
|
||||||
|
scroll-behavior: smooth;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
font-family: var(--bs-body-font-family);
|
||||||
|
font-size: var(--bs-body-font-size);
|
||||||
|
font-weight: var(--bs-body-font-weight);
|
||||||
|
line-height: var(--bs-body-line-height);
|
||||||
|
color: var(--bs-body-color);
|
||||||
|
text-align: var(--bs-body-text-align);
|
||||||
|
background-color: var(--bs-body-bg);
|
||||||
|
-webkit-text-size-adjust: 100%;
|
||||||
|
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
margin: 1rem 0;
|
||||||
|
color: inherit;
|
||||||
|
background-color: currentColor;
|
||||||
|
border: 0;
|
||||||
|
opacity: 0.25;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr:not([size]) {
|
||||||
|
height: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h6, h5, h4, h3, h2, h1 {
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
font-weight: 500;
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: calc(1.375rem + 1.5vw);
|
||||||
|
}
|
||||||
|
@media (min-width: 1200px) {
|
||||||
|
h1 {
|
||||||
|
font-size: 2.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: calc(1.325rem + 0.9vw);
|
||||||
|
}
|
||||||
|
@media (min-width: 1200px) {
|
||||||
|
h2 {
|
||||||
|
font-size: 2rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: calc(1.3rem + 0.6vw);
|
||||||
|
}
|
||||||
|
@media (min-width: 1200px) {
|
||||||
|
h3 {
|
||||||
|
font-size: 1.75rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
h4 {
|
||||||
|
font-size: calc(1.275rem + 0.3vw);
|
||||||
|
}
|
||||||
|
@media (min-width: 1200px) {
|
||||||
|
h4 {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
h5 {
|
||||||
|
font-size: 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h6 {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
abbr[title],
|
||||||
|
abbr[data-bs-original-title] {
|
||||||
|
-webkit-text-decoration: underline dotted;
|
||||||
|
text-decoration: underline dotted;
|
||||||
|
cursor: help;
|
||||||
|
-webkit-text-decoration-skip-ink: none;
|
||||||
|
text-decoration-skip-ink: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
address {
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
font-style: normal;
|
||||||
|
line-height: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
ol,
|
||||||
|
ul {
|
||||||
|
padding-right: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
ol,
|
||||||
|
ul,
|
||||||
|
dl {
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
ol ol,
|
||||||
|
ul ul,
|
||||||
|
ol ul,
|
||||||
|
ul ol {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
dt {
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
dd {
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote {
|
||||||
|
margin: 0 0 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
b,
|
||||||
|
strong {
|
||||||
|
font-weight: bolder;
|
||||||
|
}
|
||||||
|
|
||||||
|
small {
|
||||||
|
font-size: 0.875em;
|
||||||
|
}
|
||||||
|
|
||||||
|
mark {
|
||||||
|
padding: 0.2em;
|
||||||
|
background-color: #fcf8e3;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub,
|
||||||
|
sup {
|
||||||
|
position: relative;
|
||||||
|
font-size: 0.75em;
|
||||||
|
line-height: 0;
|
||||||
|
vertical-align: baseline;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub {
|
||||||
|
bottom: -0.25em;
|
||||||
|
}
|
||||||
|
|
||||||
|
sup {
|
||||||
|
top: -0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #0d6efd;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
a:hover {
|
||||||
|
color: #0a58ca;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:not([href]):not([class]), a:not([href]):not([class]):hover {
|
||||||
|
color: inherit;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre,
|
||||||
|
code,
|
||||||
|
kbd,
|
||||||
|
samp {
|
||||||
|
font-family: var(--bs-font-monospace);
|
||||||
|
font-size: 1em;
|
||||||
|
direction: ltr ;
|
||||||
|
unicode-bidi: bidi-override;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
display: block;
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
overflow: auto;
|
||||||
|
font-size: 0.875em;
|
||||||
|
}
|
||||||
|
pre code {
|
||||||
|
font-size: inherit;
|
||||||
|
color: inherit;
|
||||||
|
word-break: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
code {
|
||||||
|
font-size: 0.875em;
|
||||||
|
color: #d63384;
|
||||||
|
word-wrap: break-word;
|
||||||
|
}
|
||||||
|
a > code {
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
kbd {
|
||||||
|
padding: 0.2rem 0.4rem;
|
||||||
|
font-size: 0.875em;
|
||||||
|
color: #fff;
|
||||||
|
background-color: #212529;
|
||||||
|
border-radius: 0.2rem;
|
||||||
|
}
|
||||||
|
kbd kbd {
|
||||||
|
padding: 0;
|
||||||
|
font-size: 1em;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
figure {
|
||||||
|
margin: 0 0 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
img,
|
||||||
|
svg {
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
caption-side: bottom;
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
|
|
||||||
|
caption {
|
||||||
|
padding-top: 0.5rem;
|
||||||
|
padding-bottom: 0.5rem;
|
||||||
|
color: #6c757d;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
th {
|
||||||
|
text-align: inherit;
|
||||||
|
text-align: -webkit-match-parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
thead,
|
||||||
|
tbody,
|
||||||
|
tfoot,
|
||||||
|
tr,
|
||||||
|
td,
|
||||||
|
th {
|
||||||
|
border-color: inherit;
|
||||||
|
border-style: solid;
|
||||||
|
border-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
button:focus:not(:focus-visible) {
|
||||||
|
outline: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
input,
|
||||||
|
button,
|
||||||
|
select,
|
||||||
|
optgroup,
|
||||||
|
textarea {
|
||||||
|
margin: 0;
|
||||||
|
font-family: inherit;
|
||||||
|
font-size: inherit;
|
||||||
|
line-height: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
button,
|
||||||
|
select {
|
||||||
|
text-transform: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
[role=button] {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
word-wrap: normal;
|
||||||
|
}
|
||||||
|
select:disabled {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
[list]::-webkit-calendar-picker-indicator {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
button,
|
||||||
|
[type=button],
|
||||||
|
[type=reset],
|
||||||
|
[type=submit] {
|
||||||
|
-webkit-appearance: button;
|
||||||
|
}
|
||||||
|
button:not(:disabled),
|
||||||
|
[type=button]:not(:disabled),
|
||||||
|
[type=reset]:not(:disabled),
|
||||||
|
[type=submit]:not(:disabled) {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-moz-focus-inner {
|
||||||
|
padding: 0;
|
||||||
|
border-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
textarea {
|
||||||
|
resize: vertical;
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldset {
|
||||||
|
min-width: 0;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
legend {
|
||||||
|
float: right;
|
||||||
|
width: 100%;
|
||||||
|
padding: 0;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
font-size: calc(1.275rem + 0.3vw);
|
||||||
|
line-height: inherit;
|
||||||
|
}
|
||||||
|
@media (min-width: 1200px) {
|
||||||
|
legend {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
legend + * {
|
||||||
|
clear: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-datetime-edit-fields-wrapper,
|
||||||
|
::-webkit-datetime-edit-text,
|
||||||
|
::-webkit-datetime-edit-minute,
|
||||||
|
::-webkit-datetime-edit-hour-field,
|
||||||
|
::-webkit-datetime-edit-day-field,
|
||||||
|
::-webkit-datetime-edit-month-field,
|
||||||
|
::-webkit-datetime-edit-year-field {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-inner-spin-button {
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
[type=search] {
|
||||||
|
outline-offset: -2px;
|
||||||
|
-webkit-appearance: textfield;
|
||||||
|
}
|
||||||
|
|
||||||
|
[type="tel"],
|
||||||
|
[type="url"],
|
||||||
|
[type="email"],
|
||||||
|
[type="number"] {
|
||||||
|
direction: ltr;
|
||||||
|
}
|
||||||
|
::-webkit-search-decoration {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-color-swatch-wrapper {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-file-upload-button {
|
||||||
|
font: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
::file-selector-button {
|
||||||
|
font: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-file-upload-button {
|
||||||
|
font: inherit;
|
||||||
|
-webkit-appearance: button;
|
||||||
|
}
|
||||||
|
|
||||||
|
output {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
iframe {
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
summary {
|
||||||
|
display: list-item;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
progress {
|
||||||
|
vertical-align: baseline;
|
||||||
|
}
|
||||||
|
|
||||||
|
[hidden] {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
/*# sourceMappingURL=bootstrap-reboot.rtl.css.map */
|
@ -0,0 +1,36 @@
|
|||||||
|
/* Style concernant la confirmation de suppression d'un alias virtuel */
|
||||||
|
.confirmation-suppression {
|
||||||
|
display: none;
|
||||||
|
color: #fff;
|
||||||
|
text-align: center;
|
||||||
|
text-decoration: none;
|
||||||
|
background-color: #dc3545;
|
||||||
|
}
|
||||||
|
|
||||||
|
.confirmation-suppression:hover {
|
||||||
|
color: #fff;
|
||||||
|
background-color: #bb2d3b;
|
||||||
|
border-color: #b02a37;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-checkbox-supprimer-valeur:checked ~ .confirmation-suppression {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*.input-label-supprimer-valeur {
|
||||||
|
color: #ffffff;
|
||||||
|
background: #e23026;
|
||||||
|
padding: 0.5rem 1rem;
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
.visuellement-cache {
|
||||||
|
position: absolute;
|
||||||
|
left: -100vw;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sources :
|
||||||
|
* https://stackoverflow.com/questions/6019845/show-hide-div-on-click-with-css
|
||||||
|
* https://dabblet.com/gist/1506530
|
||||||
|
* https://css-tricks.com/the-checkbox-hack/
|
||||||
|
*/
|
@ -0,0 +1,49 @@
|
|||||||
|
.champ-interrupteur {
|
||||||
|
display: flex;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.champ-interrupteur input {
|
||||||
|
position: absolute !important;
|
||||||
|
clip: rect(0, 0, 0, 0);
|
||||||
|
height: 1px;
|
||||||
|
width: 1px;
|
||||||
|
border: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.champ-interrupteur label {
|
||||||
|
background-color: #e4e4e4;
|
||||||
|
border: 1px solid rgba(0, 0, 0, 0.2);
|
||||||
|
box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.3), 0 1px rgba(255, 255, 255, 0.1);
|
||||||
|
transition: all 0.1s ease-in-out;
|
||||||
|
width: 38px;
|
||||||
|
height: 34px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.champ-interrupteur label:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.champ-interrupteur input:checked + .interrupteur-allumer {
|
||||||
|
background-color: #0d6efd;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.champ-interrupteur input:checked + .interrupteur-eteint {
|
||||||
|
background-color: #dc3545;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.champ-interrupteur label:first-of-type {
|
||||||
|
border-radius: 4px 0 0 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.champ-interrupteur label:last-of-type {
|
||||||
|
border-radius: 0 4px 4px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.champ-interrupteur.disabled {
|
||||||
|
pointer-events: none;
|
||||||
|
opacity: .65;
|
||||||
|
}
|
@ -0,0 +1,115 @@
|
|||||||
|
body {
|
||||||
|
background-color: #f8f9fa;
|
||||||
|
margin-bottom: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#contenu_auth {
|
||||||
|
max-width: 380px;
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
#contenu_auth #envoyer {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#logo-accueil {
|
||||||
|
text-align: center;
|
||||||
|
margin: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#logo-accueil img {
|
||||||
|
width: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#logo-accueil h1 {
|
||||||
|
color: #FFF;
|
||||||
|
font-size: 40pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert img {
|
||||||
|
height: 1.5em;
|
||||||
|
margin-right: 0.3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert {
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bouton-flotant {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 20px;
|
||||||
|
right: 20px;
|
||||||
|
background-color: #0d6efd;
|
||||||
|
color: white;
|
||||||
|
border-radius: 50%;
|
||||||
|
width: 60px;
|
||||||
|
height: 60px;
|
||||||
|
border: 2px solid #0d6efd;
|
||||||
|
animation-name: zoom;
|
||||||
|
animation-duration: .2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes zoom {
|
||||||
|
0% {
|
||||||
|
transform: scale(0, 0);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: scale(1, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes dezoom {
|
||||||
|
0% {
|
||||||
|
transform: scale(1, 1);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: scale(0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.bouton-flotant.desactiver{
|
||||||
|
animation-name: dezoom;
|
||||||
|
animation-duration: .2s;
|
||||||
|
animation-fill-mode: forwards;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contour-pastille {
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.interieur-pastille {
|
||||||
|
margin: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.titre-pastille {
|
||||||
|
width: calc(100% - 122px);
|
||||||
|
text-align: center;
|
||||||
|
padding-top: 4px;
|
||||||
|
padding-left: 10px;
|
||||||
|
padding-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bouton-ajout{
|
||||||
|
padding: .375rem .475rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.interieur-pastille-bleu {
|
||||||
|
background-color: #cfe2ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chevron-dst {
|
||||||
|
height: 1em;
|
||||||
|
padding-bottom: 0.1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fond-arc-noire{
|
||||||
|
background-color: #343a40;
|
||||||
|
}
|
||||||
|
|
||||||
|
.max-hauteur-pastille{
|
||||||
|
height: calc(100% - 1.5em);
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* Page de fonctions JavaScript afférentes aux filtres de chaînes de carractères.
|
||||||
|
**/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fonction permettant de filtrer la liste des alias virtuels d'un utilisateur au file des caractères entrés dans le formulaire de création idoine.
|
||||||
|
**/
|
||||||
|
function filtreValeurs() {
|
||||||
|
// Déclaration des variables
|
||||||
|
var input, filter, divgroupe, divunitaire, a, i, txtValue;
|
||||||
|
input = document.getElementById('nom_pour_filtre');
|
||||||
|
filter = input.value.toUpperCase();
|
||||||
|
divgroupe = document.getElementById("liste_pour_filtre");
|
||||||
|
divunitaire = divgroupe.getElementsByClassName('col-md-6');
|
||||||
|
|
||||||
|
// Pour chaque "divunitaire", comparer le contenu (actualisé à chaque frappe) du "<input>" "nom_alias" avec le texte du "<p>" qu'il contient
|
||||||
|
// Si le contenu du champ de texte est vide, n'en masquer aucun. Si le motif correspond, masquer les autres
|
||||||
|
for (i = 0; i < divunitaire.length; i++) {
|
||||||
|
a = divunitaire[i].getElementsByTagName("span")[0];
|
||||||
|
txtValue = a.textContent || a.innerText;
|
||||||
|
if (txtValue.toUpperCase().indexOf(filter) > -1) {
|
||||||
|
divunitaire[i].style.display = "";
|
||||||
|
} else {
|
||||||
|
divunitaire[i].style.display = "none";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fonction permettant de valider (soumettre le formulaire) le choix de l'utilisateur pour en administrer les possessions.
|
||||||
|
**/
|
||||||
|
function autoSoumission() {
|
||||||
|
document.getElementById("form_choix_utilisateur").submit();
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* Page de fonctions JavaScript afférentes à l'affichage dynamique d'éléments.
|
||||||
|
**/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fonction permettant d'afficher et de masquer le bouton d'enregistrement d'un changement d'état pour les alias virtuels, domaines et entrées de liste noire d'un utilisateur.
|
||||||
|
**/
|
||||||
|
function activationBoutonFlotant(lui) {
|
||||||
|
const listedesentrees = [];
|
||||||
|
if (listedesentrees.find(function(valeur) {return valeur == lui.name;})) {
|
||||||
|
for( var i = 0; i < listedesentrees.length; i++){
|
||||||
|
if ( listedesentrees[i] === lui.name) {
|
||||||
|
listedesentrees.splice(i, 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
listedesentrees.push(lui.name);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (listedesentrees.length > 0){
|
||||||
|
document.getElementById("enregistrer-interrupteur").classList.remove("desactiver");
|
||||||
|
document.getElementById("enregistrer-interrupteur").style.display = "block";
|
||||||
|
}else{
|
||||||
|
document.getElementById("enregistrer-interrupteur").classList.add("desactiver");
|
||||||
|
}
|
||||||
|
}
|
After Width: | Height: | Size: 419 B |
After Width: | Height: | Size: 419 B |
After Width: | Height: | Size: 323 B |
After Width: | Height: | Size: 270 B |
After Width: | Height: | Size: 318 B |
After Width: | Height: | Size: 357 B |
After Width: | Height: | Size: 435 B |
After Width: | Height: | Size: 342 B |
After Width: | Height: | Size: 371 B |
After Width: | Height: | Size: 354 B |
After Width: | Height: | Size: 296 B |
After Width: | Height: | Size: 384 B |
After Width: | Height: | Size: 309 B |
After Width: | Height: | Size: 440 B |
@ -0,0 +1,60 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Page importé intégrant le menu de navigation dans la page d'administration centrale.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (isset($_GET['page']) && !empty($_GET['page'])) {
|
||||||
|
?>
|
||||||
|
|
||||||
|
<nav class="navbar navbar-expand-lg navbar-dark fond-arc-noire">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<a class="navbar-brand" href="/pages/gestion/administration.php?page=accueil"><img src="/fichiers/svg/send.svg" alt="" width="24" class="d-inline-block line-text-top me-1">Courtail</a>
|
||||||
|
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
|
||||||
|
<span class="navbar-toggler-icon"></span>
|
||||||
|
</button>
|
||||||
|
<div class="collapse navbar-collapse" id="navbarNav">
|
||||||
|
<ul class="navbar-nav">
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link <?php if ($_GET['page'] == 'accueil' || $_GET['page'] == 'alias') {echo 'active';} ?>" href="/pages/gestion/administration.php?page=alias">Alias</a>
|
||||||
|
</li>
|
||||||
|
<?php if (testPrivileges()=="administrateur") { ?>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link <?php if ($_GET['page'] == 'domaines') {echo 'active';} ?>" href="/pages/gestion/administration.php?page=domaines">Domaines</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item dropdown">
|
||||||
|
<a class="nav-link dropdown-toggle <?php if ($_GET['sousPage'] == 'destinataires' || $_GET['sousPage'] == 'expediteurs') {echo 'active';} ?>" href="/pages/gestion/administration.php?page=listes_noires&sousPage=destinataires" id="navbarDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||||
|
Listes noires
|
||||||
|
</a>
|
||||||
|
<ul class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||||
|
<li><a class="dropdown-item" href="/pages/gestion/administration.php?page=listes_noires&sousPage=destinataires">Destinataires</a></li>
|
||||||
|
<li><a class="dropdown-item" href="/pages/gestion/administration.php?page=listes_noires&sousPage=expediteurs">Expéditeurs</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<?php } ?>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="collapse navbar-collapse" id="navbarNav">
|
||||||
|
<ul class="navbar-nav ms-auto">
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link <?php if ($_GET['page'] == 'parametres') {echo 'active';} ?>" href="/pages/gestion/administration.php?page=parametres">Paramètres</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="/services/traitements/utilisateurs/deconnexion.php">Déconnexion</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<?php
|
||||||
|
}
|
||||||
|
|
||||||
|
/*if (isset($_GET['message']) && !empty($_GET['message'])) {
|
||||||
|
switch ($_GET['message']) {
|
||||||
|
case "bienvenue":
|
||||||
|
echo "<div class=\"alert alert-success\" role=\"alert\">Bienvenue ".$_SESSION['nom_utilisateur'].". Vous êtes authentifié en tant qu'".$_SESSION['privilege_utilisateur'].".</div>";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
|
?>
|
@ -0,0 +1,13 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="fr">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title>Courtail - Portail des courriels</title>
|
||||||
|
<link href="/fichiers/css/bootstrap.min.css" rel="stylesheet">
|
||||||
|
<link href="/fichiers/css/confirmation.css" rel="stylesheet">
|
||||||
|
<link href="/fichiers/css/personalisation.css" rel="stylesheet">
|
||||||
|
<link href="/fichiers/css/interrupteurs.css" rel="stylesheet">
|
||||||
|
<link rel="icon" href="/fichiers/svg/favicon.svg" />
|
||||||
|
</head>
|
||||||
|
<body>
|
@ -0,0 +1,4 @@
|
|||||||
|
<script src="/fichiers/js/bootstrap.bundle.min.js"></script>
|
||||||
|
<script src="/fichiers/js/formulaire.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,11 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Page par défaut du serveur WEB.
|
||||||
|
* Redirige automatiquement le visiteur sur la page d'accueil.
|
||||||
|
* Cette redirection permet d'ajuster la page de destination sans toucher à la configuration du serveur.
|
||||||
|
*/
|
||||||
|
|
||||||
|
header('Location: /pages/visiteurs/formulaire_accueil.php');
|
||||||
|
|
||||||
|
?>
|
@ -0,0 +1,4 @@
|
|||||||
|
Deny from all
|
||||||
|
<IfModule mod_autoindex.c>
|
||||||
|
Options -Indexes
|
||||||
|
</ifModule>
|
@ -0,0 +1,227 @@
|
|||||||
|
# This is the main Apache server configuration file. It contains the
|
||||||
|
# configuration directives that give the server its instructions.
|
||||||
|
# See http://httpd.apache.org/docs/2.4/ for detailed information about
|
||||||
|
# the directives and /usr/share/doc/apache2/README.Debian about Debian specific
|
||||||
|
# hints.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# Summary of how the Apache 2 configuration works in Debian:
|
||||||
|
# The Apache 2 web server configuration in Debian is quite different to
|
||||||
|
# upstream's suggested way to configure the web server. This is because Debian's
|
||||||
|
# default Apache2 installation attempts to make adding and removing modules,
|
||||||
|
# virtual hosts, and extra configuration directives as flexible as possible, in
|
||||||
|
# order to make automating the changes and administering the server as easy as
|
||||||
|
# possible.
|
||||||
|
|
||||||
|
# It is split into several files forming the configuration hierarchy outlined
|
||||||
|
# below, all located in the /etc/apache2/ directory:
|
||||||
|
#
|
||||||
|
# /etc/apache2/
|
||||||
|
# |-- apache2.conf
|
||||||
|
# | `-- ports.conf
|
||||||
|
# |-- mods-enabled
|
||||||
|
# | |-- *.load
|
||||||
|
# | `-- *.conf
|
||||||
|
# |-- conf-enabled
|
||||||
|
# | `-- *.conf
|
||||||
|
# `-- sites-enabled
|
||||||
|
# `-- *.conf
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# * apache2.conf is the main configuration file (this file). It puts the pieces
|
||||||
|
# together by including all remaining configuration files when starting up the
|
||||||
|
# web server.
|
||||||
|
#
|
||||||
|
# * ports.conf is always included from the main configuration file. It is
|
||||||
|
# supposed to determine listening ports for incoming connections which can be
|
||||||
|
# customized anytime.
|
||||||
|
#
|
||||||
|
# * Configuration files in the mods-enabled/, conf-enabled/ and sites-enabled/
|
||||||
|
# directories contain particular configuration snippets which manage modules,
|
||||||
|
# global configuration fragments, or virtual host configurations,
|
||||||
|
# respectively.
|
||||||
|
#
|
||||||
|
# They are activated by symlinking available configuration files from their
|
||||||
|
# respective *-available/ counterparts. These should be managed by using our
|
||||||
|
# helpers a2enmod/a2dismod, a2ensite/a2dissite and a2enconf/a2disconf. See
|
||||||
|
# their respective man pages for detailed information.
|
||||||
|
#
|
||||||
|
# * The binary is called apache2. Due to the use of environment variables, in
|
||||||
|
# the default configuration, apache2 needs to be started/stopped with
|
||||||
|
# /etc/init.d/apache2 or apache2ctl. Calling /usr/bin/apache2 directly will not
|
||||||
|
# work with the default configuration.
|
||||||
|
|
||||||
|
|
||||||
|
# Global configuration
|
||||||
|
#
|
||||||
|
|
||||||
|
#
|
||||||
|
# ServerRoot: The top of the directory tree under which the server's
|
||||||
|
# configuration, error, and log files are kept.
|
||||||
|
#
|
||||||
|
# NOTE! If you intend to place this on an NFS (or otherwise network)
|
||||||
|
# mounted filesystem then please read the Mutex documentation (available
|
||||||
|
# at <URL:http://httpd.apache.org/docs/2.4/mod/core.html#mutex>);
|
||||||
|
# you will save yourself a lot of trouble.
|
||||||
|
#
|
||||||
|
# Do NOT add a slash at the end of the directory path.
|
||||||
|
#
|
||||||
|
#ServerRoot "/etc/apache2"
|
||||||
|
|
||||||
|
#
|
||||||
|
# The accept serialization lock file MUST BE STORED ON A LOCAL DISK.
|
||||||
|
#
|
||||||
|
#Mutex file:${APACHE_LOCK_DIR} default
|
||||||
|
|
||||||
|
#
|
||||||
|
# The directory where shm and other runtime files will be stored.
|
||||||
|
#
|
||||||
|
|
||||||
|
DefaultRuntimeDir ${APACHE_RUN_DIR}
|
||||||
|
|
||||||
|
#
|
||||||
|
# PidFile: The file in which the server should record its process
|
||||||
|
# identification number when it starts.
|
||||||
|
# This needs to be set in /etc/apache2/envvars
|
||||||
|
#
|
||||||
|
PidFile ${APACHE_PID_FILE}
|
||||||
|
|
||||||
|
#
|
||||||
|
# Timeout: The number of seconds before receives and sends time out.
|
||||||
|
#
|
||||||
|
Timeout 300
|
||||||
|
|
||||||
|
#
|
||||||
|
# KeepAlive: Whether or not to allow persistent connections (more than
|
||||||
|
# one request per connection). Set to "Off" to deactivate.
|
||||||
|
#
|
||||||
|
KeepAlive On
|
||||||
|
|
||||||
|
#
|
||||||
|
# MaxKeepAliveRequests: The maximum number of requests to allow
|
||||||
|
# during a persistent connection. Set to 0 to allow an unlimited amount.
|
||||||
|
# We recommend you leave this number high, for maximum performance.
|
||||||
|
#
|
||||||
|
MaxKeepAliveRequests 100
|
||||||
|
|
||||||
|
#
|
||||||
|
# KeepAliveTimeout: Number of seconds to wait for the next request from the
|
||||||
|
# same client on the same connection.
|
||||||
|
#
|
||||||
|
KeepAliveTimeout 5
|
||||||
|
|
||||||
|
|
||||||
|
# These need to be set in /etc/apache2/envvars
|
||||||
|
User ${APACHE_RUN_USER}
|
||||||
|
Group ${APACHE_RUN_GROUP}
|
||||||
|
|
||||||
|
#
|
||||||
|
# HostnameLookups: Log the names of clients or just their IP addresses
|
||||||
|
# e.g., www.apache.org (on) or 204.62.129.132 (off).
|
||||||
|
# The default is off because it'd be overall better for the net if people
|
||||||
|
# had to knowingly turn this feature on, since enabling it means that
|
||||||
|
# each client request will result in AT LEAST one lookup request to the
|
||||||
|
# nameserver.
|
||||||
|
#
|
||||||
|
HostnameLookups Off
|
||||||
|
|
||||||
|
# ErrorLog: The location of the error log file.
|
||||||
|
# If you do not specify an ErrorLog directive within a <VirtualHost>
|
||||||
|
# container, error messages relating to that virtual host will be
|
||||||
|
# logged here. If you *do* define an error logfile for a <VirtualHost>
|
||||||
|
# container, that host's errors will be logged there and not here.
|
||||||
|
#
|
||||||
|
ErrorLog ${APACHE_LOG_DIR}/error.log
|
||||||
|
|
||||||
|
#
|
||||||
|
# LogLevel: Control the severity of messages logged to the error_log.
|
||||||
|
# Available values: trace8, ..., trace1, debug, info, notice, warn,
|
||||||
|
# error, crit, alert, emerg.
|
||||||
|
# It is also possible to configure the log level for particular modules, e.g.
|
||||||
|
# "LogLevel info ssl:warn"
|
||||||
|
#
|
||||||
|
LogLevel warn
|
||||||
|
|
||||||
|
# Include module configuration:
|
||||||
|
IncludeOptional mods-enabled/*.load
|
||||||
|
IncludeOptional mods-enabled/*.conf
|
||||||
|
|
||||||
|
# Include list of ports to listen on
|
||||||
|
Include ports.conf
|
||||||
|
|
||||||
|
|
||||||
|
# Sets the default security model of the Apache2 HTTPD server. It does
|
||||||
|
# not allow access to the root filesystem outside of /usr/share and /var/www.
|
||||||
|
# The former is used by web applications packaged in Debian,
|
||||||
|
# the latter may be used for local directories served by the web server. If
|
||||||
|
# your system is serving content from a sub-directory in /srv you must allow
|
||||||
|
# access here, or in any related virtual host.
|
||||||
|
<Directory />
|
||||||
|
Options FollowSymLinks
|
||||||
|
AllowOverride None
|
||||||
|
Require all denied
|
||||||
|
</Directory>
|
||||||
|
|
||||||
|
<Directory /usr/share>
|
||||||
|
AllowOverride None
|
||||||
|
Require all granted
|
||||||
|
</Directory>
|
||||||
|
|
||||||
|
<Directory /var/www/>
|
||||||
|
Options Indexes FollowSymLinks
|
||||||
|
AllowOverride all
|
||||||
|
Require all granted
|
||||||
|
</Directory>
|
||||||
|
|
||||||
|
#<Directory /srv/>
|
||||||
|
# Options Indexes FollowSymLinks
|
||||||
|
# AllowOverride None
|
||||||
|
# Require all granted
|
||||||
|
#</Directory>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# AccessFileName: The name of the file to look for in each directory
|
||||||
|
# for additional configuration directives. See also the AllowOverride
|
||||||
|
# directive.
|
||||||
|
#
|
||||||
|
AccessFileName .htaccess
|
||||||
|
|
||||||
|
#
|
||||||
|
# The following lines prevent .htaccess and .htpasswd files from being
|
||||||
|
# viewed by Web clients.
|
||||||
|
#
|
||||||
|
<FilesMatch "^\.ht">
|
||||||
|
Require all denied
|
||||||
|
</FilesMatch>
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# The following directives define some format nicknames for use with
|
||||||
|
# a CustomLog directive.
|
||||||
|
#
|
||||||
|
# These deviate from the Common Log Format definitions in that they use %O
|
||||||
|
# (the actual bytes sent including headers) instead of %b (the size of the
|
||||||
|
# requested file), because the latter makes it impossible to detect partial
|
||||||
|
# requests.
|
||||||
|
#
|
||||||
|
# Note that the use of %{X-Forwarded-For}i instead of %h is not recommended.
|
||||||
|
# Use mod_remoteip instead.
|
||||||
|
#
|
||||||
|
LogFormat "%v:%p %h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" vhost_combined
|
||||||
|
LogFormat "%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined
|
||||||
|
LogFormat "%h %l %u %t \"%r\" %>s %O" common
|
||||||
|
LogFormat "%{Referer}i -> %U" referer
|
||||||
|
LogFormat "%{User-agent}i" agent
|
||||||
|
|
||||||
|
# Include of directories ignores editors' and dpkg's backup files,
|
||||||
|
# see README.Debian for details.
|
||||||
|
|
||||||
|
# Include generic snippets of statements
|
||||||
|
IncludeOptional conf-enabled/*.conf
|
||||||
|
|
||||||
|
# Include the virtual host configurations:
|
||||||
|
IncludeOptional sites-enabled/*.conf
|
||||||
|
|
||||||
|
# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
|
After Width: | Height: | Size: 125 KiB |
After Width: | Height: | Size: 171 KiB |
After Width: | Height: | Size: 153 KiB |
After Width: | Height: | Size: 155 KiB |
After Width: | Height: | Size: 151 KiB |
After Width: | Height: | Size: 339 KiB |
@ -0,0 +1,16 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
chemin_script=$(dirname "$0")
|
||||||
|
|
||||||
|
mkdir -p /etc/postfix/bdd
|
||||||
|
rm -f /etc/postfix/bdd/postfix.sqlite
|
||||||
|
|
||||||
|
# Création des tables
|
||||||
|
echo "CREATION TABLES"
|
||||||
|
sqlite3 /etc/postfix/bdd/postfix.sqlite < "${chemin_script}"/postfix_tables.sql
|
||||||
|
|
||||||
|
# Création des données
|
||||||
|
echo "CREATION DONNÉES"
|
||||||
|
sqlite3 /etc/postfix/bdd/postfix.sqlite < "${chemin_script}"/postfix_données.sql
|
||||||
|
|
||||||
|
chown -R www-data: /etc/postfix/bdd
|
@ -0,0 +1,34 @@
|
|||||||
|
|
||||||
|
-- Alias (ne doivent pas apparaître)
|
||||||
|
INSERT INTO postfix_alias (alias,destination,active) VALUES ("toto","test1",1);
|
||||||
|
INSERT INTO postfix_alias (alias,destination,active) VALUES ("tata","test2",0);
|
||||||
|
INSERT INTO postfix_alias (alias,destination,active) VALUES ("titi","test3",1);
|
||||||
|
|
||||||
|
-- Alias virtuels
|
||||||
|
INSERT INTO postfix_alias_virtuels (destination,courriel,active) VALUES ("toto@exemple.fr","comptable@exemple.fr",1);
|
||||||
|
INSERT INTO postfix_alias_virtuels (destination,courriel,active) VALUES ("toto@exemple.fr","medecin@exemple.fr",0);
|
||||||
|
INSERT INTO postfix_alias_virtuels (destination,courriel,active) VALUES ("toto@exemple.fr","supermacher@exemple.fr",1);
|
||||||
|
INSERT INTO postfix_alias_virtuels (destination,courriel,active) VALUES ("tata@exemple.fr","fleuriste@exemple.fr",0);
|
||||||
|
INSERT INTO postfix_alias_virtuels (destination,courriel,active) VALUES ("tata@exemple.fr","coiffeur@exemple.fr",0);
|
||||||
|
INSERT INTO postfix_alias_virtuels (destination,courriel,active) VALUES ("titi@exemple.fr","promos@exemple.fr",1);
|
||||||
|
|
||||||
|
-- Domaines secondaires
|
||||||
|
INSERT INTO postfix_domaines (domaine,active,defaut) VALUES ("exemple.fr",1,0);
|
||||||
|
INSERT INTO postfix_domaines (domaine,active,defaut) VALUES ("toto.fr",1,0);
|
||||||
|
INSERT INTO postfix_domaines (domaine,active,defaut) VALUES ("tata.fr",1,0);
|
||||||
|
INSERT INTO postfix_domaines (domaine,active,defaut) VALUES ("titi.fr",0,0);
|
||||||
|
|
||||||
|
-- Listes noires destinataires
|
||||||
|
INSERT INTO postfix_liste_noire_destinataires (courriel,action,active) VALUES ("root@mail.exemple.fr","REJECT",1);
|
||||||
|
INSERT INTO postfix_liste_noire_destinataires (courriel,action,active) VALUES ("git@mail.exemple.fr","REJECT",1);
|
||||||
|
INSERT INTO postfix_liste_noire_destinataires (courriel,action,active) VALUES ("liste@mail.exemple.fr","REJECT",1);
|
||||||
|
|
||||||
|
-- Listes noires expéditeurs
|
||||||
|
INSERT INTO postfix_liste_noire_expediteurs (courriel,code_retour,message,active) VALUES ("tata@exemple.fr",554,"Parle à ma main, ma tête est malade.",0);
|
||||||
|
INSERT INTO postfix_liste_noire_expediteurs (courriel,code_retour,message,active) VALUES ("bob@titi.fr",554,"Parle à ma main, ma tête est malade.",1);
|
||||||
|
INSERT INTO postfix_liste_noire_expediteurs (courriel,code_retour,message,active) VALUES ("roland@tata.fr",554,"Parle à ma main, ma tête est malade.",1);
|
||||||
|
|
||||||
|
-- Listes utilisateurs
|
||||||
|
INSERT INTO postfix_utilisateurs (utilisateur,mot_de_passe,nom_complet,rep_perso,uid,gid,privilege,prefixe,active) VALUES ("demo@exemple.fr","{SHA512-CRYPT}$6$UXHkG3wTNiXZthSO$JVK6Qubf0JdCTFNlsYr./61wPNqxre3N4xGbMQHl264F9om84F2QbrqzI.pQj36npoHifUElvZNNhOw6T/9Rp0","Démo","exemple.fr/demo/",3000,3000,"administrateur","",1);
|
||||||
|
INSERT INTO postfix_utilisateurs (utilisateur,mot_de_passe,nom_complet,rep_perso,uid,gid,privilege,active) VALUES ("toto@exemple.fr","{SHA512-CRYPT}$6$bhI1RyJYs3jZFEPT$bfZC1tupWAWVAK34zfOxoAXhJvfKM83tZy9doLURsws9jXS3XvBISxtWxiXPKZ3Nex3MXoOPNFzw7iy8PiWMN.","Toto Dupont","exemple.fr/toto/",3000,3000,"administrateur",1);
|
||||||
|
INSERT INTO postfix_utilisateurs (utilisateur,mot_de_passe,nom_complet,rep_perso,uid,gid,privilege,prefixe,active) VALUES ("tata@tata.fr","{SHA512-CRYPT}$6$9E.KRufz4Gd.dBhW$KUdFnBg8aiPbYarKiDc4cD6NC.WsYanXBqhZEpCXJndR4SlJn3eVVo7HirXzpYaggihBgdUScS6wswG.AfOKd/","Tata Dupuis","tata.fr/tata/",3000,3000,"utilisateur","ta.",1);
|
@ -0,0 +1,43 @@
|
|||||||
|
CREATE TABLE IF NOT EXISTS postfix_alias (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
alias TEXT NOT NULL UNIQUE,
|
||||||
|
destination TEXT NOT NULL,
|
||||||
|
active INTEGER
|
||||||
|
);
|
||||||
|
CREATE TABLE IF NOT EXISTS postfix_alias_virtuels (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
courriel TEXT NOT NULL UNIQUE,
|
||||||
|
destination TEXT NOT NULL,
|
||||||
|
active INTEGER
|
||||||
|
);
|
||||||
|
CREATE TABLE IF NOT EXISTS postfix_domaines (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
domaine TEXT NOT NULL UNIQUE,
|
||||||
|
defaut BOOLEAN NOT NULL CHECK (defaut IN (0, 1)),
|
||||||
|
active INTEGER
|
||||||
|
);
|
||||||
|
CREATE TABLE IF NOT EXISTS postfix_liste_noire_destinataires (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
courriel TEXT NOT NULL UNIQUE,
|
||||||
|
action TEXT NOT NULL,
|
||||||
|
active INTEGER
|
||||||
|
);
|
||||||
|
CREATE TABLE IF NOT EXISTS postfix_liste_noire_expediteurs (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
courriel TEXT NOT NULL UNIQUE,
|
||||||
|
code_retour INTEGER NOT NULL,
|
||||||
|
message TEXT NOT NULL,
|
||||||
|
active INTEGER
|
||||||
|
);
|
||||||
|
CREATE TABLE postfix_utilisateurs (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
utilisateur TEXT NOT NULL UNIQUE,
|
||||||
|
mot_de_passe TEXT NOT NULL,
|
||||||
|
nom_complet TEXT,
|
||||||
|
rep_perso TEXT NOT NULL,
|
||||||
|
uid INTEGER NOT NULL,
|
||||||
|
gid INTEGER NOT NULL,
|
||||||
|
privilege TEXT NOT NULL,
|
||||||
|
prefixe TEXT,
|
||||||
|
active INTEGER
|
||||||
|
);
|
@ -0,0 +1,5 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
dockerfile="$(dirname ${0})/../"
|
||||||
|
docker build -t courtail "${dockerfile}"
|
||||||
|
docker run -it -p 8080:80 -p 4443:443 -v /etc/localtime:/etc/localtime:ro courtail:latest
|
After Width: | Height: | Size: 83 KiB |
@ -0,0 +1,68 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Page centrale de gestion des fonctionnalités du serveur de courriel.
|
||||||
|
* C'est de cette page qu'est appelé l'ensemble des fonctionnalités du portail.
|
||||||
|
*/
|
||||||
|
session_start();
|
||||||
|
|
||||||
|
require_once($_SERVER["DOCUMENT_ROOT"]."/services/fonctions/sessions/authentification.php");
|
||||||
|
validationCookie($pdo);
|
||||||
|
|
||||||
|
require_once($_SERVER["DOCUMENT_ROOT"]."/services/fonctions/sessions/privileges.php");
|
||||||
|
testPrivileges();
|
||||||
|
require_once($_SERVER["DOCUMENT_ROOT"]."/inclusions/entete.php");
|
||||||
|
require_once($_SERVER["DOCUMENT_ROOT"]."/inclusions/barre_menu.php");
|
||||||
|
|
||||||
|
require_once($_SERVER["DOCUMENT_ROOT"]."/services/fonctions/messages/messages.php");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Affichage d'une bannière d'état sur l'action précedemment effectuée.
|
||||||
|
*/
|
||||||
|
if (isset($_GET['erreur']) && !empty($_GET['erreur'])) {
|
||||||
|
retourneMessage('erreurs',$_GET['erreur']);
|
||||||
|
}
|
||||||
|
elseif (isset($_GET['succes']) && !empty($_GET['succes'])) {
|
||||||
|
retourneMessage('succes',$_GET['succes']);
|
||||||
|
}
|
||||||
|
elseif (isset($_GET['message']) && !empty($_GET['message'])) {
|
||||||
|
retourneMessage('messages',$_GET['message']);
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "<div class=\"container-fluid\">";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Permet d'importer les fonctions de la page demandée par l'utilisateur sur le portail d'administration.
|
||||||
|
*/
|
||||||
|
if (isset($_GET['page']) && !empty($_GET['page'])) {
|
||||||
|
switch ($_GET['page']) {
|
||||||
|
case 'accueil':
|
||||||
|
require_once($_SERVER["DOCUMENT_ROOT"]."/services/gestion/alias_virtuels.php");
|
||||||
|
break;
|
||||||
|
case 'alias':
|
||||||
|
require_once($_SERVER["DOCUMENT_ROOT"]."/services/gestion/alias_virtuels.php");
|
||||||
|
break;
|
||||||
|
case 'domaines':
|
||||||
|
require_once($_SERVER["DOCUMENT_ROOT"]."/services/gestion/domaines.php");
|
||||||
|
break;
|
||||||
|
case 'listes_noires':
|
||||||
|
require_once($_SERVER["DOCUMENT_ROOT"]."/services/gestion/listes_noires.php");
|
||||||
|
break;
|
||||||
|
case 'parametres':
|
||||||
|
require_once($_SERVER["DOCUMENT_ROOT"]."/services/gestion/parametres.php");
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
echo "<h1>Cette page n'existe pas.</h1>";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
echo "<h1>Cette page n'existe pas.</h1>";
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "</div>";
|
||||||
|
|
||||||
|
require_once($_SERVER["DOCUMENT_ROOT"]."/inclusions/pied.php");
|
||||||
|
|
||||||
|
?>
|
@ -0,0 +1,267 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Page de redirection vers la page d'accueil.
|
||||||
|
* Elle est appelée par la page d'identification lorsqu'un visiteur n'est pas parvenu à s'identifier.
|
||||||
|
* Elle ajoute à cette redirection un temps d'attente pour limiter la fréquence des tentatives ainsi qu'une variable dans l'URL permettant l'affichage d'un message d'explication sur la redirection.
|
||||||
|
*/
|
||||||
|
|
||||||
|
header ("Refresh: 5;URL=/pages/visiteurs/formulaire_accueil.php?erreur=17");
|
||||||
|
|
||||||
|
?>
|
||||||
|
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="fr">
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title>Courtail - Portail des courriels</title>
|
||||||
|
<link rel="icon" href="/fichiers/svg/favicon.svg" />
|
||||||
|
<style>
|
||||||
|
/* Base */
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
font-family: sans-serif;
|
||||||
|
font-size: 40px;
|
||||||
|
color: #FFF;
|
||||||
|
background-color: #343a40;
|
||||||
|
text-align: center; }
|
||||||
|
|
||||||
|
.chargements{
|
||||||
|
position: absolute;
|
||||||
|
top:40%;
|
||||||
|
margin: 0 auto;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section {
|
||||||
|
height: 100%;
|
||||||
|
line-height: 100%; }
|
||||||
|
|
||||||
|
.section-2 {
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-3 {
|
||||||
|
background-color: #e74c3c; }
|
||||||
|
|
||||||
|
.section-4 {
|
||||||
|
background-color: #8e44ad; }
|
||||||
|
|
||||||
|
.chargement {
|
||||||
|
width: 50px;
|
||||||
|
height: 50px;
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: middle;
|
||||||
|
position: relative; }
|
||||||
|
|
||||||
|
/* chargements */
|
||||||
|
.chargement-quart {
|
||||||
|
border-radius: 50px;
|
||||||
|
border: 6px solid rgba(255, 255, 255, 0.4); }
|
||||||
|
|
||||||
|
.chargement-quart:after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: -6px;
|
||||||
|
left: -6px;
|
||||||
|
bottom: -6px;
|
||||||
|
right: -6px;
|
||||||
|
border-radius: 50px;
|
||||||
|
border: 6px solid transparent;
|
||||||
|
border-top-color: #FFF;
|
||||||
|
-webkit-animation: spin 1s linear infinite;
|
||||||
|
-moz-animation: spin 1s linear infinite;
|
||||||
|
animation: spin 1s linear infinite; }
|
||||||
|
|
||||||
|
.chargement-double {
|
||||||
|
border-radius: 50px;
|
||||||
|
border: 6px solid transparent;
|
||||||
|
border-top-color: #FFF;
|
||||||
|
border-bottom-color: #FFF;
|
||||||
|
-webkit-animation: spin 1s linear infinite;
|
||||||
|
-moz-animation: spin 1s linear infinite;
|
||||||
|
animation: spin 1s linear infinite; }
|
||||||
|
.chargement-double:after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 5px;
|
||||||
|
left: 5px;
|
||||||
|
bottom: 5px;
|
||||||
|
right: 5px;
|
||||||
|
border-radius: 50px;
|
||||||
|
border: 6px solid transparent;
|
||||||
|
border-top-color: #FFF;
|
||||||
|
border-bottom-color: #FFF;
|
||||||
|
opacity: 0.6;
|
||||||
|
-webkit-animation: spinreverse 2s linear infinite;
|
||||||
|
-moz-animation: spinreverse 2s linear infinite;
|
||||||
|
animation: spinreverse 2s linear infinite; }
|
||||||
|
|
||||||
|
.chargement-cercles {
|
||||||
|
border-radius: 50px;
|
||||||
|
border: 3px solid transparent;
|
||||||
|
border-top-color: #FFF;
|
||||||
|
-webkit-animation: spin 1s linear infinite;
|
||||||
|
-moz-animation: spin 1s linear infinite;
|
||||||
|
animation: spin 1s linear infinite; }
|
||||||
|
.chargement-cercles:before, .chargement-cercles:after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 5px;
|
||||||
|
left: 5px;
|
||||||
|
bottom: 5px;
|
||||||
|
right: 5px;
|
||||||
|
border-radius: 50px;
|
||||||
|
border: 3px solid transparent;
|
||||||
|
border-top-color: #FFF;
|
||||||
|
opacity: 0.8;
|
||||||
|
-webkit-animation: spin 10s linear infinite;
|
||||||
|
-moz-animation: spin 10s linear infinite;
|
||||||
|
animation: spin 10s linear infinite; }
|
||||||
|
.chargement-cercles:before {
|
||||||
|
top: 12px;
|
||||||
|
left: 12px;
|
||||||
|
bottom: 12px;
|
||||||
|
right: 12px;
|
||||||
|
opacity: .5;
|
||||||
|
-webkit-animation: spin 5s linear infinite;
|
||||||
|
-moz-animation: spin 5s linear infinite;
|
||||||
|
animation: spin 5s linear infinite; }
|
||||||
|
|
||||||
|
.chargement-barres:before, .chargement-barres:after,
|
||||||
|
.chargement-barres span {
|
||||||
|
content: '';
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
left: 0px;
|
||||||
|
top: 0;
|
||||||
|
width: 10px;
|
||||||
|
height: 30px;
|
||||||
|
background-color: #FFF;
|
||||||
|
-webkit-animation: grow 1s linear infinite;
|
||||||
|
-moz-animation: grow 1s linear infinite;
|
||||||
|
animation: grow 1s linear infinite; }
|
||||||
|
.chargement-barres:after {
|
||||||
|
left: 15px;
|
||||||
|
-webkit-animation-delay: -0.66s;
|
||||||
|
-moz-animation-delay: -0.66s;
|
||||||
|
animation-delay: -0.66s; }
|
||||||
|
.chargement-barres span {
|
||||||
|
left: 30px;
|
||||||
|
-webkit-animation-delay: -0.33s;
|
||||||
|
-moz-animation-delay: -0.33s;
|
||||||
|
animation-delay: -0.33s; }
|
||||||
|
|
||||||
|
/* Animations */
|
||||||
|
@-webkit-keyframes spin {
|
||||||
|
from {
|
||||||
|
-webkit-transform: rotate(0deg); }
|
||||||
|
|
||||||
|
to {
|
||||||
|
-webkit-transform: rotate(360deg); } }
|
||||||
|
@-moz-keyframes spin {
|
||||||
|
from {
|
||||||
|
-moz-transform: rotate(0deg); }
|
||||||
|
|
||||||
|
to {
|
||||||
|
-moz-transform: rotate(360deg); } }
|
||||||
|
@keyframes spin {
|
||||||
|
from {
|
||||||
|
-webkit-transform: rotate(0deg);
|
||||||
|
-moz-transform: rotate(0deg);
|
||||||
|
-ms-transform: rotate(0deg);
|
||||||
|
-o-transform: rotate(0deg);
|
||||||
|
transform: rotate(0deg); }
|
||||||
|
|
||||||
|
to {
|
||||||
|
-webkit-transform: rotate(360deg);
|
||||||
|
-moz-transform: rotate(360deg);
|
||||||
|
-ms-transform: rotate(360deg);
|
||||||
|
-o-transform: rotate(360deg);
|
||||||
|
transform: rotate(360deg); } }
|
||||||
|
@-webkit-keyframes spinreverse {
|
||||||
|
from {
|
||||||
|
-webkit-transform: rotate(0deg); }
|
||||||
|
|
||||||
|
to {
|
||||||
|
-webkit-transform: rotate(-360deg); } }
|
||||||
|
@-moz-keyframes spinreverse {
|
||||||
|
from {
|
||||||
|
-moz-transform: rotate(0deg); }
|
||||||
|
|
||||||
|
to {
|
||||||
|
-moz-transform: rotate(-360deg); } }
|
||||||
|
@keyframes spinreverse {
|
||||||
|
from {
|
||||||
|
-webkit-transform: rotate(0deg);
|
||||||
|
-moz-transform: rotate(0deg);
|
||||||
|
-ms-transform: rotate(0deg);
|
||||||
|
-o-transform: rotate(0deg);
|
||||||
|
transform: rotate(0deg); }
|
||||||
|
|
||||||
|
to {
|
||||||
|
-webkit-transform: rotate(-360deg);
|
||||||
|
-moz-transform: rotate(-360deg);
|
||||||
|
-ms-transform: rotate(-360deg);
|
||||||
|
-o-transform: rotate(-360deg);
|
||||||
|
transform: rotate(-360deg); } }
|
||||||
|
@-webkit-keyframes grow {
|
||||||
|
0% {
|
||||||
|
-webkit-transform: scaleY(0);
|
||||||
|
opacity: 0; }
|
||||||
|
|
||||||
|
50% {
|
||||||
|
-webkit-transform: scaleY(1);
|
||||||
|
opacity: 1; }
|
||||||
|
|
||||||
|
100% {
|
||||||
|
-webkit-transform: scaleY(0);
|
||||||
|
opacity: 0; } }
|
||||||
|
@-moz-keyframes grow {
|
||||||
|
0% {
|
||||||
|
-moz-transform: scaleY(0);
|
||||||
|
opacity: 0; }
|
||||||
|
|
||||||
|
50% {
|
||||||
|
-moz-transform: scaleY(1);
|
||||||
|
opacity: 1; }
|
||||||
|
|
||||||
|
100% {
|
||||||
|
-moz-transform: scaleY(0);
|
||||||
|
opacity: 0; } }
|
||||||
|
@keyframes grow {
|
||||||
|
0% {
|
||||||
|
-webkit-transform: scaleY(0);
|
||||||
|
-moz-transform: scaleY(0);
|
||||||
|
-ms-transform: scaleY(0);
|
||||||
|
-o-transform: scaleY(0);
|
||||||
|
transform: scaleY(0);
|
||||||
|
opacity: 0; }
|
||||||
|
|
||||||
|
50% {
|
||||||
|
-webkit-transform: scaleY(1);
|
||||||
|
-moz-transform: scaleY(1);
|
||||||
|
-ms-transform: scaleY(1);
|
||||||
|
-o-transform: scaleY(1);
|
||||||
|
transform: scaleY(1);
|
||||||
|
opacity: 1; }
|
||||||
|
|
||||||
|
100% {
|
||||||
|
-webkit-transform: scaleY(0);
|
||||||
|
-moz-transform: scaleY(0);
|
||||||
|
-ms-transform: scaleY(0);
|
||||||
|
-o-transform: scaleY(0);
|
||||||
|
transform: scaleY(0);
|
||||||
|
opacity: 0; } }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="chargements">
|
||||||
|
<section class="section section-2">
|
||||||
|
<span class="chargement chargement-double"></span>
|
||||||
|
Traitement...
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,69 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Page d'accueil du portail.
|
||||||
|
* Impose une authentification du visiteur pour continuer.
|
||||||
|
* Redirige les tentative d'identification pour traitement et test de légitimité.
|
||||||
|
*/
|
||||||
|
session_start();
|
||||||
|
|
||||||
|
require_once($_SERVER["DOCUMENT_ROOT"]."/services/fonctions/sessions/authentification.php");
|
||||||
|
validationCookie($pdo);
|
||||||
|
|
||||||
|
if (isset($_SESSION['id_utilisateur']) && isset($_SESSION['pseudo_utilisateur']) && isset($_SESSION['nom_utilisateur']) && isset($_SESSION['privilege_utilisateur']) && !empty($_SESSION['id_utilisateur']) && !empty($_SESSION['pseudo_utilisateur']) && !empty($_SESSION['nom_utilisateur']) && !empty($_SESSION['privilege_utilisateur'])) {
|
||||||
|
header ("location: /pages/gestion/administration.php?page=accueil");
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
|
||||||
|
require_once($_SERVER["DOCUMENT_ROOT"]."/inclusions/entete.php");
|
||||||
|
require_once($_SERVER["DOCUMENT_ROOT"]."/services/fonctions/messages/messages.php");
|
||||||
|
|
||||||
|
?>
|
||||||
|
|
||||||
|
<div id="contenu" class="contenu container">
|
||||||
|
<div id="logo-accueil" class="logo">
|
||||||
|
<img src="/fichiers/svg/send.svg" alt="courriel">
|
||||||
|
<h1>Courtail</h1>
|
||||||
|
</div>
|
||||||
|
<div class="card" id="contenu_auth">
|
||||||
|
<div class="card-body">
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Affichage d'une bannière d'état sur l'action précedemment effectuée.
|
||||||
|
*/
|
||||||
|
if (isset($_GET['erreur']) && !empty($_GET['erreur'])) {
|
||||||
|
retourneMessage('erreurs',$_GET['erreur']);
|
||||||
|
}
|
||||||
|
elseif (isset($_GET['succes']) && !empty($_GET['succes'])) {
|
||||||
|
retourneMessage('succes',$_GET['succes']);
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
<form method="post" action="/services/traitements/utilisateurs/identification.php">
|
||||||
|
<div class="form-floating mb-3 mt-3">
|
||||||
|
<input type="text" name="identifiant" class="form-control" id="identifiant" placeholder="nom@example.fr" autofocus required/>
|
||||||
|
<label for="identifiant">Votre nom d'utilisateur</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-floating mb-3">
|
||||||
|
<input type="password" name="mdp" class="form-control" id="mdp" placeholder="Mot de passe" required/>
|
||||||
|
<label for="mdp">Votre mot de passe</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check mb-3">
|
||||||
|
<input type="checkbox" name="souvenir-session" id="souvenir-session" class="form-check-input" checked/>
|
||||||
|
<label for="souvenir-session" class="form-check-label">Se souvenir de moi</label>
|
||||||
|
</div>
|
||||||
|
<button id="envoyer" type="submit" class="btn btn-primary">envoyer</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const body = document.querySelector('body');
|
||||||
|
body.classList.add("fond-arc-noire");
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<?php
|
||||||
|
require_once($_SERVER["DOCUMENT_ROOT"]."/inclusions/pied.php");
|
||||||
|
?>
|
@ -0,0 +1,157 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Page de fonctions permettant la gestion des alias virtuels.
|
||||||
|
*/
|
||||||
|
|
||||||
|
require_once ($_SERVER["DOCUMENT_ROOT"]."/services/fonctions/bdd/connexion.php");
|
||||||
|
require_once ($_SERVER["DOCUMENT_ROOT"]."/services/fonctions/sessions/privileges.php");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fonction listant les alias virtuels d'un utilisateur.
|
||||||
|
*/
|
||||||
|
function listeAliasVirtuelsPostfix($pdo) {
|
||||||
|
try {
|
||||||
|
// Filtre des alias virtuels de l'utilisateur courant
|
||||||
|
$req = 'SELECT * FROM postfix_alias_virtuels WHERE destination=:destination ORDER BY courriel ASC';
|
||||||
|
$sql=$pdo->prepare($req);
|
||||||
|
$sql->bindValue(':destination',$_SESSION['pseudo_utilisateur']);
|
||||||
|
$sql->execute();
|
||||||
|
|
||||||
|
$liste_alias_virtuels = $sql->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
return $liste_alias_virtuels;
|
||||||
|
}
|
||||||
|
catch (\Exception $e) {
|
||||||
|
die ("Erreur de requête de selection des alias virtuels : ".$e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fonction listant tous les alias virtuels de la base.
|
||||||
|
*/
|
||||||
|
function listeTousAliasVirtuelsPostfix($pdo) {
|
||||||
|
try {
|
||||||
|
$req = 'SELECT * FROM postfix_alias_virtuels';
|
||||||
|
$sql=$pdo->prepare($req);
|
||||||
|
$sql->execute();
|
||||||
|
|
||||||
|
$liste_alias_virtuels = $sql->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
return $liste_alias_virtuels;
|
||||||
|
}
|
||||||
|
catch (\Exception $e) {
|
||||||
|
die ("Erreur de requête de selection des alias virtuels : ".$e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fonction d'ajout d'un alias virtuel.
|
||||||
|
*/
|
||||||
|
function ajoutAliasVirtuelsPostfix($pdo,$nom_alias_virtuel,$choix_domaine_alias_virtuel) {
|
||||||
|
try {
|
||||||
|
// Insertion de l'alias virtuel entré par l'utilisateur et lié avec son adresse
|
||||||
|
$req='INSERT INTO postfix_alias_virtuels (courriel,destination,active) VALUES (:alias_virtuel,:courriel,1)';
|
||||||
|
|
||||||
|
$sql=$pdo->prepare($req);
|
||||||
|
$sql->bindValue(':courriel',$_SESSION['pseudo_utilisateur']);
|
||||||
|
$sql->bindValue(':alias_virtuel',substr(htmlspecialchars(retournePrefixeUtilisateurPostfix($pdo,$_SESSION['pseudo_utilisateur']).$nom_alias_virtuel."@".$choix_domaine_alias_virtuel),0,100));
|
||||||
|
$sql->execute();
|
||||||
|
|
||||||
|
if ($sql->rowCount() == 1){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (\Exception $e) {
|
||||||
|
// Récupération du code de retour de la commande SQLite
|
||||||
|
$code_retour=$sql->errorInfo();
|
||||||
|
|
||||||
|
if ($code_retour[0]=="23000") {
|
||||||
|
// Code de retour envoyé par le pilote PDO SQLite signifiant que la contrainte "UNIQUE" du champ "courriel" de la table "postif_alias_virtuels" est violée. L'alias envoyé via le formulaire par l'utilisateur a déjà été renseigné dans la base
|
||||||
|
header ("Location: /pages/gestion/administration.php?page=alias&erreur=3");
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
elseif ($code_retour[0]=="HY000") {
|
||||||
|
// Code de retour envoyé par le pilote PDO SQLite lorsque la base de données n'est accessible qu'en lecture seule à www-data
|
||||||
|
header ("Location: /pages/gestion/administration.php?page=alias&erreur=4");
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// En cas d'erreur non gérée, le script s'arrête avec un message d'erreur à destination de l'administrateur du serveur
|
||||||
|
die ("Erreur de requête d'ajout d'alias virtuel : ".$e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fonction d'activation/désactivation d'un alias virtuel.
|
||||||
|
* Suite à une soumission du formulaire dédié, cette fonction va traiter l'ensemble des alias virtuels d'un utilisateur.
|
||||||
|
* Elle occasionnera peut-être des baisses de performance si un très grand nombre d'alias virtuels existe pour un utilisateur donné (le traitement n'intervenant pas spécifiquement pour l'entrée modifiée).
|
||||||
|
*/
|
||||||
|
function modifEtatAliasVirtuelsPostfix($pdo,$retour_form) {
|
||||||
|
try {
|
||||||
|
$compteModifs=0;
|
||||||
|
foreach ($retour_form as $id_alias_virtuel => $etat_alias_virtuel) {
|
||||||
|
$req='UPDATE postfix_alias_virtuels SET active=:etat_alias_virtuel WHERE id=:id_alias_virtuel AND destination=:pseudo_utilisateur';
|
||||||
|
|
||||||
|
$sql=$pdo->prepare($req);
|
||||||
|
$sql->bindValue(':etat_alias_virtuel',$etat_alias_virtuel);
|
||||||
|
$sql->bindValue(':id_alias_virtuel',$id_alias_virtuel);
|
||||||
|
$sql->bindValue(':pseudo_utilisateur',$_SESSION['pseudo_utilisateur']);
|
||||||
|
$sql->execute();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (\Exception $e) {
|
||||||
|
// Récupération du code de retour de la commande SQLite
|
||||||
|
$code_retour=$sql->errorInfo();
|
||||||
|
|
||||||
|
if ($code_retour[0]=="HY000") {
|
||||||
|
// Code de retour envoyé par le pilote PDO SQLite lorsque la base est accessible en lecture seule à www-data
|
||||||
|
header ("Location: /pages/gestion/administration.php?page=alias&erreur=4");
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// En cas d'erreur non gérée, le script s'arrête avec un message d'erreur à destination de l'administrateur du serveur
|
||||||
|
die ("Erreur de requête de modification d'état pour les alias virtuels : ".$e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fonction de suppression d'un alias virtuel.
|
||||||
|
*/
|
||||||
|
function supprAliasVirtuelsPostfix($pdo,$suppr_alias_virtuel) {
|
||||||
|
try {
|
||||||
|
$req='DELETE FROM postfix_alias_virtuels WHERE id=:id_alias_virtuel AND destination=:pseudo_utilisateur';
|
||||||
|
|
||||||
|
$sql=$pdo->prepare($req);
|
||||||
|
$sql->bindValue(':id_alias_virtuel',$suppr_alias_virtuel);
|
||||||
|
$sql->bindValue(':pseudo_utilisateur',$_SESSION['pseudo_utilisateur']);
|
||||||
|
$sql->execute();
|
||||||
|
|
||||||
|
if($sql->rowCount() == 1){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (\Exception $e) {
|
||||||
|
// Récupération du code de retour de la commande SQLite
|
||||||
|
$code_retour=$sql->errorInfo();
|
||||||
|
|
||||||
|
if ($code_retour[0]=="HY000") {
|
||||||
|
// Code de retour envoyé par le pilote PDO SQLite lorsque la base est accessible en lecture seule à www-data
|
||||||
|
header ("Location: /pages/gestion/administration.php?page=alias&erreur=4");
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// En cas d'erreur non gérée, le script s'arrête avec un message d'erreur à destination de l'administrateur du serveur
|
||||||
|
die ("Erreur de requête de suppression d'un alias virtuel : ".$e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
@ -0,0 +1,17 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Connexion à la base SQLite3.
|
||||||
|
*/
|
||||||
|
|
||||||
|
$base = "/etc/postfix/bdd/postfix.sqlite";
|
||||||
|
|
||||||
|
try{
|
||||||
|
$pdo = new PDO("sqlite:$base");
|
||||||
|
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||||
|
}
|
||||||
|
catch (Exception $e){
|
||||||
|
die ("Erreur de connexion à la base \"$base\" : ".$e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
@ -0,0 +1,197 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Page de fonctions concernant la gestion des domaines.
|
||||||
|
*/
|
||||||
|
|
||||||
|
require_once ($_SERVER["DOCUMENT_ROOT"]."/services/fonctions/bdd/connexion.php");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fonction listant les domaines.
|
||||||
|
*/
|
||||||
|
function listeDomainesPostfix($pdo) {
|
||||||
|
try {
|
||||||
|
$req = 'SELECT * FROM postfix_domaines ORDER BY defaut DESC';
|
||||||
|
|
||||||
|
$sql=$pdo->prepare($req);
|
||||||
|
$sql->execute();
|
||||||
|
|
||||||
|
$liste_domaines = $sql->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
return $liste_domaines;
|
||||||
|
}
|
||||||
|
catch (\Exception $e) {
|
||||||
|
die ("Erreur de requête de selection des domaines pour \"$base\" : ".$e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fonction affichant le domaine par défaut.
|
||||||
|
*/
|
||||||
|
function retourneDomaineDefautPostfix($pdo) {
|
||||||
|
try {
|
||||||
|
$req = 'SELECT domaine FROM postfix_domaines WHERE defaut=1 LIMIT 1';
|
||||||
|
|
||||||
|
$sql=$pdo->prepare($req);
|
||||||
|
$sql->execute();
|
||||||
|
|
||||||
|
$result = $sql ->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
$comptage = count($result);
|
||||||
|
|
||||||
|
if($comptage == 1){
|
||||||
|
$domaine_defaut = $result;
|
||||||
|
return $domaine_defaut[0]['domaine'];;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$domaine_defaut = "";
|
||||||
|
return $domaine_defaut;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (\Exception $e) {
|
||||||
|
die ("Erreur de requête de selection des domaines pour \"$base\" : ".$e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fonction changeant le domaine par défaut.
|
||||||
|
*/
|
||||||
|
function changeDomaineDefautPostfix($pdo,$choix_domaine_defaut) {
|
||||||
|
try {
|
||||||
|
// suppression du status de domaine par défaut sur tous les domaines pour s'assurer de l'unicité de ce paramètre à la requête suivante
|
||||||
|
$req = 'UPDATE postfix_domaines SET defaut=0';
|
||||||
|
|
||||||
|
$sql=$pdo->prepare($req);
|
||||||
|
$sql->execute();
|
||||||
|
|
||||||
|
// Définition du domaine renseigné par l'utilisateur et activation de celui-ci (au cas-où il ne l'était pas)
|
||||||
|
$req = 'UPDATE postfix_domaines SET defaut=1, active=1 WHERE domaine=:domaine';
|
||||||
|
|
||||||
|
$sql=$pdo->prepare($req);
|
||||||
|
$sql->bindValue(':domaine',$choix_domaine_defaut);
|
||||||
|
$sql->execute();
|
||||||
|
}
|
||||||
|
catch (\Exception $e) {
|
||||||
|
// Récupération du code de retour de la commande SQLite
|
||||||
|
$code_retour=$sql->errorInfo();
|
||||||
|
|
||||||
|
if ($code_retour[0]=="HY000") {
|
||||||
|
// Code de retour envoyé par le pilote PDO SQLite lorsque la base est accessible en lecture seule à www-data
|
||||||
|
header ("Location: /pages/gestion/administration.php?page=domaines&erreur=4");
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// En cas d'erreur non gérée, le script s'arrête avec un message d'erreur à destination de l'administrateur du serveur
|
||||||
|
die ("Erreur de requête de modification de préférence pour le domaine par défaut : ".$e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fonction d'ajout d'un domaine.
|
||||||
|
*/
|
||||||
|
function ajoutDomainePostfix($pdo,$nom_domaine) {
|
||||||
|
try {
|
||||||
|
// Insertion du domaine entré par l'administrateur
|
||||||
|
$req='INSERT INTO postfix_domaines (domaine,defaut,active) VALUES (:domaine,0,1)';
|
||||||
|
|
||||||
|
$sql=$pdo->prepare($req);
|
||||||
|
$sql->bindValue(':domaine',substr(htmlspecialchars($nom_domaine),0,100));
|
||||||
|
$sql->execute();
|
||||||
|
|
||||||
|
if ($sql->rowCount() == 1){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (\Exception $e) {
|
||||||
|
// Récupération du code de retour de la commande SQLite.
|
||||||
|
$code_retour=$sql->errorInfo();
|
||||||
|
|
||||||
|
if ($code_retour[0]=="23000") {
|
||||||
|
// Code de retour envoyé par le pilote PDO SQLite signifiant que la contrainte "UNIQUE" du champ "domaine" de la table "postfix_domaines" est violée. Le domaine envoyé via le formulaire par l'administrateur a déjà été renseigné dans la base
|
||||||
|
header ("Location: /pages/gestion/administration.php?page=domaines&erreur=7");
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
elseif ($code_retour[0]=="HY000") {
|
||||||
|
// Code de retour envoyé par le pilote PDO SQLite lorsque la base de données n'est accessible qu'en lecture seule à www-data
|
||||||
|
header ("Location: /pages/gestion/administration.php?page=domaines&erreur=4");
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// En cas d'erreur non gérée, le script s'arrête avec un message d'erreur à destination de l'administrateur du serveur
|
||||||
|
die ("Erreur de requête d'ajout d'un domaine : ".$e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fonction d'activation/désactivation d'un domaine.
|
||||||
|
* Suite à une soumission du formulaire dédié, cette fonction va traiter l'ensemble des domaines d'un utilisateur.
|
||||||
|
* Elle occasionnera peut-être des baisses de performance si un très grand nombre de domaines existe pour un utilisateur donné (le traitement n'intervenant pas spécifiquement pour l'entrée modifiée).
|
||||||
|
*/
|
||||||
|
function modifEtatDomainesPostfix($pdo,$retour_form) {
|
||||||
|
try {
|
||||||
|
$compteModifs=0;
|
||||||
|
foreach ($retour_form as $id_domaine => $etat_domaine) {
|
||||||
|
$req='UPDATE postfix_domaines SET active=:etat_domaine WHERE id=:id_domaine AND defaut!=1';
|
||||||
|
|
||||||
|
$sql=$pdo->prepare($req);
|
||||||
|
$sql->bindValue(':etat_domaine',$etat_domaine);
|
||||||
|
$sql->bindValue(':id_domaine',$id_domaine);
|
||||||
|
$sql->execute();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (\Exception $e) {
|
||||||
|
// Récupération du code de retour de la commande SQLite
|
||||||
|
$code_retour=$sql->errorInfo();
|
||||||
|
|
||||||
|
if ($code_retour[0]=="HY000") {
|
||||||
|
// Code de retour envoyé par le pilote PDO SQLite lorsque la base est accessible en lecture seule à www-data
|
||||||
|
header ("Location: /pages/gestion/administration.php?page=domaines&erreur=4");
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// En cas d'erreur non gérée, le script s'arrête avec un message d'erreur à destination de l'administrateur du serveur
|
||||||
|
die ("Erreur de requête de modification d'état pour les domaines : ".$e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fonction de suppression d'un domaine.
|
||||||
|
*/
|
||||||
|
function supprDomainesPostfix($pdo,$suppr_domaine) {
|
||||||
|
try {
|
||||||
|
$req='DELETE FROM postfix_domaines WHERE id=:id_domaine AND defaut!=1';
|
||||||
|
|
||||||
|
$sql=$pdo->prepare($req);
|
||||||
|
$sql->bindValue(':id_domaine',$suppr_domaine);
|
||||||
|
$sql->execute();
|
||||||
|
|
||||||
|
if($sql->rowCount() == 1){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (\Exception $e) {
|
||||||
|
// Récupération du code de retour de la commande SQLite
|
||||||
|
$code_retour=$sql->errorInfo();
|
||||||
|
|
||||||
|
if ($code_retour[0]=="HY000") {
|
||||||
|
// Code de retour envoyé par le pilote PDO SQLite lorsque la base est accessible en lecture seule à www-data
|
||||||
|
header ("Location: /pages/gestion/administration.php?page=domaines&erreur=4");
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// En cas d'erreur non gérée, le script s'arrête avec un message d'erreur à destination de l'administrateur du serveur
|
||||||
|
die ("Erreur de requête de suppression d'un domaine : ".$e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
@ -0,0 +1,323 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Page de fonctions permettant la la sauvegarde et la restauration des données de la base de la messagerie.
|
||||||
|
*/
|
||||||
|
|
||||||
|
require_once ($_SERVER["DOCUMENT_ROOT"]."/services/fonctions/bdd/connexion.php");
|
||||||
|
require_once ($_SERVER["DOCUMENT_ROOT"]."/services/fonctions/sessions/privileges.php");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fonction générant un fichier CSV avec le contenu des alias virtuels d'un utilisateur.
|
||||||
|
* Ce fichier est créé à la volée et se popose à l'utilisateur pour téléchargement.
|
||||||
|
*/
|
||||||
|
function exportAliasVirtuelsUtilisateur($pdo,$utilisateur) {
|
||||||
|
try {
|
||||||
|
// Filtre des alias virtuels de l'utilisateur courant
|
||||||
|
$req = 'SELECT * FROM postfix_alias_virtuels WHERE destination=:destination';
|
||||||
|
$sql=$pdo->prepare($req);
|
||||||
|
$sql->bindValue(':destination',$utilisateur);
|
||||||
|
$sql->execute();
|
||||||
|
|
||||||
|
$liste_alias_virtuels = $sql->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
$nom_fichier_csv="Alias-virtuels_".$utilisateur."_".date('d-m-Y').".csv";
|
||||||
|
|
||||||
|
// Entêtes HTTP permettant le téléchargement à la volée du CSV
|
||||||
|
header("Content-Disposition: attachment; filename=\"$nom_fichier_csv\"");
|
||||||
|
header("Content-Type: text/csv");
|
||||||
|
|
||||||
|
foreach ($liste_alias_virtuels as $alias_virtuel => $champ_alias_virtuel) {
|
||||||
|
echo implode(":", $champ_alias_virtuel)."\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Le fait de tuer la page enclenche la demande de téléchargement à l'utilisateur qui ne quitte visuellement jamais la page des paramètres
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
catch (\Exception $e) {
|
||||||
|
die ("Erreur de requête d'export des alias virtuels utilisateur en CSV : ".$e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fonction générant un fichier CSV avec le contenu de la base Sqlite demandé par un administrateur.
|
||||||
|
* Ce fichier est créé à la volée et se popose à l'administrateur pour téléchargement.
|
||||||
|
*/
|
||||||
|
function exportDonneesMessagerie($pdo,$types_donnees_a_exporter) {
|
||||||
|
try {
|
||||||
|
$nom_fichier_csv="Données_Courtail_".date('d-m-Y').".csv";
|
||||||
|
|
||||||
|
// Entêtes HTTP permettant le téléchargement à la volée du CSV
|
||||||
|
header("Content-Disposition: attachment; filename=\"$nom_fichier_csv\"");
|
||||||
|
header("Content-Type: text/csv");
|
||||||
|
|
||||||
|
foreach ($types_donnees_a_exporter as $cle_donnees_a_exporter => $type_donnee_a_exporter) {
|
||||||
|
switch ($type_donnee_a_exporter) {
|
||||||
|
case "alias_virtuels":
|
||||||
|
$req = 'SELECT * FROM postfix_alias_virtuels';
|
||||||
|
$sql=$pdo->prepare($req);
|
||||||
|
$sql->execute();
|
||||||
|
|
||||||
|
$liste_alias_virtuels = $sql->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
|
echo "#~// Alias_vituels\n";
|
||||||
|
foreach ($liste_alias_virtuels as $alias_virtuel => $champ_alias_virtuel) {
|
||||||
|
echo implode(":", $champ_alias_virtuel)."\n";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "domaines":
|
||||||
|
$req = 'SELECT * FROM postfix_domaines';
|
||||||
|
$sql=$pdo->prepare($req);
|
||||||
|
$sql->execute();
|
||||||
|
|
||||||
|
$liste_domaines = $sql->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
|
echo "#~// Domaines\n";
|
||||||
|
foreach ($liste_domaines as $domaine => $champ_domaine) {
|
||||||
|
echo implode(":", $champ_domaine)."\n";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "liste_noire_destinataires":
|
||||||
|
$req = 'SELECT * FROM postfix_liste_noire_destinataires';
|
||||||
|
$sql=$pdo->prepare($req);
|
||||||
|
$sql->execute();
|
||||||
|
|
||||||
|
$liste_liste_noire_destinataires = $sql->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
|
echo "#~// Liste_noire_destinataires\n";
|
||||||
|
foreach ($liste_liste_noire_destinataires as $liste_noire_destinataire => $champ_liste_noire_destinataire) {
|
||||||
|
echo implode(":", $champ_liste_noire_destinataire)."\n";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "liste_noire_expediteurs":
|
||||||
|
$req = 'SELECT * FROM postfix_liste_noire_expediteurs';
|
||||||
|
$sql=$pdo->prepare($req);
|
||||||
|
$sql->execute();
|
||||||
|
|
||||||
|
$liste_liste_noire_expediteurs = $sql->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
|
echo "#~// Liste_noire_expéditeur\n";
|
||||||
|
foreach ($liste_liste_noire_expediteurs as $liste_noire_expediteur => $champ_liste_noire_expediteur) {
|
||||||
|
echo implode(":", $champ_liste_noire_expediteur)."\n";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "utilisateurs":
|
||||||
|
$req = 'SELECT * FROM postfix_utilisateurs';
|
||||||
|
$sql=$pdo->prepare($req);
|
||||||
|
$sql->execute();
|
||||||
|
|
||||||
|
$liste_utilisateurs = $sql->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
|
echo "#~// Utilisateurs\n";
|
||||||
|
foreach ($liste_utilisateurs as $liste_utilisateur => $champ_utilisateur) {
|
||||||
|
echo implode(":", $champ_utilisateur)."\n";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Le fait de tuer la page enclenche la demande de téléchargement à l'utilisateur qui ne quitte visuellement jamais la page des paramètres
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
catch (\Exception $e) {
|
||||||
|
die ("Erreur de requête d'export des données de la base en CSV : ".$e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fonction important un fichier d'export d'alias virtuels utilisateur en CSV vers la base de données.
|
||||||
|
*/
|
||||||
|
function importAliasVirtuelsUtilisateur($pdo,$alias_virtuel,$utilisateur,$active) {
|
||||||
|
try {
|
||||||
|
// Insertion de l'alias virtuels parcouru dans le fichier CSV soumis pas l'utilisateur
|
||||||
|
// Les contrôles de données ont étés effectués dans la page de traitement
|
||||||
|
$req = 'INSERT INTO postfix_alias_virtuels (courriel,destination,active) VALUES (:alias_virtuel,:destination,:active)';
|
||||||
|
$sql=$pdo->prepare($req);
|
||||||
|
$sql->bindValue(':alias_virtuel',htmlspecialchars($alias_virtuel));
|
||||||
|
$sql->bindValue(':destination',htmlspecialchars($utilisateur));
|
||||||
|
$sql->bindValue(':active',$active);
|
||||||
|
$sql->execute();
|
||||||
|
|
||||||
|
if ($sql->rowCount() == 1){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (\Exception $e) {
|
||||||
|
// Récupération du code de retour de la commande SQLite
|
||||||
|
$code_retour=$sql->errorInfo();
|
||||||
|
|
||||||
|
if ($code_retour[0]=="23000") {
|
||||||
|
// Code de retour envoyé par le pilote PDO SQLite signifiant que la contrainte "UNIQUE" du champ "courriel" de la table "postif_alias_virtuels" est violée. Dans la mesure ou un contrôle d'unicité est effectué par la page de traitement, cette erreur signifie qu'un bogue est présent dans celui-ci
|
||||||
|
header ("Location: /pages/gestion/administration.php?page=alias&erreur=3");
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
elseif ($code_retour[0]=="HY000") {
|
||||||
|
// Code de retour envoyé par le pilote PDO SQLite lorsque la base de données n'est accessible qu'en lecture seule à www-data
|
||||||
|
header ("Location: /pages/gestion/administration.php?page=alias&erreur=4");
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// En cas d'erreur non gérée, le script s'arrête avec un message d'erreur à destination de l'administrateur du serveur
|
||||||
|
die ("Erreur de requête d'import des alias virtuels utilisateur en CSV : ".$e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fonction important les données sauvegardées dans un fichier CSV par un administrateur avec la fonction exportDonneesMessagerie().
|
||||||
|
*/
|
||||||
|
function importDonneesMessagerie($pdo,$type_donnees_csv,$donnees_csv) {
|
||||||
|
try {
|
||||||
|
switch ($type_donnees_csv) {
|
||||||
|
case "alias_virtuels":
|
||||||
|
$req = 'INSERT INTO postfix_alias_virtuels (courriel,destination,active) VALUES (:alias_virtuel,:destination,:active)';
|
||||||
|
$sql=$pdo->prepare($req);
|
||||||
|
$sql->bindValue(':alias_virtuel',htmlspecialchars($donnees_csv[1]));
|
||||||
|
$sql->bindValue(':destination',htmlspecialchars($donnees_csv[2]));
|
||||||
|
$sql->bindValue(':active',$donnees_csv[3]);
|
||||||
|
$sql->execute();
|
||||||
|
|
||||||
|
if ($sql->rowCount() == 1){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "domaines":
|
||||||
|
$req = 'INSERT INTO postfix_domaines (domaine,defaut,active) VALUES (:domaine,:defaut,:active)';
|
||||||
|
$sql=$pdo->prepare($req);
|
||||||
|
$sql->bindValue(':domaine',htmlspecialchars($donnees_csv[1]));
|
||||||
|
$sql->bindValue(':defaut',htmlspecialchars($donnees_csv[2]));
|
||||||
|
$sql->bindValue(':active',$donnees_csv[3]);
|
||||||
|
$sql->execute();
|
||||||
|
|
||||||
|
if ($sql->rowCount() == 1){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "liste_noire_destinataires":
|
||||||
|
$req = 'INSERT INTO postfix_liste_noire_destinataires (courriel,action,active) VALUES (:courriel,:action,:active)';
|
||||||
|
$sql=$pdo->prepare($req);
|
||||||
|
$sql->bindValue(':courriel',htmlspecialchars($donnees_csv[1]));
|
||||||
|
$sql->bindValue(':action',htmlspecialchars($donnees_csv[2]));
|
||||||
|
$sql->bindValue(':active',$donnees_csv[3]);
|
||||||
|
$sql->execute();
|
||||||
|
|
||||||
|
if ($sql->rowCount() == 1){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "liste_noire_expediteurs":
|
||||||
|
$req = 'INSERT INTO postfix_liste_noire_expediteurs (courriel,code_retour,message,active) VALUES (:courriel,:code_retour,:message,:active)';
|
||||||
|
$sql=$pdo->prepare($req);
|
||||||
|
$sql->bindValue(':courriel',htmlspecialchars($donnees_csv[1]));
|
||||||
|
$sql->bindValue(':code_retour',htmlspecialchars($donnees_csv[2]));
|
||||||
|
$sql->bindValue(':message',htmlspecialchars($donnees_csv[3]));
|
||||||
|
$sql->bindValue(':active',$donnees_csv[4]);
|
||||||
|
$sql->execute();
|
||||||
|
|
||||||
|
if ($sql->rowCount() == 1){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "utilisateurs":
|
||||||
|
$req = 'INSERT INTO postfix_utilisateurs (utilisateur,mot_de_passe,nom_complet,rep_perso,uid,gid,privilege,prefixe,active) VALUES (:utilisateur,:mot_de_passe,:nom_complet,:rep_perso,:uid,:gid,:privilege,:prefixe,:active)';
|
||||||
|
$sql=$pdo->prepare($req);
|
||||||
|
$sql->bindValue(':utilisateur',htmlspecialchars($donnees_csv[1]));
|
||||||
|
$sql->bindValue(':mot_de_passe',htmlspecialchars($donnees_csv[2]));
|
||||||
|
$sql->bindValue(':nom_complet',htmlspecialchars($donnees_csv[3]));
|
||||||
|
$sql->bindValue(':rep_perso',$donnees_csv[4]);
|
||||||
|
$sql->bindValue(':uid',$donnees_csv[5]);
|
||||||
|
$sql->bindValue(':gid',$donnees_csv[6]);
|
||||||
|
$sql->bindValue(':privilege',$donnees_csv[7]);
|
||||||
|
$sql->bindValue(':prefixe',$donnees_csv[8]);
|
||||||
|
$sql->bindValue(':active',$donnees_csv[9]);
|
||||||
|
$sql->execute();
|
||||||
|
|
||||||
|
if ($sql->rowCount() == 1){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (\Exception $e) {
|
||||||
|
die ("Erreur de requête d'import des données de la base en CSV : ".$e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fonction de purge des tables permettant une importation fidèle des données contenues dans un ficher d'export CSV généré par la fonction exportDonneesMessagerie().
|
||||||
|
*/
|
||||||
|
function purgeTable($pdo,$table) {
|
||||||
|
try {
|
||||||
|
switch ($table) {
|
||||||
|
case "postfix_alias_virtuels":
|
||||||
|
$sql = $pdo->prepare('DELETE FROM postfix_alias_virtuels');
|
||||||
|
$sql->execute();
|
||||||
|
$sql = $pdo->prepare('UPDATE sqlite_sequence SET seq = 0 WHERE name = "postfix_alias_virtuels"');
|
||||||
|
$sql->execute();
|
||||||
|
$sql = $pdo->prepare('VACUUM');
|
||||||
|
$sql->execute();
|
||||||
|
break;
|
||||||
|
case "postfix_domaines":
|
||||||
|
$sql = $pdo->prepare('DELETE FROM postfix_domaines');
|
||||||
|
$sql->execute();
|
||||||
|
$sql = $pdo->prepare('UPDATE sqlite_sequence SET seq = 0 WHERE name = "postfix_domaines"');
|
||||||
|
$sql->execute();
|
||||||
|
$sql = $pdo->prepare('VACUUM');
|
||||||
|
$sql->execute();
|
||||||
|
break;
|
||||||
|
case "postfix_liste_noire_destinataires":
|
||||||
|
$sql = $pdo->prepare('DELETE FROM postfix_liste_noire_destinataires');
|
||||||
|
$sql->execute();
|
||||||
|
$sql = $pdo->prepare('UPDATE sqlite_sequence SET seq = 0 WHERE name = "postfix_liste_noire_destinataires"');
|
||||||
|
$sql->execute();
|
||||||
|
$sql = $pdo->prepare('VACUUM');
|
||||||
|
$sql->execute();
|
||||||
|
break;
|
||||||
|
case "postfix_liste_noire_expediteurs":
|
||||||
|
$sql = $pdo->prepare('DELETE FROM postfix_liste_noire_expediteurs');
|
||||||
|
$sql->execute();
|
||||||
|
$sql = $pdo->prepare('UPDATE sqlite_sequence SET seq = 0 WHERE name = "postfix_liste_noire_expediteurs"');
|
||||||
|
$sql->execute();
|
||||||
|
$sql = $pdo->prepare('VACUUM');
|
||||||
|
$sql->execute();
|
||||||
|
break;
|
||||||
|
case "postfix_utilisateurs":
|
||||||
|
$sql = $pdo->prepare('DELETE FROM postfix_utilisateurs');
|
||||||
|
$sql->execute();
|
||||||
|
$sql = $pdo->prepare('UPDATE sqlite_sequence SET seq = 0 WHERE name = "postfix_utilisateurs"');
|
||||||
|
$sql->execute();
|
||||||
|
$sql = $pdo->prepare('VACUUM');
|
||||||
|
$sql->execute();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (\Exception $e) {
|
||||||
|
die ("Erreur de requête de purge d'une table : ".$e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
@ -0,0 +1,261 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Page de fonctions concernant les entrées de la liste noire des destinataires.
|
||||||
|
*/
|
||||||
|
|
||||||
|
require_once ($_SERVER["DOCUMENT_ROOT"]."/services/fonctions/bdd/connexion.php");
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fonction listant les entrées de la liste noire des destinataires.
|
||||||
|
*/
|
||||||
|
function listeEntreeListeNoireDstPostfix($pdo) {
|
||||||
|
try {
|
||||||
|
$req = 'SELECT * FROM postfix_liste_noire_destinataires';
|
||||||
|
|
||||||
|
$sql=$pdo->prepare($req);
|
||||||
|
$sql->execute();
|
||||||
|
|
||||||
|
$liste_entree_liste_noire_dst = $sql->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
return $liste_entree_liste_noire_dst;
|
||||||
|
}
|
||||||
|
catch (\Exception $e) {
|
||||||
|
die ("Erreur de requête de selection des entrées de liste noire destinataires pour \"$base\" : ".$e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fonction listant les entrées de la liste noire des expéditeurs.
|
||||||
|
*/
|
||||||
|
function listeEntreeListeNoireExpPostfix($pdo) {
|
||||||
|
try {
|
||||||
|
$req = 'SELECT * FROM postfix_liste_noire_expediteurs';
|
||||||
|
|
||||||
|
$sql=$pdo->prepare($req);
|
||||||
|
$sql->execute();
|
||||||
|
|
||||||
|
$liste_entree_liste_noire_exp = $sql->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
return $liste_entree_liste_noire_exp;
|
||||||
|
}
|
||||||
|
catch (\Exception $e) {
|
||||||
|
die ("Erreur de requête de selection des entrées de liste noire expéditeurs : ".$e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fonction d'ajout d'une entrée de liste noir destinataire.
|
||||||
|
*/
|
||||||
|
function ajoutEntreeListeNoireDstPostfix($pdo,$courriel_entree_liste_noire_dst,$action_entree_liste_noire_dst) {
|
||||||
|
try {
|
||||||
|
// Insertion de l'entrée de liste noire de destinataires renseignée par l'administrateur
|
||||||
|
$req='INSERT INTO postfix_liste_noire_destinataires (courriel,action,active) VALUES (:courriel,:action,1)';
|
||||||
|
$sql=$pdo->prepare($req);
|
||||||
|
$sql->bindValue(':courriel',substr(htmlspecialchars($courriel_entree_liste_noire_dst),0,100));
|
||||||
|
$sql->bindValue(':action',$action_entree_liste_noire_dst);
|
||||||
|
$sql->execute();
|
||||||
|
|
||||||
|
if ($sql->rowCount() == 1){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (\Exception $e) {
|
||||||
|
// Récupération du code de retour de la commande SQLite
|
||||||
|
$code_retour=$sql->errorInfo();
|
||||||
|
|
||||||
|
if ($code_retour[0]=="23000") {
|
||||||
|
// Code de retour envoyé par le pilote PDO SQLite signifiant que la contrainte "UNIQUE" du champ "courriel" de la table "postfix_liste_noire_destinataires" est violée. L'adresse de destination envoyé via le formulaire par l'utilisateur a déjà été renseignée dans la base
|
||||||
|
header ("Location: /pages/gestion/administration.php?page=listes_noires&sousPage=destinataires&erreur=12");
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
elseif ($code_retour[0]=="HY000") {
|
||||||
|
// Code de retour envoyé par le pilote PDO SQLite lorsque la base de données n'est accessible qu'en lecture seule à www-data
|
||||||
|
header ("Location: /pages/gestion/administration.php?page=listes_noires&sousPage=destinataires&erreur=4");
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// En cas d'erreur non gérée, le script s'arrête avec un message d'erreur à destination de l'administrateur du serveur
|
||||||
|
die ("Erreur de requête d'ajout de l'entrée de liste noire de destinataires : ".$e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fonction d'ajout d'une entrée de liste noir expéditeurs.
|
||||||
|
*/
|
||||||
|
function ajoutEntreeListeNoireExpPostfix($pdo,$courriel_entree_liste_noire_exp,$code_retour_entree_liste_noire_exp) {
|
||||||
|
try {
|
||||||
|
// Insertion de l'entrée de liste noire d'expéditeurs renseignée par l'administrateur
|
||||||
|
$req='INSERT INTO postfix_liste_noire_expediteurs (courriel,code_retour,message,active) VALUES (:courriel,:code_retour,"Votre message a été rejeté par le serveur car votre adresse est en liste noire.",1)';
|
||||||
|
$sql=$pdo->prepare($req);
|
||||||
|
$sql->bindValue(':courriel',substr(htmlspecialchars($courriel_entree_liste_noire_exp),0,100));
|
||||||
|
$sql->bindValue(':code_retour',$code_retour_entree_liste_noire_exp);
|
||||||
|
$sql->execute();
|
||||||
|
|
||||||
|
if ($sql->rowCount() == 1){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (\Exception $e) {
|
||||||
|
// Récupération du code de retour de la commande SQLite
|
||||||
|
$code_retour=$sql->errorInfo();
|
||||||
|
if ($code_retour[0]=="23000") {
|
||||||
|
// Code de retour envoyé par le pilote PDO SQLite signifiant que la contrainte "UNIQUE" du champ "courriel" de la table "postfix_liste_noire_expediteurs" est violée. L'adresse de destination envoyé via le formulaire par l'utilisateur a déjà été renseignée dans la base
|
||||||
|
header ("Location: /pages/gestion/administration.php?page=listes_noires&sousPage=expediteurs&erreur=16");
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
elseif ($code_retour[0]=="HY000") {
|
||||||
|
// Code de retour envoyé par le pilote PDO SQLite lorsque la base de données n'est accessible qu'en lecture seule à www-data
|
||||||
|
header ("Location: /pages/gestion/administration.php?page=listes_noires&sousPage=expediteurs&erreur=4");
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// En cas d'erreur non gérée, le script s'arrête avec un message d'erreur à destination de l'administrateur du serveur
|
||||||
|
die ("Erreur de requête d'ajout de l'entrée de liste noire d'expéditeurs : ".$e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fonction d'activation/désactivation d'une entrée dans la liste noire des destinataires.
|
||||||
|
* Suite à une soumission du formulaire dédié, cette fonction va traiter l'ensemble des entrées de la liste noire des destinataires du serveur.
|
||||||
|
* Elle occasionnera peut-être des baisses de performance si un très grand d'entrées existent (le traitement n'intervenant pas spécifiquement pour l'entrée modifiée).
|
||||||
|
*/
|
||||||
|
function modifEntreeListeNoireDstPostfix($pdo,$retour_form) {
|
||||||
|
try {
|
||||||
|
$compteModifs=0;
|
||||||
|
foreach ($retour_form as $id_entree_liste_noire_dst => $etat_entree_liste_noire_dst) {
|
||||||
|
$req='UPDATE postfix_liste_noire_destinataires SET active=:etat_entree_liste_noire_dst WHERE id=:id_entree_liste_noire_dst';
|
||||||
|
|
||||||
|
$sql=$pdo->prepare($req);
|
||||||
|
$sql->bindValue(':etat_entree_liste_noire_dst',$etat_entree_liste_noire_dst);
|
||||||
|
$sql->bindValue(':id_entree_liste_noire_dst',$id_entree_liste_noire_dst);
|
||||||
|
$sql->execute();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (\Exception $e) {
|
||||||
|
// Récupération du code de retour de la commande SQLite
|
||||||
|
$code_retour=$sql->errorInfo();
|
||||||
|
|
||||||
|
if ($code_retour[0]=="HY000") {
|
||||||
|
// Code de retour envoyé par le pilote PDO SQLite lorsque la base est accessible en lecture seule à www-data
|
||||||
|
header ("Location: /pages/gestion/administration.php?page=listes_noires&sousPage=destinataires&erreur=10");
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// En cas d'erreur non gérée, le script s'arrête avec un message d'erreur à destination de l'administrateur du serveur
|
||||||
|
die ("Erreur de requête de modification d'état pour l'entrée de liste noire de destinataires : ".$e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fonction d'activation/désactivation d'une entrée dans la liste noire des expéditeurs.
|
||||||
|
* Suite à une soumission du formulaire dédié, cette fonction va traiter l'ensemble des entrées de la liste noire des expéditeurs du serveur.
|
||||||
|
* Elle occasionnera peut-être des baisses de performance si un très grand d'entrées existent (le traitement n'intervenant pas spécifiquement pour l'entrée modifiée).
|
||||||
|
*/
|
||||||
|
function modifEntreeListeNoireExpPostfix($pdo,$retour_form) {
|
||||||
|
try {
|
||||||
|
$compteModifs=0;
|
||||||
|
foreach ($retour_form as $id_entree_liste_noire_exp => $etat_entree_liste_noire_exp) {
|
||||||
|
$req='UPDATE postfix_liste_noire_expediteurs SET active=:etat_entree_liste_noire_exp WHERE id=:id_entree_liste_noire_exp';
|
||||||
|
|
||||||
|
$sql=$pdo->prepare($req);
|
||||||
|
$sql->bindValue(':etat_entree_liste_noire_exp',$etat_entree_liste_noire_exp);
|
||||||
|
$sql->bindValue(':id_entree_liste_noire_exp',$id_entree_liste_noire_exp);
|
||||||
|
$sql->execute();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (\Exception $e) {
|
||||||
|
// Récupération du code de retour de la commande SQLite
|
||||||
|
$code_retour=$sql->errorInfo();
|
||||||
|
|
||||||
|
if ($code_retour[0]=="HY000") {
|
||||||
|
// Code de retour envoyé par le pilote PDO SQLite lorsque la base est accessible en lecture seule à www-data
|
||||||
|
header ("Location: /pages/gestion/administration.php?page=listes_noires&sousPage=expediteurs&erreur=14");
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// En cas d'erreur non gérée, le script s'arrête avec un message d'erreur à destination de l'administrateur du serveur
|
||||||
|
die ("Erreur de requête de modification d'état pour l'entrée de liste noire d'expéditeurs : ".$e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fonction de suppression d'une entrée de liste noire de destinataires.
|
||||||
|
*/
|
||||||
|
function supprEntreeListeNoireDstPostfix($pdo) {
|
||||||
|
try {
|
||||||
|
$req='DELETE FROM postfix_liste_noire_destinataires WHERE id=:id_entree_liste_noire_dst';
|
||||||
|
|
||||||
|
$sql=$pdo->prepare($req);
|
||||||
|
$sql->bindValue(':id_entree_liste_noire_dst',$_GET['supprEntreeListeNoireDst']);
|
||||||
|
$sql->execute();
|
||||||
|
|
||||||
|
if($sql->rowCount() == 1){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (\Exception $e) {
|
||||||
|
// Récupération du code de retour de la commande SQLite
|
||||||
|
$code_retour=$sql->errorInfo();
|
||||||
|
|
||||||
|
if ($code_retour[0]=="HY000") {
|
||||||
|
// Code de retour envoyé par le pilote PDO SQLite lorsque la base est accessible en lecture seule à www-data
|
||||||
|
header ("Location: /pages/gestion/administration.php?page=listes_noires&sousPage=destinataires&erreur=4");
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// En cas d'erreur non gérée, le script s'arrête avec un message d'erreur à destination de l'administrateur du serveur
|
||||||
|
die ("Erreur de requête de suppression d'une entrée de liste noire de destinataires : ".$e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fonction de suppression d'une entrée de liste noire d'expéditeurs.
|
||||||
|
*/
|
||||||
|
function supprEntreeListeNoireExpPostfix($pdo) {
|
||||||
|
try {
|
||||||
|
$req='DELETE FROM postfix_liste_noire_expediteurs WHERE id=:id_entree_liste_noire_exp';
|
||||||
|
|
||||||
|
$sql=$pdo->prepare($req);
|
||||||
|
$sql->bindValue(':id_entree_liste_noire_exp',$_GET['supprEntreeListeNoireExp']);
|
||||||
|
$sql->execute();
|
||||||
|
|
||||||
|
if($sql->rowCount() == 1){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (\Exception $e) {
|
||||||
|
// Récupération du code de retour de la commande SQLite
|
||||||
|
$code_retour=$sql->errorInfo();
|
||||||
|
|
||||||
|
if ($code_retour[0]=="HY000") {
|
||||||
|
// Code de retour envoyé par le pilote PDO SQLite lorsque la base est accessible en lecture seule à www-data
|
||||||
|
header ("Location: /pages/gestion/administration.php?page=listes_noires&sousPage=expediteurs&erreur=4");
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// En cas d'erreur non gérée, le script s'arrête avec un message d'erreur à destination de l'administrateur du serveur
|
||||||
|
die ("Erreur de requête de suppression d'une entrée de liste noire d'expéditeurs : ".$e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
@ -0,0 +1,165 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Page de fonctions permettant la gestion des utilisateurs.
|
||||||
|
*/
|
||||||
|
|
||||||
|
require_once ($_SERVER["DOCUMENT_ROOT"]."/services/fonctions/bdd/connexion.php");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fonction listant les utilisateurs.
|
||||||
|
*/
|
||||||
|
function listeUtilisateursPostfix($pdo) {
|
||||||
|
try {
|
||||||
|
$req = 'SELECT utilisateur FROM postfix_utilisateurs';
|
||||||
|
$sql=$pdo->prepare($req);
|
||||||
|
$sql->execute();
|
||||||
|
|
||||||
|
$liste_utilisateurs = $sql->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
return $liste_utilisateurs;
|
||||||
|
}
|
||||||
|
catch (\Exception $e) {
|
||||||
|
die ("Erreur de requête de selection des utilisateurs : ".$e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fonction vérifiant le mot de passe actuel d'un utilisateur.
|
||||||
|
*/
|
||||||
|
function verificationMotDePasseUtilisateurPostfix($pdo,$identifiant,$mdp) {
|
||||||
|
try {
|
||||||
|
$req = 'SELECT mot_de_passe FROM postfix_utilisateurs WHERE utilisateur=:identifiant';
|
||||||
|
|
||||||
|
$sql = $pdo->prepare($req);
|
||||||
|
$sql->bindValue(':identifiant', $identifiant);
|
||||||
|
$sql->execute();
|
||||||
|
|
||||||
|
$result = $sql ->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
$comptage = count($result);
|
||||||
|
|
||||||
|
}
|
||||||
|
catch(PDOException $e) {
|
||||||
|
die ("Erreur lors du traitement de la requête de vérification du mot de passe utilisateur : " . $e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($comptage == 1) {
|
||||||
|
|
||||||
|
$mot_de_passe_base=explode('$', $result['0']['mot_de_passe']);
|
||||||
|
$mot_de_passe_form=crypt(trim("$mdp"), "$".$mot_de_passe_base[1]."$".$mot_de_passe_base[2]."$");
|
||||||
|
|
||||||
|
if ("$".$mot_de_passe_base[1]."$".$mot_de_passe_base[2]."$".$mot_de_passe_base[3]==$mot_de_passe_form) {
|
||||||
|
// Si le mot de passe renseigné n'est le bon, le visiteur est redirigé vers la page d'accueil avec un message explicatif
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fonction changeant le mot de passe d'un utilisateur.
|
||||||
|
*/
|
||||||
|
function changeMotDePasseUtilisateurPostfix($pdo,$utilisateur,$nouveau_mdp,$confirmation_mdp) {
|
||||||
|
if ($nouveau_mdp===$confirmation_mdp) {
|
||||||
|
$caracters = '.0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
||||||
|
$chaine_aleatoire = '';
|
||||||
|
|
||||||
|
// Génération d'un sel à 16 caractères
|
||||||
|
for ($i = 0; $i < 16; $i++) {
|
||||||
|
$index = rand(0, strlen($caracters) - 1);
|
||||||
|
$chaine_aleatoire .= $caracters[$index];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Construction d'un mot de passe haché compatible avec Dovecot
|
||||||
|
$mot_de_passe_hachis='{SHA512-CRYPT}'.crypt(trim($nouveau_mdp),'$6$'.$chaine_aleatoire);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$req = 'UPDATE postfix_utilisateurs SET mot_de_passe=:nouveau_mdp WHERE utilisateur=:utilisateur';
|
||||||
|
$sql=$pdo->prepare($req);
|
||||||
|
$sql->bindValue(':utilisateur', $utilisateur);
|
||||||
|
$sql->bindValue(':nouveau_mdp', $mot_de_passe_hachis);
|
||||||
|
$sql->execute();
|
||||||
|
}
|
||||||
|
catch (\Exception $e) {
|
||||||
|
die ("Erreur de requête de changement de mot de passe utilisateur : ".$e->getMessage());
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fonction listant le préfixe de l'utilisateur courant.
|
||||||
|
*/
|
||||||
|
function retournePrefixeUtilisateurPostfix($pdo,$utilisateur) {
|
||||||
|
try {
|
||||||
|
$req = 'SELECT prefixe FROM postfix_utilisateurs WHERE utilisateur=:utilisateur';
|
||||||
|
$sql=$pdo->prepare($req);
|
||||||
|
$sql->bindValue(':utilisateur', $utilisateur);
|
||||||
|
$sql->execute();
|
||||||
|
|
||||||
|
$prefixe_utilisateurs = $sql->fetchAll();
|
||||||
|
|
||||||
|
if (isset($prefixe_utilisateurs[0]['prefixe'])) {
|
||||||
|
return $prefixe_utilisateurs[0]['prefixe'];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$prefixe_utilisateurs[0]['prefixe']="";
|
||||||
|
return $prefixe_utilisateurs[0]['prefixe'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (\Exception $e) {
|
||||||
|
die ("Erreur de requête de changement de préfixe utilisateur : ".$e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fonction changeant le préfixe d'un utilisateur.
|
||||||
|
*/
|
||||||
|
function changePrefixeUtilisateurPostfix($pdo,$utilisateur,$nouveau_prefixe) {
|
||||||
|
try {
|
||||||
|
$req = 'UPDATE postfix_utilisateurs SET prefixe=:nouveau_prefixe WHERE utilisateur=:utilisateur';
|
||||||
|
$sql=$pdo->prepare($req);
|
||||||
|
$sql->bindValue(':utilisateur', $utilisateur);
|
||||||
|
$sql->bindValue(':nouveau_prefixe', $nouveau_prefixe);
|
||||||
|
$sql->execute();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (\Exception $e) {
|
||||||
|
die ("Erreur de requête de changement de préfixe utilisateur : ".$e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fonction vérifiant que l'utilisateur connecté au site existe toujours dans la base de données.
|
||||||
|
*/
|
||||||
|
function verifUtilisateursExiste($pdo,$utilisateur) {
|
||||||
|
try {
|
||||||
|
$req = 'SELECT utilisateur FROM postfix_utilisateurs WHERE utilisateur=:utilisateur';
|
||||||
|
$sql=$pdo->prepare($req);
|
||||||
|
$sql->bindValue(':utilisateur', $utilisateur);
|
||||||
|
$sql->execute();
|
||||||
|
|
||||||
|
$liste_utilisateurs = $sql->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
|
if (count($liste_utilisateurs) === 1) {
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (\Exception $e) {
|
||||||
|
die ("Erreur de requête de vérification d'existence de l'utilisateur connecté : ".$e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
?>
|
@ -0,0 +1,79 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fonction affichant les messages de retour des traitements site lorsqu'elle est interrogée.
|
||||||
|
*/
|
||||||
|
function retourneMessage($type_message,$num_message) {
|
||||||
|
if ($type_message=="succes" || $type_message=="erreurs" || $type_message=="messages") {
|
||||||
|
if (isset($_SESSION) && !empty($_SESSION['pseudo_utilisateur']) || !empty($_SESSION['nom_utilisateur']) || !empty($_SESSION['privilege_utilisateur'])) {
|
||||||
|
$pseudo_utilisateur=$_SESSION['pseudo_utilisateur'];
|
||||||
|
$nom_utilisateur=$_SESSION['nom_utilisateur'];
|
||||||
|
$privilege_utilisateur=$_SESSION['privilege_utilisateur'];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$pseudo_utilisateur="visiteur";
|
||||||
|
$nom_utilisateur="visiteur";
|
||||||
|
$privilege_utilisateur="visiteur";
|
||||||
|
}
|
||||||
|
$liste_messages = array (
|
||||||
|
"succes" => array(
|
||||||
|
1 => "<div class=\"alert alert-success\" role=\"alert\"><img src=\"/fichiers/svg/check-circle.svg\"/> Alias virtuel créé avec succès.</div>",
|
||||||
|
2 => "<div class=\"alert alert-success\" role=\"alert\"><img src=\"/fichiers/svg/check-circle.svg\"/> Alias virtuel modifiés avec succès.</div>",
|
||||||
|
3 => "<div class=\"alert alert-success\" role=\"alert\"><img src=\"/fichiers/svg/check-circle.svg\"/> Alias virtuel supprimé avec succès.</div>",
|
||||||
|
4 => "<div class=\"alert alert-success\" role=\"alert\"><img src=\"/fichiers/svg/check-circle.svg\"/> Utilisateur changé en ".$pseudo_utilisateur." avec succès.</div>",
|
||||||
|
5 => "<div class=\"alert alert-success\" role=\"alert\"><img src=\"/fichiers/svg/check-circle.svg\"/> Domaine créé avec succès.</div>",
|
||||||
|
6 => "<div class=\"alert alert-success\" role=\"alert\"><img src=\"/fichiers/svg/check-circle.svg\"/> Domaine modifiés avec succès.</div>",
|
||||||
|
7 => "<div class=\"alert alert-success\" role=\"alert\"><img src=\"/fichiers/svg/check-circle.svg\"/> Domaine supprimé avec succès.</div>",
|
||||||
|
8 => "<div class=\"alert alert-success\" role=\"alert\"><img src=\"/fichiers/svg/check-circle.svg\"/> Domaine défini par défaut avec succès.</div>",
|
||||||
|
9 => "<div class=\"alert alert-success\" role=\"alert\"><img src=\"/fichiers/svg/check-circle.svg\"/> L'entrée de liste noire destiataires a été créée avec succès.</div>",
|
||||||
|
10 => "<div class=\"alert alert-success\" role=\"alert\"><img src=\"/fichiers/svg/check-circle.svg\"/> L'état de l'entrée de liste noire destiataires a été modifié avec succès.</div>",
|
||||||
|
11 => "<div class=\"alert alert-success\" role=\"alert\"><img src=\"/fichiers/svg/check-circle.svg\"/> L'entrée de liste noire destinataires a été supprimée avec succès.</div>",
|
||||||
|
12 => "<div class=\"alert alert-success\" role=\"alert\"><img src=\"/fichiers/svg/check-circle.svg\"/> L'entrée de liste noire expéditeurs a été créée avec succès.</div>",
|
||||||
|
13 => "<div class=\"alert alert-success\" role=\"alert\"><img src=\"/fichiers/svg/check-circle.svg\"/> L'état de l'entrée de liste noire expéditeurs a été modifié avec succès.</div>",
|
||||||
|
14 => "<div class=\"alert alert-success\" role=\"alert\"><img src=\"/fichiers/svg/check-circle.svg\"/> L'entrée de liste noire expéditeurs a été supprimée avec succès.</div>",
|
||||||
|
15 => "<div class=\"alert alert-success\" role=\"alert\"><img src=\"/fichiers/svg/check-circle.svg\"/> Vous avez bien été déconnecté.</div>",
|
||||||
|
16 => "<div class=\"alert alert-success\" role=\"alert\"><img src=\"/fichiers/svg/check-circle.svg\"/> Le mot de passe de $pseudo_utilisateur a bien été changé.</div>",
|
||||||
|
17 => "<div class=\"alert alert-success\" role=\"alert\"><img src=\"/fichiers/svg/check-circle.svg\"/> Le préfixe de $pseudo_utilisateur a bien été changé.</div>",
|
||||||
|
18 => "<div class=\"alert alert-success\" role=\"alert\"><img src=\"/fichiers/svg/check-circle.svg\"/> Vos données ont bien étés importés. Les doublons ainsi que les données erronées ont étés ignorés.</div>",
|
||||||
|
19 => "<div class=\"alert alert-success\" role=\"alert\"><img src=\"/fichiers/svg/check-circle.svg\"/> Vos données ont bien étés importés. Veuillez vous ré-identifier.</div>"),
|
||||||
|
"erreurs" => array(
|
||||||
|
1 => "<div class=\"alert alert-danger\" role=\"alert\"><img src=\"/fichiers/svg/alert-triangle.svg\"/> Aucun alias virtuel supprimé.</div>",
|
||||||
|
2 => "<div class=\"alert alert-danger\" role=\"alert\"><img src=\"/fichiers/svg/alert-triangle.svg\"/> Aucun alias virtuel créé car une donnée est erronée ou manquante.</div>",
|
||||||
|
3 => "<div class=\"alert alert-danger\" role=\"alert\"><img src=\"/fichiers/svg/alert-triangle.svg\"/> L'alias virtuel est déjà existant.</div>",
|
||||||
|
4 => "<div class=\"alert alert-danger\" role=\"alert\"><img src=\"/fichiers/svg/alert-triangle.svg\"/> Code d'erreur générique (HY000) signifiant probablement que la base SQLite n'est pas accessible en écriture. Il faut que la base et le répertoire <i>bdd</i> appartiennent à <i>www-data</i>.</div>",
|
||||||
|
5 => "<div class=\"alert alert-danger\" role=\"alert\"><img src=\"/fichiers/svg/alert-triangle.svg\"/> Aucun domaine supprimé.</div>",
|
||||||
|
6 => "<div class=\"alert alert-danger\" role=\"alert\"><img src=\"/fichiers/svg/alert-triangle.svg\"/> Aucun domaine créé car une donnée est erronée ou manquante.</div>",
|
||||||
|
7 => "<div class=\"alert alert-danger\" role=\"alert\"><img src=\"/fichiers/svg/alert-triangle.svg\"/> Le domaine est déjà existant.</div>",
|
||||||
|
8 => "<div class=\"alert alert-danger\" role=\"alert\"><img src=\"/fichiers/svg/alert-triangle.svg\"/> Le domaine par défaut n'a pas été modifié.</div>",
|
||||||
|
9 => "<div class=\"alert alert-danger\" role=\"alert\"><img src=\"/fichiers/svg/alert-triangle.svg\"/> L'entrée de liste noire destinataires n'a pas été ajouté car une donnée est erronée ou manquante.</div>",
|
||||||
|
10 => "<div class=\"alert alert-danger\" role=\"alert\"><img src=\"/fichiers/svg/alert-triangle.svg\"/> L'état de l'entrée de liste noire destinataires n'a pas été modifié.</div>",
|
||||||
|
11 => "<div class=\"alert alert-danger\" role=\"alert\"><img src=\"/fichiers/svg/alert-triangle.svg\"/> L'entrée de liste noire destinataires n'a pas été supprimée.</div>",
|
||||||
|
12 => "<div class=\"alert alert-danger\" role=\"alert\"><img src=\"/fichiers/svg/alert-triangle.svg\"/> L'entrée de liste noire destinataires n'a pas été ajouté car elle est déjà existante.</div>",
|
||||||
|
13 => "<div class=\"alert alert-danger\" role=\"alert\"><img src=\"/fichiers/svg/alert-triangle.svg\"/> L'entrée de liste noire expéditeurs n'a pas été ajouté car une donnée est erronée ou manquante.</div>",
|
||||||
|
14 => "<div class=\"alert alert-danger\" role=\"alert\"><img src=\"/fichiers/svg/alert-triangle.svg\"/> L'état de l'entrée de liste noire expéditeurs n'a pas été modifié.</div>",
|
||||||
|
15 => "<div class=\"alert alert-danger\" role=\"alert\"><img src=\"/fichiers/svg/alert-triangle.svg\"/> L'entrée de liste noire expéditeurs n'a pas été supprimée.</div>",
|
||||||
|
16 => "<div class=\"alert alert-danger\" role=\"alert\"><img src=\"/fichiers/svg/alert-triangle.svg\"/> L'entrée de liste noire expéditeurs n'a pas été ajouté car elle est déjà existante.</div>",
|
||||||
|
17 => "<div class=\"alert alert-danger\" role=\"alert\"><img src=\"/fichiers/svg/alert-triangle.svg\"/> Identifiant ou mot de passe incorrecte.</div>",
|
||||||
|
18 => "<div class=\"alert alert-danger\" role=\"alert\"><img src=\"/fichiers/svg/alert-triangle.svg\"/> Vous n'avez pas les privilèges nécessaires.</div>",
|
||||||
|
19 => "<div class=\"alert alert-danger\" role=\"alert\"><img src=\"/fichiers/svg/alert-triangle.svg\"/> Erreur non gérée.</div>",
|
||||||
|
20 => "<div class=\"alert alert-danger\" role=\"alert\"><img src=\"/fichiers/svg/alert-triangle.svg\"/> L'ancien mot de passe renseigné est erroné.</div>",
|
||||||
|
21 => "<div class=\"alert alert-danger\" role=\"alert\"><img src=\"/fichiers/svg/alert-triangle.svg\"/> Le mot de passe de confimation n'est pas identique au nouveau mot de passe.</div>",
|
||||||
|
22 => "<div class=\"alert alert-danger\" role=\"alert\"><img src=\"/fichiers/svg/alert-triangle.svg\"/> Une erreur s'est produite lors de l'envoi du fichier. Il doit être de type CSV de moins de 2 Mo et avoir été généré par Courtail.</div>",
|
||||||
|
23 => "<div class=\"alert alert-danger\" role=\"alert\"><img src=\"/fichiers/svg/alert-triangle.svg\"/> Votre fichier d'import CSV est plus grand que 2 Mo.</div>",
|
||||||
|
24 => "<div class=\"alert alert-danger\" role=\"alert\"><img src=\"/fichiers/svg/alert-triangle.svg\"/> Auncun type de donnée n'a été spécifié pour l'importation.</div>"),
|
||||||
|
"messages" => array(
|
||||||
|
"bienvenue" => "<div class=\"alert alert-primary\" role=\"alert\"><img src=\"/fichiers/svg/info.svg\"/> Bienvenue ".$nom_utilisateur.". Vous êtes authentifié en tant qu'".$privilege_utilisateur.".</div>")
|
||||||
|
);
|
||||||
|
|
||||||
|
$num_message=htmlspecialchars($num_message);
|
||||||
|
|
||||||
|
if (isset($liste_messages[$type_message][$num_message])) {
|
||||||
|
echo $liste_messages[$type_message][$num_message];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
echo $liste_messages['erreurs']['19'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
@ -0,0 +1,133 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Page de fonctions permettant d'identifier la légitimité d'un utilisateur.
|
||||||
|
*/
|
||||||
|
|
||||||
|
require_once ($_SERVER["DOCUMENT_ROOT"]."/services/fonctions/bdd/connexion.php");
|
||||||
|
require_once ($_SERVER["DOCUMENT_ROOT"]."/services/fonctions/bdd/domaines.php");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fonction d'authentification des utilisateurs.
|
||||||
|
* Elle récupère le couple identifiant/mot de passe renseigné par le visiteur sur la page d'accueil.
|
||||||
|
* Elle compare ces information avec la ligne correspondante dans la base de donnée (en prenant l'adresse de courriel comme sélecteur).
|
||||||
|
* Elle hache le mot de passe du formulaire et le compare à celui de l'entrée correspondante en base.
|
||||||
|
*/
|
||||||
|
function validationIdentifiants($pdo,$identifiant,$mdp) {
|
||||||
|
try {
|
||||||
|
$req = 'SELECT * FROM postfix_utilisateurs WHERE utilisateur=:identifiant';
|
||||||
|
|
||||||
|
if (!strpos($identifiant, '@')) {
|
||||||
|
$identifiant.="@".retourneDomaineDefautPostfix($pdo);
|
||||||
|
}
|
||||||
|
|
||||||
|
$sql = $pdo->prepare($req);
|
||||||
|
$sql->bindValue(':identifiant', htmlspecialchars($identifiant));
|
||||||
|
$sql->execute();
|
||||||
|
|
||||||
|
$result = $sql ->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
$comptage = count($result);
|
||||||
|
|
||||||
|
}
|
||||||
|
catch(PDOException $e) {
|
||||||
|
die ("Erreur lors du traitement de la requête : " . $e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($comptage == 1) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Les paramètres de la fonction crypt de $mot_de_passe_form sont composés du mot de passe issue du formulaire accueil ainsi que du sel.
|
||||||
|
* Les signes dollars sont des séparateurs. $mot_de_passe_base[1]=6=SHA512. $mot_de_passe_base[2]=au sel du mot de passe contenu dans la base.
|
||||||
|
* Les paramètres de sel sont issus du mot de passe haché contenu dans la base.
|
||||||
|
* L'opération de vérification s'adapte ainsi automatiquement aux algoritmes utilisés par Dovecot lors du hachage du mot de passe utilisateur.
|
||||||
|
*/
|
||||||
|
$mot_de_passe_base=explode('$', $result['0']['mot_de_passe']);
|
||||||
|
$mot_de_passe_form=crypt(trim("$mdp"), "$".$mot_de_passe_base[1]."$".$mot_de_passe_base[2]."$");
|
||||||
|
|
||||||
|
if ("$".$mot_de_passe_base[1]."$".$mot_de_passe_base[2]."$".$mot_de_passe_base[3]!=$mot_de_passe_form) {
|
||||||
|
// Si le mot de passe renseigné n'est le bon, le visiteur est redirigé vers la page d'accueil avec un message explicatif
|
||||||
|
header('Location: /pages/visiteurs/echec_auth.php');
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fonction d'initialisation des valeurs de session.
|
||||||
|
* Elle utilise les informations de l'utilisateur en base de données pour initialiser une session personnalisée.
|
||||||
|
*/
|
||||||
|
function initValeursSession($result) {
|
||||||
|
$_SESSION['id_utilisateur'] = $result[0]['id'];
|
||||||
|
$_SESSION['pseudo_utilisateur'] = $result[0]['utilisateur'];
|
||||||
|
$_SESSION['nom_utilisateur'] = $result[0]['nom_complet'];
|
||||||
|
$_SESSION['privilege_utilisateur'] = $result[0]['privilege'];
|
||||||
|
$_SESSION['pseudo_connexion_utilisateur'] = $result[0]['utilisateur'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fonction de création d'un cookie de connexion automatique.
|
||||||
|
* Si la case "Se souvenir de moi" est cochée au formulaire de connexion, un cookie d'une durée d'un mois est créé.
|
||||||
|
*/
|
||||||
|
function creerCookie($result) {
|
||||||
|
$cookie_params = array (
|
||||||
|
'expires' => time() + 60*60*24*30,
|
||||||
|
'path' => '/',
|
||||||
|
'domain' => $_SERVER['HTTP_HOST'],
|
||||||
|
'secure' => false, // Mettre à true pour ne le créer qu'en HTTPS (le faire également dans "deconnexion.php" et au commentaire "Prolongement de la durée du cookie." plus bas).
|
||||||
|
'httponly' => true,
|
||||||
|
'samesite' => 'Strict'
|
||||||
|
);
|
||||||
|
setcookie('souvenir-session', htmlspecialchars($_SESSION['pseudo_utilisateur']).'|--@--|'.hash('sha3-512', $result['0']['id'].$result['0']['utilisateur'].$result['0']['mot_de_passe']), $cookie_params);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fonction de validation du cookie de connexion automatique.
|
||||||
|
* Vérifie la légitimité du cookie de connexion de l'utilisateur via les informations en base de données.
|
||||||
|
* Si légitime, une session PHP est initialisée et le cookie est renouvelé pour un mois supplémentaire.
|
||||||
|
* Si non légitime, la fonction ne fait rien. Le comportement du site s'en remet alors à la seule existence d'une session PHP.
|
||||||
|
*/
|
||||||
|
function validationCookie($pdo) {
|
||||||
|
if (isset($_COOKIE['souvenir-session'])) {
|
||||||
|
if (!isset($_SESSION['id_utilisateur'])) {
|
||||||
|
$donnees_cookie=explode('|--@--|', $_COOKIE['souvenir-session']);
|
||||||
|
try {
|
||||||
|
$req = 'SELECT * FROM postfix_utilisateurs WHERE utilisateur=:identifiant';
|
||||||
|
|
||||||
|
$sql = $pdo->prepare($req);
|
||||||
|
$sql->bindValue(':identifiant', htmlspecialchars($donnees_cookie['0']));
|
||||||
|
$sql->execute();
|
||||||
|
|
||||||
|
$result = $sql ->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
$comptage = count($result);
|
||||||
|
}
|
||||||
|
catch(PDOException $e) {
|
||||||
|
die ("Erreur lors du traitement de la requête : " . $e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($comptage == 1) {
|
||||||
|
if (hash('sha3-512', $result['0']['id'].$result['0']['utilisateur'].$result['0']['mot_de_passe'])===$donnees_cookie['1']) {
|
||||||
|
// Cookie valide. On initialise les variables de sessions pour le bon fonctionnement du site.
|
||||||
|
initValeursSession($result);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Cookie invalide (probablement modifié par l'utilisateur).
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Prolongement de la durée du cookie.
|
||||||
|
setcookie('souvenir-session', $_COOKIE['souvenir-session'], ['expires' => time() + 60*60*24*30, 'path' => '/', 'domain' => $_SERVER['HTTP_HOST'], 'secure' => false, 'httponly' => true, 'samesite' => 'strict']);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Page de fonctions permettant la vérification des permission d'un utilisateur ou d'un visiteur.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fonction testant le niveau de privilège d'un utilisateur authentifié ou non.
|
||||||
|
* Elle vérifie le privilège de l'utilisateur connecté et retourne la valeur adéquate.
|
||||||
|
* Si un visiteur ou un utilisateur ne remplis pas la bonne condition, il est redirigé à la page d'accueil avec un message expllicatif.
|
||||||
|
* Cette fonction devrait être appelée dans toute page de traitement.
|
||||||
|
*/
|
||||||
|
function testPrivileges(){
|
||||||
|
if (isset($_SESSION['id_utilisateur']) && !empty($_SESSION['id_utilisateur']) && $_SESSION['privilege_utilisateur']=="administrateur") {
|
||||||
|
return "administrateur";
|
||||||
|
}
|
||||||
|
elseif (isset($_SESSION['id_utilisateur']) && !empty($_SESSION['id_utilisateur']) && $_SESSION['privilege_utilisateur']=="utilisateur") {
|
||||||
|
return "utilisateur";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
header("Location: /pages/visiteurs/formulaire_accueil.php?erreur=18");
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
@ -0,0 +1,154 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Page de gestion importé par la page d'administration centrale permettant la gestion des alias virtuels.
|
||||||
|
*/
|
||||||
|
|
||||||
|
require_once ($_SERVER["DOCUMENT_ROOT"]."/services/fonctions/bdd/domaines.php");
|
||||||
|
require_once ($_SERVER["DOCUMENT_ROOT"]."/services/fonctions/bdd/utilisateurs.php");
|
||||||
|
require_once ($_SERVER["DOCUMENT_ROOT"]."/services/fonctions/bdd/alias_virtuels.php");
|
||||||
|
|
||||||
|
$liste_utilisateurs = listeUtilisateursPostfix($pdo);
|
||||||
|
$liste_domaines = listeDomainesPostfix($pdo);
|
||||||
|
$liste_alias_virtuels = listeAliasVirtuelsPostfix($pdo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Affiche le formulaire de selection d'un utilisateur si celui connecté possède les privilèges administrateur.
|
||||||
|
*/
|
||||||
|
if (testPrivileges()==="administrateur") {
|
||||||
|
echo <<<_HEREDOC_
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12 col-md-6">
|
||||||
|
<div class="card mt-4 max-hauteur-pastille">
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="card-title">Choix de l'adresse</h5>
|
||||||
|
<form id="form_choix_utilisateur" action="/services/traitements/utilisateurs/changeUtilisateur.php" method="post">
|
||||||
|
<select class="form-select" name="choix_utilisateur" onchange="autoSoumission(this);">
|
||||||
|
_HEREDOC_;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remplis un menu déroulant permettant le choix de l'utilisateur par l'administrateur.
|
||||||
|
* Ce choix permettra de modifier les données y étant rattachés.
|
||||||
|
* La valeur par défaut du menu est positionnée sur le compte administrateur actuellement connecté.
|
||||||
|
*/
|
||||||
|
foreach ($liste_utilisateurs as $utilisateur_bdd => $utilisateur) {
|
||||||
|
if ($utilisateur['utilisateur']===$_SESSION['pseudo_utilisateur']) {
|
||||||
|
echo "<option value=\"".$utilisateur['utilisateur']."\" selected>".$utilisateur['utilisateur']."</option>\n";
|
||||||
|
}
|
||||||
|
elseif ($_SESSION['privilege_utilisateur']==="administrateur") {
|
||||||
|
echo "<option value=\"".$utilisateur['utilisateur']."\">".$utilisateur['utilisateur']."</option>\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
echo <<<_HEREDOC_
|
||||||
|
</select>
|
||||||
|
<input type="hidden" name="page_origine" value="alias">
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
_HEREDOC_;
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
|
||||||
|
<div class="col-12<?php if ($_SESSION['privilege_utilisateur']==="administrateur") {echo' col-md-6';}?>">
|
||||||
|
<div class="card mt-4 max-hauteur-pastille">
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="card-title">Ajouter un alias virtuel</h5>
|
||||||
|
<form action="/services/traitements/alias_virtuels/ajoutAliasVirtuels.php" method="post">
|
||||||
|
<div class="input-group">
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ajout d'un alias virtuel.
|
||||||
|
*/
|
||||||
|
$prefixe_utilisateur=retournePrefixeUtilisateurPostfix($pdo,$_SESSION['pseudo_utilisateur']);
|
||||||
|
if (!empty($prefixe_utilisateur)) {
|
||||||
|
echo "<span class=\"input-group-text\">$prefixe_utilisateur</span>";
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
<input type="text" class="form-control" id="nom_pour_filtre" name="nom_alias_virtuel" placeholder="alias" onkeyup="filtreValeurs();" required>
|
||||||
|
<span class="input-group-text">@</span>
|
||||||
|
<select class="form-select" name="choix_domaine_alias_virtuel">
|
||||||
|
<?php
|
||||||
|
|
||||||
|
try {
|
||||||
|
foreach ($liste_domaines as $domaine_bdd => $domaine) {
|
||||||
|
echo "<option value=\"".$domaine['domaine']."\">".$domaine['domaine']."</option>\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (\Exception $e) {
|
||||||
|
die ("Erreur de requête de selection du domaine pour \"$base\" : ".$e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
</select>
|
||||||
|
<!--<select name="choix_domaine_alias" onchange='document.getElementById("domaine_alias").innerHTML = this.options[this.selectedIndex].text'>
|
||||||
|
<option value=\"".$domaine['domaine']."\">".$domaine['domaine']."</option>
|
||||||
|
</select>
|
||||||
|
<p id="domaine_alias"><?php //echo $liste_domaines[0]["domaine"]; ?></p>-->
|
||||||
|
<button class="btn btn-primary bouton-ajout" type="submit"><img src="/fichiers/svg/plus.svg"/></button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card mt-4">
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="card-title">Alias de <?php echo $_SESSION['pseudo_utilisateur']; ?></h5>
|
||||||
|
<form class="" action="/services/traitements/alias_virtuels/editEtatAliasVirtuels.php" method="post">
|
||||||
|
<div class="row" id="liste_pour_filtre">
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Liste des alias virtuels.
|
||||||
|
*/
|
||||||
|
try {
|
||||||
|
foreach ($liste_alias_virtuels as $alias_virtuels_cles => $alias_virtuels_valeurs) {
|
||||||
|
if (isset($alias_virtuels_valeurs['active']) && $alias_virtuels_valeurs['active']=="1") {
|
||||||
|
$etat_interrupteur_allumer="checked";
|
||||||
|
$etat_interrupteur_eteint="";
|
||||||
|
} else {
|
||||||
|
$etat_interrupteur_eteint="checked";
|
||||||
|
$etat_interrupteur_allumer="";
|
||||||
|
}
|
||||||
|
echo <<<_HEREDOC_
|
||||||
|
<div class="col-md-6 col-xl-4">
|
||||||
|
<div class="card contour-pastille">
|
||||||
|
<div class="d-flex interieur-pastille">
|
||||||
|
<div class="champ-interrupteur">
|
||||||
|
<input type="radio" name="{$alias_virtuels_valeurs['id']}" id="allumer{$alias_virtuels_valeurs['id']}" onchange="activationBoutonFlotant(this)" value="1" {$etat_interrupteur_allumer}>
|
||||||
|
<label for="allumer{$alias_virtuels_valeurs['id']}" class="interrupteur-allumer"></label>
|
||||||
|
<input type="radio" name="{$alias_virtuels_valeurs['id']}" id="eteint{$alias_virtuels_valeurs['id']}" onchange="activationBoutonFlotant(this)" value="0" {$etat_interrupteur_eteint}>
|
||||||
|
<label for="eteint{$alias_virtuels_valeurs['id']}" class="interrupteur-eteint"></label>
|
||||||
|
</div>
|
||||||
|
<div class="titre-pastille">
|
||||||
|
<span>{$alias_virtuels_valeurs['courriel']}</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="input-label-supprimer-valeur btn btn-danger btn-sm" for="supprimer-valeur-{$alias_virtuels_valeurs['id']}"><img src="/fichiers/svg/trash-2.svg"></label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<input type="checkbox" class="input-checkbox-supprimer-valeur visuellement-cache" id="supprimer-valeur-{$alias_virtuels_valeurs['id']}">
|
||||||
|
<a class="confirmation-suppression card-footer" href="/services/traitements/alias_virtuels/supprAliasVirtuels.php?supprAliasVirtuel={$alias_virtuels_valeurs['id']}">Confirmer la suppression</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
_HEREDOC_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (\Exception $e) {
|
||||||
|
die ("Erreur de requête de selection utilisateurs pour \"$base\" : ".$e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
</div>
|
||||||
|
<button id="enregistrer-interrupteur" style="display: none;" class="bouton-flotant desactiver" type="submit"><img src="/fichiers/svg/save.svg"/></button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="/fichiers/js/filtre.js"></script>
|
@ -0,0 +1,137 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Page de gestion importé par la page d'administration centrale permettant la gestion des domaines.
|
||||||
|
*/
|
||||||
|
|
||||||
|
require_once ($_SERVER["DOCUMENT_ROOT"]."/services/fonctions/sessions/privileges.php");
|
||||||
|
|
||||||
|
if (testPrivileges()!=="administrateur") {
|
||||||
|
header("Location: /pages/visiteurs/formulaire_accueil.php?erreur=18");
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
|
||||||
|
require_once ($_SERVER["DOCUMENT_ROOT"]."/services/fonctions/bdd/domaines.php");
|
||||||
|
$liste_domaines = listeDomainesPostfix($pdo);
|
||||||
|
|
||||||
|
?>
|
||||||
|
<!-- Affichage et changement du domaine par défaut -->
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12 col-md-6">
|
||||||
|
<div class="card mt-4 max-hauteur-pastille">
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="card-title">Domaine par défaut</h5>
|
||||||
|
<?php
|
||||||
|
|
||||||
|
$domaine_defaut = retourneDomaineDefautPostfix($pdo);
|
||||||
|
if (empty($domaine_defaut)) {
|
||||||
|
echo <<<_HEREDOC_
|
||||||
|
<div class="alert alert-warning mb-2" role="alert"><img src="/fichiers/svg/alert-triangle-warning.svg"/>
|
||||||
|
Aucun domaine n'est défini par défaut. Celui-ci permet l'utilisation d'identifiants de connexion courts et le pré-sélectionne lors des créations d'alias virtuels.
|
||||||
|
</div>
|
||||||
|
_HEREDOC_;
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
<form action="/services/traitements/domaines/changeDomaineDefaut.php" method="post">
|
||||||
|
<div class="input-group">
|
||||||
|
<select class="form-select" name="choix_domaine_defaut">
|
||||||
|
<?php
|
||||||
|
|
||||||
|
// Génération de la liste des domaines existants
|
||||||
|
try {
|
||||||
|
foreach ($liste_domaines as $domaine_cles => $domaine_valeurs) {
|
||||||
|
echo "<option value=\"".$domaine_valeurs['domaine']."\">".$domaine_valeurs['domaine']."</option>\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (\Exception $e) {
|
||||||
|
die ("Erreur de requête de selection du domaine pour \"$base\" : ".$e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
</select>
|
||||||
|
<!-- Définition du domaine sélectionné comme étant par défaut -->
|
||||||
|
<button class="btn btn-primary" type="submit">Définir par défaut</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-12 col-md-6">
|
||||||
|
<div class="card mt-4 max-hauteur-pastille">
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="card-title">Ajouter un domaine</h5>
|
||||||
|
<form action="/services/traitements/domaines/ajoutDomaines.php" method="post">
|
||||||
|
<div class="input-group">
|
||||||
|
<input type="text" class="form-control" id="nom_pour_filtre" name="nom_domaine" onkeyup="filtreValeurs();" placeholder="domaine.tld" required/>
|
||||||
|
<button class="btn btn-primary bouton-ajout" type="submit"><img src="/fichiers/svg/plus.svg"/></button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card mt-4 max-hauteur-pastille">
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="card-title">Domaines du serveur de messagerie</h5>
|
||||||
|
<form class="" action="/services/traitements/domaines/editEtatDomaines.php" method="post">
|
||||||
|
<div class="row" id="liste_pour_filtre">
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Liste des domaines.
|
||||||
|
*/
|
||||||
|
try {
|
||||||
|
foreach ($liste_domaines as $liste_domaines_cles => $liste_domaines_valeurs) {
|
||||||
|
if (isset($liste_domaines_valeurs['active']) && $liste_domaines_valeurs['active']=="1") {
|
||||||
|
$etat_interrupteur_allumer="checked";
|
||||||
|
$etat_interrupteur_eteint="";
|
||||||
|
} else {
|
||||||
|
$etat_interrupteur_eteint="checked";
|
||||||
|
$etat_interrupteur_allumer="";
|
||||||
|
}
|
||||||
|
if (isset($liste_domaines_valeurs['defaut']) && $liste_domaines_valeurs['defaut']=="1") {
|
||||||
|
$etat_bouton="disabled";
|
||||||
|
$bordure_pastille="border-primary interieur-pastille-bleu";
|
||||||
|
$post_texte=" <span class=\"text-primary\">(défaut)</span>";
|
||||||
|
} else {
|
||||||
|
$etat_bouton="";
|
||||||
|
$bordure_pastille="";
|
||||||
|
$post_texte="";
|
||||||
|
}
|
||||||
|
echo <<<_HEREDOC_
|
||||||
|
<div class="col-md-6 col-xl-4">
|
||||||
|
<div class="card contour-pastille {$bordure_pastille}">
|
||||||
|
<div class="d-flex interieur-pastille">
|
||||||
|
<div class="champ-interrupteur {$etat_bouton}">
|
||||||
|
<input type="radio" name="{$liste_domaines_valeurs['id']}" id="allumer{$liste_domaines_valeurs['id']}" onchange="activationBoutonFlotant(this)" value="1" {$etat_interrupteur_allumer}>
|
||||||
|
<label for="allumer{$liste_domaines_valeurs['id']}" class="interrupteur-allumer"></label>
|
||||||
|
<input type="radio" name="{$liste_domaines_valeurs['id']}" id="eteint{$liste_domaines_valeurs['id']}" onchange="activationBoutonFlotant(this)" value="0" {$etat_interrupteur_eteint}>
|
||||||
|
<label for="eteint{$liste_domaines_valeurs['id']}" class="interrupteur-eteint"></label>
|
||||||
|
</div>
|
||||||
|
<div class="titre-pastille">
|
||||||
|
<span>{$liste_domaines_valeurs['domaine']}{$post_texte}</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="input-label-supprimer-valeur btn btn-danger btn-sm {$etat_bouton}" for="supprimer-valeur-{$liste_domaines_valeurs['id']}"><img src="/fichiers/svg/trash-2.svg"></label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<input type="checkbox" class="input-checkbox-supprimer-valeur visuellement-cache" id="supprimer-valeur-{$liste_domaines_valeurs['id']}">
|
||||||
|
<a class="confirmation-suppression card-footer" href="/services/traitements/domaines/supprDomaines.php?supprDomaine={$liste_domaines_valeurs['id']}">Confirmer la suppression</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
_HEREDOC_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (\Exception $e) {
|
||||||
|
die ("Erreur de requête de selection utilisateurs pour \"$base\" : ".$e->getMessage());
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
</div>
|
||||||
|
<button id="enregistrer-interrupteur" style="display: none;" class="bouton-flotant desactiver" type="submit"><img src="/fichiers/svg/save.svg"/></button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="/fichiers/js/filtre.js"></script>
|
@ -0,0 +1,173 @@
|
|||||||
|
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Page de gestion importé par la page d'administration centrale permettant la gestion des listes noires.
|
||||||
|
*/
|
||||||
|
|
||||||
|
require_once ($_SERVER["DOCUMENT_ROOT"]."/services/fonctions/sessions/privileges.php");
|
||||||
|
|
||||||
|
if (testPrivileges()!=="administrateur") {
|
||||||
|
header("Location: /pages/visiteurs/formulaire_accueil.php?erreur=18");
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
|
||||||
|
require_once ($_SERVER["DOCUMENT_ROOT"]."/services/fonctions/bdd/listes_noires.php");
|
||||||
|
$liste_entrees_liste_noires_dst=listeEntreeListeNoireDstPostfix($pdo);
|
||||||
|
$liste_entrees_liste_noires_exp=listeEntreeListeNoireExpPostfix($pdo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Permet d'inclure la page d'administration des listes noires déstinataires ou expéditeurs dédiée.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (isset($_GET['sousPage']) && !empty($_GET['sousPage'])) {
|
||||||
|
switch ($_GET['sousPage']) {
|
||||||
|
case 'destinataires':
|
||||||
|
echo <<<_HEREDOC_
|
||||||
|
<div class="card mt-4">
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="card-title">Ajouter une entrée dans la liste noire des destinataires</h5>
|
||||||
|
<form action="/services/traitements/liste_noire_dst/ajoutEntreeListeNoireDst.php" method="post">
|
||||||
|
<div class="input-group">
|
||||||
|
<input type="text" class="form-control" id="nom_pour_filtre" name="courriel_entree_liste_noire_dst" placeholder="utilisateur@domaine.tld" onkeyup="filtreValeurs();" required>
|
||||||
|
<select class="form-select" name="choix_action_entree_liste_noire_dst">
|
||||||
|
<option value="REJECT">REJECT</option>
|
||||||
|
<option value="DEFER">DEFER</option>
|
||||||
|
</select>
|
||||||
|
<button class="btn btn-primary bouton-ajout" type="submit"><img src="/fichiers/svg/plus.svg"/></button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card mt-4">
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="card-title">Entrées de la liste noire des destinataires du serveur de messagerie</h5>
|
||||||
|
|
||||||
|
<form class="" action="/services/traitements/liste_noire_dst/editEntreeListeNoireDst.php" method="post">
|
||||||
|
<div class="row" id="liste_pour_filtre">
|
||||||
|
_HEREDOC_;
|
||||||
|
/**
|
||||||
|
* Liste des entrées de la liste noire des destinataires.
|
||||||
|
*/
|
||||||
|
try {
|
||||||
|
foreach ($liste_entrees_liste_noires_dst as $liste_entrees_liste_noires_dst_cles => $liste_entrees_liste_noires_dst_valeurs) {
|
||||||
|
if (isset($liste_entrees_liste_noires_dst_valeurs['active']) && $liste_entrees_liste_noires_dst_valeurs['active']=="1") {
|
||||||
|
$etat_interrupteur_allumer="checked";
|
||||||
|
$etat_interrupteur_eteint="";
|
||||||
|
} else {
|
||||||
|
$etat_interrupteur_eteint="checked";
|
||||||
|
$etat_interrupteur_allumer="";
|
||||||
|
}
|
||||||
|
echo <<<_HEREDOC_
|
||||||
|
<div class="col-md-6 col-xl-4">
|
||||||
|
<div class="card contour-pastille">
|
||||||
|
<div class="d-flex interieur-pastille">
|
||||||
|
<div class="champ-interrupteur">
|
||||||
|
<input type="radio" name="{$liste_entrees_liste_noires_dst_valeurs['id']}" id="allumer{$liste_entrees_liste_noires_dst_valeurs['id']}" onchange="activationBoutonFlotant(this)" value="1" {$etat_interrupteur_allumer}>
|
||||||
|
<label for="allumer{$liste_entrees_liste_noires_dst_valeurs['id']}" class="interrupteur-allumer"></label>
|
||||||
|
<input type="radio" name="{$liste_entrees_liste_noires_dst_valeurs['id']}" id="eteint{$liste_entrees_liste_noires_dst_valeurs['id']}" onchange="activationBoutonFlotant(this)" value="0" {$etat_interrupteur_eteint}>
|
||||||
|
<label for="eteint{$liste_entrees_liste_noires_dst_valeurs['id']}" class="interrupteur-eteint"></label>
|
||||||
|
</div>
|
||||||
|
<div class="titre-pastille">
|
||||||
|
<span>{$liste_entrees_liste_noires_dst_valeurs['courriel']} <img class="chevron-dst" src="/fichiers/svg/chevron-right.svg" /> <span class="badge fond-arc-noire">{$liste_entrees_liste_noires_dst_valeurs['action']}</span></span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="input-label-supprimer-valeur btn btn-danger btn-sm" for="supprimer-valeur-{$liste_entrees_liste_noires_dst_valeurs['id']}"><img src="/fichiers/svg/trash-2.svg"></label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<input type="checkbox" class="input-checkbox-supprimer-valeur visuellement-cache" id="supprimer-valeur-{$liste_entrees_liste_noires_dst_valeurs['id']}">
|
||||||
|
<a class="confirmation-suppression card-footer" href="/services/traitements/liste_noire_dst/supprEntreeListeNoireDst.php?supprEntreeListeNoireDst={$liste_entrees_liste_noires_dst_valeurs['id']}">Confirmer la suppression</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
_HEREDOC_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (\Exception $e) {
|
||||||
|
die ("Erreur de requête de selection utilisateurs pour \"$base\" : ".$e->getMessage());
|
||||||
|
}
|
||||||
|
echo <<<_HEREDOC_
|
||||||
|
</div>
|
||||||
|
<button id="enregistrer-interrupteur" style="display: none;" class="bouton-flotant desactiver" type="submit"><img src="/fichiers/svg/save.svg"/></button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
_HEREDOC_;
|
||||||
|
break;
|
||||||
|
case 'expediteurs':
|
||||||
|
echo <<<_HEREDOC_
|
||||||
|
<div class="card mt-4">
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="card-title">Ajouter une entrée dans la liste noire des expéditeurs</h5>
|
||||||
|
<form action="/services/traitements/liste_noire_exp/ajoutEntreeListeNoireExp.php" method="post">
|
||||||
|
<div class="input-group">
|
||||||
|
<input type="text" class="form-control" id="nom_pour_filtre" name="courriel_entree_liste_noire_exp" placeholder="utilisateur@domaine.tld" onkeyup="filtreValeurs();" required>
|
||||||
|
<select class="form-select" name="choix_code_retour_entree_liste_noire_exp">
|
||||||
|
<option value="554">REJECT</option>
|
||||||
|
</select>
|
||||||
|
<button class="btn btn-primary bouton-ajout" type="submit"><img src="/fichiers/svg/plus.svg"/></button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card mt-4">
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="card-title">Entrées de la liste noire des expéditeurs du serveur de messagerie</h5>
|
||||||
|
|
||||||
|
<form class="" action="/services/traitements/liste_noire_exp/editEntreeListeNoireExp.php" method="post">
|
||||||
|
<div class="row" id="liste_pour_filtre">
|
||||||
|
_HEREDOC_;
|
||||||
|
/**
|
||||||
|
* Liste des entrées de la liste noire des destinataires.
|
||||||
|
*/
|
||||||
|
try {
|
||||||
|
foreach ($liste_entrees_liste_noires_exp as $liste_entrees_liste_noires_exp_cles => $liste_entrees_liste_noires_exp_valeurs) {
|
||||||
|
if (isset($liste_entrees_liste_noires_exp_valeurs['active']) && $liste_entrees_liste_noires_exp_valeurs['active']=="1") {
|
||||||
|
$etat_interrupteur_allumer="checked";
|
||||||
|
$etat_interrupteur_eteint="";
|
||||||
|
} else {
|
||||||
|
$etat_interrupteur_eteint="checked";
|
||||||
|
$etat_interrupteur_allumer="";
|
||||||
|
}
|
||||||
|
echo <<<_HEREDOC_
|
||||||
|
<div class="col-md-6 col-xl-4">
|
||||||
|
<div class="card contour-pastille">
|
||||||
|
<div class="d-flex interieur-pastille">
|
||||||
|
<div class="champ-interrupteur">
|
||||||
|
<input type="radio" name="{$liste_entrees_liste_noires_exp_valeurs['id']}" id="allumer{$liste_entrees_liste_noires_exp_valeurs['id']}" onchange="activationBoutonFlotant(this)" value="1" {$etat_interrupteur_allumer}>
|
||||||
|
<label for="allumer{$liste_entrees_liste_noires_exp_valeurs['id']}" class="interrupteur-allumer"></label>
|
||||||
|
<input type="radio" name="{$liste_entrees_liste_noires_exp_valeurs['id']}" id="eteint{$liste_entrees_liste_noires_exp_valeurs['id']}" onchange="activationBoutonFlotant(this)" value="0" {$etat_interrupteur_eteint}>
|
||||||
|
<label for="eteint{$liste_entrees_liste_noires_exp_valeurs['id']}" class="interrupteur-eteint"></label>
|
||||||
|
</div>
|
||||||
|
<div class="titre-pastille">
|
||||||
|
<span><span class="badge fond-arc-noire">{$liste_entrees_liste_noires_exp_valeurs['code_retour']}</span> <img class="chevron-dst" src="/fichiers/svg/chevron-right.svg" /> {$liste_entrees_liste_noires_exp_valeurs['courriel']}</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="input-label-supprimer-valeur btn btn-danger btn-sm" for="supprimer-valeur-{$liste_entrees_liste_noires_exp_valeurs['id']}"><img src="/fichiers/svg/trash-2.svg"></label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<input type="checkbox" class="input-checkbox-supprimer-valeur visuellement-cache" id="supprimer-valeur-{$liste_entrees_liste_noires_exp_valeurs['id']}">
|
||||||
|
<a class="confirmation-suppression card-footer" href="/services/traitements/liste_noire_exp/supprEntreeListeNoireExp.php?supprEntreeListeNoireExp={$liste_entrees_liste_noires_exp_valeurs['id']}">Confirmer la suppression</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
_HEREDOC_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (\Exception $e) {
|
||||||
|
die ("Erreur de requête de selection utilisateurs pour \"$base\" : ".$e->getMessage());
|
||||||
|
}
|
||||||
|
echo <<<_HEREDOC_
|
||||||
|
</div>
|
||||||
|
<button id="enregistrer-interrupteur" style="display: none;" class="bouton-flotant desactiver" type="submit"><img src="/fichiers/svg/save.svg"/></button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
_HEREDOC_;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
echo " <h1>Cette page n'existe pas.</h1>";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
|
||||||
|
<script src="/fichiers/js/filtre.js"></script>
|