diff options
author | polo <ordipolo@gmx.fr> | 2022-02-17 18:13:00 +0100 |
---|---|---|
committer | polo <ordipolo@gmx.fr> | 2022-02-17 18:13:00 +0100 |
commit | 787d03e48471ba62cd830379428f04d996f0b74b (patch) | |
tree | e9f98c7b9288c4530b50985688dd82622106ba2d /index.php | |
parent | 29df6f1362745eabf4fbcaedf309eb63795152fa (diff) | |
download | melaine-787d03e48471ba62cd830379428f04d996f0b74b.zip |
model update
Diffstat (limited to 'index.php')
-rw-r--r-- | index.php | 570 |
1 files changed, 271 insertions, 299 deletions
@@ -1,299 +1,271 @@ | |||
1 | <?php | 1 | <?php |
2 | // index.php | 2 | // index.php |
3 | // | 3 | // |
4 | // routeur MVC ou controlleur principal | 4 | // routeur MVC ou controlleur principal |
5 | // il traite les GET et passe la main aux contrôleurs | 5 | // il traite les GET et passe la main aux contrôleurs |
6 | // | 6 | |
7 | // ce site utilise une architecture Modèle-Vue-Contrôleur (MVC) | 7 | |
8 | // le schéma ci-dessous représente le sens dans lequel le code est interprété | 8 | // sessions, penser aux attaques CSRF (cross-site request forgery): |
9 | // | 9 | // ça consite à faire qu'un utilisateur connecté avec une session envoie malgré lui une requête GET ou POST qu'un hacker aura cachée par exemple dans une fausse image clicable |
10 | // modèle | 10 | // - solution: faire qu'un GET seul dans une session ne suffise pas à effectuer une action (les GET ne doivent servir qu'à afficher la bonne page), une attaque sur un POST est possible aussi mais plus difficile et nécessite d'injecter du javascript |
11 | // ^ | | 11 | // - on peut demander à l'utilisateur une vérification supplémentaire avant chaque action, mais c'est plutôt chiant |
12 | // | v | 12 | // - il y a la méthode des jetons, "nonces" et horodatage |
13 | // routeur --> contrôleur | 13 | // - vérifier le "référent", c'est à dire l'URL de la page d'où vient normallement la requête |
14 | // | | 14 | // infos: https://fr.wikipedia.org/wiki/Cross-site_request_forgery |
15 | // v | 15 | session_start(); |
16 | // vue ---> envoi de la page au client | 16 | |
17 | // | 17 | if(!empty($_SESSION['erreur'])) |
18 | // pour retrouver quelque chose dans le code, il suffit de suivre un chemin linéaire dont le départ est ici | 18 | { |
19 | // pas de croisement, pas de marche arrière, impossible de se perdre! | 19 | echo('<script>alert(\'' . $_SESSION['erreur'] . '\');</script>'); |
20 | // autre avantage: les chemins sont tous relatifs et sont toujours bons, parce que tous les fichiers sont "inclus" dans index.php | 20 | unset($_SESSION['erreur']); |
21 | // | 21 | } |
22 | // Les dossiers: | 22 | |
23 | // -> controller: traitements en PHP pur | 23 | // au premier démarrage du site |
24 | // -> model: interface entre PHP et données, on y trouve le SQL ou la manipulation de fichiers textes, le PHP y est orienté objet | 24 | // l'explication des éventuels problèmes de droits en lecture/écriture est à chercher ici: |
25 | // -> view: le PHP y produit le HTML, il construit les pages, | 25 | require('controller/installation.php'); |
26 | // le mélange PHP/HTML étant très vite assez dégueulasse, le HTML figé est placé à part dans le fichier view/template.php | 26 | require('controller/password.php'); |
27 | // -> public: contient CSS, JS, images, polices, medias, etc, il est utilisé par template.php | 27 | installation(); |
28 | // -> lib: les bibliothèques, on y trouve en particulier le ckeditor qui occupe une place centrale dans le projet, et aussi htmLawed qui nettoie le HTML produit par l'éditeur (failles XSS) | 28 | |
29 | // -> data: comme son nom l'indique | 29 | |
30 | // | 30 | // traitement des requêtes AJAX |
31 | // Quelques fichiers spéciaux (indépendants de index.php): | 31 | if(isset($_GET['action']) && isset($_GET['page']) && $_GET['action'] == 'upload_image') |
32 | // - imageAJAX.php traite les requêtes AJAX envoyées par l'éditeur | 32 | { |
33 | // - .htaccess pour la sécurité (configurer le httpd.conf d'apache peut être nécessaire) | 33 | // sécurité !! |
34 | // - erreur404.php (fonctionne avec .htaccess) | 34 | if(!isset($_SESSION['admin']) || $_SESSION['admin'] != 1 |
35 | // | 35 | || !isset($_FILES['upload']) || empty($_FILES['upload'])) |
36 | // le dossier data et son contenu sont "normalement" autorisés en écriture pour deux raisons: | 36 | { |
37 | // - placer le contenu pré-existant avec son client FTP | 37 | // sans effet? |
38 | // - autoriser PHP (sinon, c'est comme si on avait un site statique) | 38 | header('Location: index.php?erreur=image_ajax'); |
39 | // -> pour pouvoir installer le site en n'ayant qu'à modifier les droits du dossier data uniquement et éviter les situations pénibles ou l'utilisateur est bloqué sans rien comprendre, on pourra créer ou utiliser des sauvegardes au format ZIP depuis une page spéciale accessible avec le compte admin | 39 | } |
40 | 40 | else | |
41 | // sessions, penser aux attaques CSRF (cross-site request forgery): | 41 | { |
42 | // ça consite à faire qu'un utilisateur connecté avec une session envoie malgré lui une requête GET ou POST qu'un hacker aura cachée par exemple dans une fausse image clicable | 42 | require('model/Image.php'); |
43 | // - solution: faire qu'un GET seul dans une session ne suffise pas à effectuer une action (les GET ne doivent servir qu'à afficher la bonne page), une attaque sur un POST est possible aussi mais plus difficile et nécessite d'injecter du javascript | 43 | // paramètre "true" parce qu'on reçoit une requête AJAX |
44 | // - on peut demander à l'utilisateur une vérification supplémentaire avant chaque action, mais c'est plutôt chiant | 44 | $Image = new Image(true); |
45 | // - il y a la méthode des jetons, "nonces" et horodatage | 45 | $Image->upload(); |
46 | // - vérifier le "référent", c'est à dire l'URL de la page d'où vient normallement la requête | 46 | } |
47 | // infos: https://fr.wikipedia.org/wiki/Cross-site_request_forgery | 47 | exit; // stop !! |
48 | session_start(); | 48 | } |
49 | 49 | ||
50 | if(!empty($_SESSION['erreur'])) | 50 | |
51 | { | 51 | // traitement des POST du ckeditor |
52 | echo('<script>alert(\'' . $_SESSION['erreur'] . '\');</script>'); | 52 | // la fonction submitCKeditor est "autonome", elle n'affiche rien puis redirige sans GET |
53 | unset($_SESSION['erreur']); | 53 | if(isset($_SESSION['admin']) && $_SESSION['admin'] == 1 |
54 | } | 54 | && isset($_GET['action']) && $_GET['action'] == 'submit' |
55 | 55 | // trois possibilités: on a un contenu HTML ou JSON ou les deux | |
56 | // au premier démarrage du site | 56 | && ((isset($_POST['contenu']) && $_POST['contenu'] != '') |
57 | // l'explication des éventuels problèmes de droits en lecture/écriture est à chercher ici: | 57 | || (isset($_POST['titre']) && isset($_POST['annee'])))) |
58 | require('controller/installation.php'); | 58 | { |
59 | require('controller/password.php'); | 59 | require('controller/ckeditor.php'); // traitement du POST |
60 | installation(); | 60 | require('controller/Security.php'); // sécurité des chaines |
61 | 61 | require('model/Article.php'); | |
62 | 62 | ||
63 | // traitement des requêtes AJAX | 63 | if($_GET['page'] == 'discographie') |
64 | if(isset($_GET['action']) && isset($_GET['page']) && $_GET['action'] == 'upload_image') | 64 | { |
65 | { | 65 | require('model/Album.php'); |
66 | // et une backdoor de fermée! | 66 | } |
67 | if(!isset($_SESSION['admin']) || $_SESSION['admin'] != 1 | 67 | |
68 | || !isset($_FILES['upload']) || empty($_FILES['upload'])) | 68 | submitCKeditor(); |
69 | { | 69 | // modification |
70 | // sans effet? | 70 | /*if(isset($_SESSION['target'])) |
71 | header('Location: index.php?erreur=image_ajax'); | 71 | { |
72 | } | 72 | submitCKeditor($_SESSION['target']); |
73 | else | 73 | } |
74 | { | 74 | // nouvel article |
75 | require('model/Image.php'); | 75 | else |
76 | // paramètre "true" parce qu'on reçoit une requête AJAX | 76 | { |
77 | $Image = new Image(true); | 77 | submitCKeditor(''); // $target = '' |
78 | $Image->upload(); | 78 | }*/ |
79 | } | 79 | } |
80 | exit; // arrêt ici !! | 80 | else |
81 | } | 81 | { |
82 | 82 | unset($_SESSION['target']); | |
83 | 83 | } | |
84 | // traitement des POST du ckeditor | 84 | |
85 | // la fonction submitCKeditor est "autonome", elle n'affiche rien puis redirige sans GET | 85 | |
86 | if(isset($_SESSION['admin']) && $_SESSION['admin'] == 1 | 86 | // déconnexion |
87 | && isset($_GET['action']) && $_GET['action'] == 'submit' | 87 | if(isset($_GET['action']) && isset($_GET['page'])) |
88 | // trois possibilités: on a un contenu HTML ou JSON ou les deux | 88 | { |
89 | && ((isset($_POST['contenu']) && $_POST['contenu'] != '') | 89 | if($_GET['action'] == "deconnexion") |
90 | || (isset($_POST['titre']) && isset($_POST['annee'])))) | 90 | { |
91 | { | 91 | // on nettoie et on recharge |
92 | require('controller/ckeditor.php'); // traitement du POST | 92 | $_SESSION['admin'] = 0; |
93 | require('controller/Security.php'); // sécurité des chaines | 93 | header('Location: index.php?page=' . $_GET['page']); |
94 | require('model/Page.php'); // modèle | 94 | } |
95 | if($_GET['page'] == 'discographie') | 95 | } |
96 | { | 96 | |
97 | require('model/Album.php'); | 97 | |
98 | } | 98 | |
99 | 99 | // construction des pages | |
100 | // modification | 100 | |
101 | if(isset($_SESSION['target'])) | 101 | // mode visiteur (sans l'éditeur) |
102 | { | 102 | require('controller/visitor.php'); |
103 | submitCKeditor($_SESSION['target']); | 103 | |
104 | } | 104 | // modèle |
105 | // nouvel article | 105 | if(isset($_GET['page']) && $_GET['page'] != 'menu') |
106 | else | 106 | { |
107 | { | 107 | require('model/Article.php'); |
108 | submitCKeditor(''); | 108 | if($_GET['page'] == 'discographie' || $_GET['page'] == 'album') |
109 | } | 109 | { |
110 | 110 | require('model/Album.php'); | |
111 | // nettoyage | 111 | } |
112 | unset($_SESSION['nomFichier']); | 112 | } |
113 | unset($_GET['action']); | 113 | |
114 | unset($_POST['contenu']); | 114 | |
115 | header('Location: index.php?page=' . $_GET['page']); | 115 | // contrôleur des pages en mode admin |
116 | exit(); | 116 | if(isset($_SESSION['admin']) && $_SESSION['admin'] == 1) |
117 | } | 117 | { |
118 | 118 | // contrôleur en mode admin (= lecture/écriture) | |
119 | // déconnexion: nettoyer et recharger la page | 119 | require('controller/admin.php'); |
120 | if(isset($_GET['action']) && isset($_GET['page'])) | 120 | } |
121 | { | 121 | else |
122 | if($_GET['action'] == "deconnexion") | 122 | { |
123 | { | 123 | // initialisation |
124 | $_SESSION['admin'] = 0; | 124 | $_SESSION['admin'] = 0; |
125 | header('Location: index.php?page=' . $_GET['page']); | 125 | } |
126 | } | 126 | |
127 | } | 127 | |
128 | 128 | // page du site demandée | |
129 | // contrôleur des pages en mode visiteur (= lecture uniquement) | 129 | if(isset($_GET['page'])) |
130 | // appelé tout le temps parce que certaines pages (accueil, menu) n'ont pas de version "admin" => à améliorer | 130 | { |
131 | require('controller/visitor.php'); | 131 | // page d'accueil |
132 | 132 | if($_GET['page'] == 'accueil') | |
133 | // utile pour presque toutes les pages | 133 | { |
134 | if(isset($_GET['page']) && $_GET['page'] != 'menu') | 134 | accueil(); |
135 | { | 135 | } |
136 | require('model/Page.php'); | 136 | // page menu |
137 | if($_GET['page'] == 'discographie' || $_GET['page'] == 'album') | 137 | elseif($_GET['page'] == 'menu') |
138 | { | 138 | { |
139 | require('model/Album.php'); | 139 | menu(); |
140 | } | 140 | } |
141 | } | 141 | // page melaine |
142 | 142 | elseif($_GET['page'] == 'melaine') | |
143 | // contrôleur des pages en mode admin | 143 | { |
144 | if(isset($_SESSION['admin']) && $_SESSION['admin'] == 1) | 144 | // cas de l'ouverture de l'éditeur pour modification: |
145 | { | 145 | // on récupère le GET qui sera placé dans une session |
146 | // contrôleur en mode admin (= lecture/écriture) | 146 | // GET, POST, cookies => navigation (utiles au visiteur) |
147 | require('controller/admin.php'); | 147 | // sessions => action |
148 | } | 148 | // un seul utilisateur peut modifier les données donc ça va, |
149 | else | 149 | // avec plusieurs utilisateurs, il faut plus de sécurités |
150 | { | 150 | |
151 | // initialisation | 151 | // rédaction |
152 | $_SESSION['admin'] = 0; | 152 | if($_SESSION['admin'] == 1 && isset($_GET['action']) && $_GET['action'] == 'editor') |
153 | } | 153 | { |
154 | 154 | //echo($_GET['file_code']); die(); | |
155 | 155 | ||
156 | // page du site demandée | 156 | // modification |
157 | if(isset($_GET['page'])) | 157 | if(isset($_GET['file_code']) || !empty($_GET['file_code'])) |
158 | { | 158 | { |
159 | // page d'accueil | 159 | melaineEdit($_GET['file_code'], 0); |
160 | if($_GET['page'] == 'accueil') | 160 | } |
161 | { | 161 | // nouvel article |
162 | accueil(); | 162 | else |
163 | } | 163 | { |
164 | // page menu | 164 | melaineEdit('', 0); |
165 | elseif($_GET['page'] == 'menu') | 165 | } |
166 | { | 166 | } |
167 | menu(); | 167 | // suppression |
168 | } | 168 | else if($_SESSION['admin'] == 1 && isset($_GET['action']) && $_GET['action'] == 'suppression') |
169 | // page melaine | 169 | { |
170 | elseif($_GET['page'] == 'melaine') | 170 | melaineEdit($_GET['file_code'], 1); |
171 | { | 171 | } |
172 | // Si ouverture de l'éditeur pour modification: | 172 | else |
173 | // le lien utilisé pour ouvrir l'éditeur contient un GET avec le numéro de l'article, mais pas le nom du fichier que le visiteur ne doit pas voir | 173 | { |
174 | // GET, POST, cookies => navigation (utiles au visiteur) | 174 | melaineVisitor(); |
175 | // sessions => action | 175 | } |
176 | // c'est ici qu'on passe des GET aux sessions | 176 | } |
177 | // on associe maintenant le numéro de l'article et le nom du fichier, l'article déjà existant inséré dans l'éditeur DOIT être celui qui sera modifié | 177 | // page discographie |
178 | 178 | elseif($_GET['page'] == 'discographie') | |
179 | if($_SESSION['admin'] == 1 && isset($_GET['action']) && $_GET['action'] == 'editor') | 179 | { |
180 | { | 180 | // rédaction |
181 | // modification | 181 | if($_SESSION['admin'] == 1 && isset($_GET['action']) && $_GET['action'] == 'edition') |
182 | if(isset($_GET['article']) && is_numeric($_GET['article']) && $_GET['article'] > 0) | 182 | { |
183 | { | 183 | // modification |
184 | melaineEdit($_GET['article'], 0); | 184 | if(isset($_GET['file_code']) || !empty($_GET['file_code'])) |
185 | } | 185 | { |
186 | // nouvel article | 186 | discoEdit($_GET['file_code'], 0); |
187 | else | 187 | } |
188 | { | 188 | // nouvel article |
189 | // par sécurité | 189 | else |
190 | unset($_SESSION['nomFichier']); | 190 | { |
191 | 191 | // par sécurité | |
192 | melaineEdit(0, 0); | 192 | unset($_GET['file_code']); |
193 | } | 193 | |
194 | } | 194 | discoEdit('', 0); |
195 | // suppression | 195 | } |
196 | else if($_SESSION['admin'] == 1 && isset($_GET['action']) && $_GET['action'] == 'suppression') | 196 | } |
197 | { | 197 | // suppression |
198 | melaineEdit($_GET['article'], 1); | 198 | else if($_SESSION['admin'] == 1 && isset($_GET['action']) && $_GET['action'] == 'suppression') |
199 | } | 199 | { |
200 | else | 200 | discoEdit($_GET['file_code'], 1); |
201 | { | 201 | } |
202 | melaineVisitor(); | 202 | else |
203 | } | 203 | { |
204 | } | 204 | discoVisitor(); |
205 | // page discographie | 205 | } |
206 | elseif($_GET['page'] == 'discographie') | 206 | } |
207 | { | 207 | // page d'un album de la discographie |
208 | if($_SESSION['admin'] == 1 && isset($_GET['action']) && $_GET['action'] == 'edition') | 208 | // page visiteur uniquement |
209 | { | 209 | elseif($_GET['page'] == 'album') |
210 | // modification | 210 | { |
211 | if(isset($_GET['album_code']) || !empty($_GET['album_code'])) | 211 | album($_GET['file_code'], $_GET['album_name']); |
212 | { | 212 | } |
213 | discoEdit($_GET['album_code'], 0); | 213 | // page connexion |
214 | } | 214 | elseif($_GET['page'] == 'connexion') |
215 | // nouvel article | 215 | { |
216 | else | 216 | connect(); |
217 | { | 217 | } |
218 | // par sécurité | 218 | // $_GET['page'] = n'importe quoi! |
219 | $_GET['album_code'] = ''; | 219 | else |
220 | unset($_SESSION['nomFichier']); | 220 | { |
221 | 221 | menu(); | |
222 | discoEdit('', 0); | 222 | } |
223 | } | 223 | } |
224 | } | 224 | |
225 | // suppression | 225 | |
226 | else if($_SESSION['admin'] == 1 && isset($_GET['action']) && $_GET['action'] == 'suppression') | 226 | // actions en mode admin, recharger une des pages principales |
227 | { | 227 | elseif($_SESSION['admin'] == 1 && isset($_GET['action'])) |
228 | discoEdit($_GET['album_code'], 1); | 228 | { |
229 | } | 229 | if($_GET['action'] == 'modif_mdp') |
230 | else | 230 | { |
231 | { | 231 | //changePassword($secret); |
232 | discoVisitor(); | 232 | changePassword(); |
233 | } | 233 | } |
234 | } | 234 | // extraction du contenu du dossier data |
235 | // page d'un album de la discographie | 235 | else if($_GET['action'] == 'extraction') |
236 | elseif($_GET['page'] == 'album') | 236 | { |
237 | { | 237 | require('controller/backup.php'); |
238 | album($_GET['album_code'], $_GET['album_name']); | 238 | extraction($_GET['from']); |
239 | // page visiteur uniquement | 239 | } |
240 | } | 240 | // l'inverse, insertion des données d'une sauvegarde |
241 | // page connexion | 241 | else if($_GET['action'] == 'insertion') |
242 | elseif($_GET['page'] == 'connexion') | 242 | { |
243 | { | 243 | require('controller/backup.php'); |
244 | connect(); | 244 | insertion($_GET['from']); |
245 | } | 245 | } |
246 | // $_GET['page'] = n'importe quoi! | 246 | else |
247 | else | 247 | { |
248 | { | 248 | accueil(); |
249 | menu(); | 249 | } |
250 | } | 250 | } |
251 | } | 251 | |
252 | 252 | // renvoi ici par le .htaccess si lien mort ou sans http:// au début | |
253 | 253 | elseif(isset($_GET['erreur'])) | |
254 | // actions en mode admin, recharger une des pages principales | 254 | { |
255 | elseif($_SESSION['admin'] == 1 && isset($_GET['action'])) | 255 | //if($_GET['erreur'] == 404) |
256 | { | 256 | //{ |
257 | if($_GET['action'] == 'modif_mdp') | 257 | // echo('<p style="color: red;" >ERREUR 404<br/>Le lien sur lequel vous avez cliqué pointe vers un emplacement introuvable.<br /> |
258 | { | 258 | // Ce n\'est pas votre faute. Vous pouvez éventuellement rechercher la page demandée avec votre moteur de recherche ou prévenir le responsable du site.</p>'); |
259 | //changePassword($secret); | 259 | // echo('<p><a href="index.php" >Retour au site</a></p>'); |
260 | changePassword(); | 260 | //} |
261 | } | 261 | //else |
262 | // extraction du contenu du dossier data | 262 | //{ |
263 | else if($_GET['action'] == 'extraction') | 263 | accueil(); |
264 | { | 264 | //} |
265 | require('controller/backup.php'); | 265 | } |
266 | extraction($_GET['from']); | 266 | |
267 | } | 267 | // page d'accueil (adresse sans GET valable) |
268 | // l'inverse, insertion des données d'une sauvegarde | 268 | else |
269 | else if($_GET['action'] == 'insertion') | 269 | { |
270 | { | 270 | accueil(); |
271 | require('controller/backup.php'); | 271 | } |
272 | insertion($_GET['from']); | ||
273 | } | ||
274 | else | ||
275 | { | ||
276 | accueil(); | ||
277 | } | ||
278 | } | ||
279 | |||
280 | // renvoi ici par le .htaccess si lien mort ou sans http:// au début | ||
281 | elseif(isset($_GET['erreur'])) | ||
282 | { | ||
283 | //if($_GET['erreur'] == 404) | ||
284 | //{ | ||
285 | // echo('<p style="color: red;" >ERREUR 404<br/>Le lien sur lequel vous avez cliqué pointe vers un emplacement introuvable.<br /> | ||
286 | // Ce n\'est pas votre faute. Vous pouvez éventuellement rechercher la page demandée avec votre moteur de recherche ou prévenir le responsable du site.</p>'); | ||
287 | // echo('<p><a href="index.php" >Retour au site</a></p>'); | ||
288 | //} | ||
289 | //else | ||
290 | //{ | ||
291 | accueil(); | ||
292 | //} | ||
293 | } | ||
294 | |||
295 | // page d'accueil (adresse sans GET valable) | ||
296 | else | ||
297 | { | ||
298 | accueil(); | ||
299 | } | ||