summaryrefslogtreecommitdiff
path: root/src/controller
diff options
context:
space:
mode:
Diffstat (limited to 'src/controller')
-rw-r--r--src/controller/ArticleController.php4
-rw-r--r--src/controller/UserController.php360
-rw-r--r--src/controller/ViewController.php39
-rw-r--r--src/controller/password.php328
4 files changed, 401 insertions, 330 deletions
diff --git a/src/controller/ArticleController.php b/src/controller/ArticleController.php
index e3e4edb..3b39335 100644
--- a/src/controller/ArticleController.php
+++ b/src/controller/ArticleController.php
@@ -19,12 +19,12 @@ class ArticleController
19 // cas d'une nouvelle "news" 19 // cas d'une nouvelle "news"
20 if(is_array($json['content'])){ 20 if(is_array($json['content'])){
21 foreach($json['content'] as $one_input){ 21 foreach($json['content'] as $one_input){
22 $one_input = Security::secureString($one_input); 22 $one_input = Security::secureHTML($one_input);
23 } 23 }
24 $content = $json['content']; 24 $content = $json['content'];
25 } 25 }
26 else{ 26 else{
27 $content = Security::secureString($json['content']); 27 $content = Security::secureHTML($json['content']);
28 } 28 }
29 29
30 // nouvel article 30 // nouvel article
diff --git a/src/controller/UserController.php b/src/controller/UserController.php
new file mode 100644
index 0000000..50e8bf7
--- /dev/null
+++ b/src/controller/UserController.php
@@ -0,0 +1,360 @@
1<?php
2// src/controller/PasswordController.php
3//
4// test mot de passe et captcha
5
6declare(strict_types=1);
7
8use Doctrine\ORM\EntityManager;
9use App\Entity\User;
10use App\Entity\Log;
11
12class UserController
13{
14 static public function existUsers(EntityManager $entityManager): bool
15 {
16 // optimiser ça si possible, on veut juste savoir si la table est vide ou non
17 $users = $entityManager->getRepository(User::class)->findAll();
18
19 if(count($users) === 0) // table vide
20 {
21 $_SESSION['user'] = '';
22 $_SESSION['admin'] = false;
23
24 return false;
25 }
26 else{
27 return true;
28 }
29 }
30
31 static public function createUser(EntityManager $entityManager)
32 {
33 // test mauvais paramètres
34 if(!isset($_POST['login']) || empty($_POST['login'])
35 || !isset($_POST['password']) || empty($_POST['password'])
36 || !isset($_POST['password_confirmation']) || empty($_POST['password_confirmation'])
37 || !isset($_POST['create_user_hidden']) || !empty($_POST['create_user_hidden']))
38 {
39 header('Location: ' . new URL);
40 die;
41 }
42
43 unset($_SESSION['user']);
44
45 $captcha_solution = (isset($_SESSION['captcha']) && is_int($_SESSION['captcha'])) ? $_SESSION['captcha'] : 0;
46 $captcha_try = isset($_POST['captcha']) ? Captcha::controlInput($_POST['captcha']) : 0;
47 unset($_SESSION['captcha']);
48
49 $error = '';
50 if($captcha_try == 0)
51 {
52 $error = 'error_non_valid_captcha';
53 }
54 elseif($captcha_solution == 0) // ne peut pas arriver, si?
55 {
56 $error = 'captcha_server_error';
57 }
58 elseif($captcha_try != $captcha_solution) // le test!
59 {
60 $error = 'bad_solution_captcha';
61 }
62 elseif($_POST['password'] !== $_POST['password_confirmation'])
63 {
64 $error = 'different_passwords';
65 }
66 else
67 {
68 $login = self::removeSpacesTabsCRLF(htmlspecialchars($_POST['login']));
69 $password = self::removeSpacesTabsCRLF(htmlspecialchars($_POST['password']));
70
71 // self::removeSpacesTabsCRLF prévient la validation par erreur d'une chaine "vide"
72
73 // conformité
74 if(!empty($password) && !empty($login)
75 && $password === $_POST['password'] && $login === $_POST['login'])
76 {
77 // enregistrement et redirection
78 $password = password_hash($password, PASSWORD_DEFAULT);
79 $user = new App\Entity\User($login, $password);
80 $entityManager->persist($user);
81 $entityManager->flush();
82
83 header('Location: ' . new URL);
84 die;
85 }
86 else{
87 $error = 'forbidden_characters';
88 }
89 }
90
91 $url = empty($error) ? new URL : new URL(['error' => $error]);
92 header('Location: ' . $url);
93 die;
94 }
95
96 static public function connect(EntityManager $entityManager): void
97 {
98 if($_SESSION['admin']) // déjà connecté?
99 {
100 header('Location: ' . new URL);
101 die;
102 }
103
104 $_SESSION['user'] = '';
105 $_SESSION['admin'] = false;
106
107 $captcha_solution = (isset($_SESSION['captcha']) && is_int($_SESSION['captcha'])) ? $_SESSION['captcha'] : 0;
108 $captcha_try = isset($_POST['captcha']) ? Captcha::controlInput($_POST['captcha']) : 0;
109 unset($_SESSION['captcha']);
110
111 $error = '';
112 if($captcha_try == 0)
113 {
114 $error = 'error_non_valid_captcha';
115 }
116 elseif($captcha_solution == 0) // pas censé se produire
117 {
118 $error = 'captcha_server_error';
119 }
120 elseif($captcha_try != $captcha_solution) // le test!
121 {
122 $error = 'bad_solution_captcha';
123 }
124 elseif(!isset($_POST['login']) || empty($_POST['login'])
125 || !isset($_POST['password']) || empty($_POST['password']))
126 {
127 $error = 'bad_login_or_password';
128 }
129 else // c'est OK
130 {
131 $login = trim($_POST['login']);
132 $password = trim($_POST['password']);
133 $user = self::getUser($login, $entityManager);
134
135 // enregistrement et redirection
136 if(!empty($user) && $login === $user->getLogin() && password_verify($password, $user->getPassword()))
137 {
138 $log = new Log(true);
139 $entityManager->persist($log);
140 $entityManager->flush();
141
142 // protection fixation de session, si l'attaquant crée un cookie de session, il est remplacé
143 session_regenerate_id(true);
144
145 $_SESSION['user'] = $login;
146 $_SESSION['admin'] = true;
147
148 $url = new URL(isset($_GET['from']) ? ['page' => $_GET['from']] : []);
149 isset($_GET['id']) ? $url->addParams(['id' => $_GET['id']]) : '';
150 header('Location: ' . $url);
151 die;
152 }
153 else
154 {
155 $log = new Log(false);
156 $entityManager->persist($log);
157 $entityManager->flush();
158 $error = 'bad_login_or_password';
159 }
160 }
161
162 // tous les cas sauf connexion réussie
163 sleep(1); // défense basique à la force brute
164 $url = new URL(isset($_GET['from']) ? ['page' => 'connexion', 'from' => $_GET['from']] : []);
165 isset($_GET['id']) ? $url->addParams(['id' => $_GET['id']]) : '';
166 !empty($error) ? $url->addParams(['error' => $error]) : '';
167 header('Location: ' . $url);
168 die;
169 }
170
171 static public function disconnect(): void
172 {
173 // nettoyage complet
174 $_SESSION = []; // mémoire vive
175 session_destroy(); // fichier côté serveur
176 setcookie('PHPSESSID', '', time() - 86400, '/'); // cookie de session
177
178 // retour même page
179 $url = new URL;
180 isset($_GET['from']) ? $url->addParams(['page' => $_GET['from']]) : '';
181 isset($_GET['id']) ? $url->addParams(['id' => $_GET['id']]) : '';
182 header('Location: ' . $url);
183 die;
184 }
185
186 static public function updateUsername(EntityManager $entityManager): void
187 {
188 if(!$_SESSION['admin']) // superflux, fait dans le routeur
189 {
190 self::disconnect();
191 }
192
193 $captcha_solution = (isset($_SESSION['captcha']) && is_int($_SESSION['captcha'])) ? $_SESSION['captcha'] : 0;
194 $captcha_try = isset($_POST['captcha']) ? Captcha::controlInput($_POST['captcha']) : 0;
195 unset($_SESSION['captcha']);
196
197 $url = new URL(['page' => 'user_edit']);
198 isset($_GET['from']) ? $url->addParams(['from' => $_GET['from']]) : null;
199
200 $error = '';
201 if(!isset($_POST['old_login']) || empty($_POST['old_login'])
202 || !isset($_POST['password']) || empty($_POST['password'])
203 || !isset($_POST['new_login']) || empty($_POST['new_login'])
204 || !isset($_POST['modify_username_hidden']) || !empty($_POST['modify_username_hidden']))
205 {
206 $error = 'bad_login_or_password';
207 }
208 elseif($captcha_try != $captcha_solution) // le test!
209 {
210 $error = 'bad_solution_captcha';
211 }
212 else
213 {
214 // sécurisation de la saisie
215 $old_login = $_POST['old_login'];
216 $password = $_POST['password'];
217 $new_login = self::removeSpacesTabsCRLF(htmlspecialchars($_POST['new_login']));
218 // removeSpacesTabsCRLF pour éviter d'enregistrer une chaîne vide
219
220 // tests de conformité
221 if($old_login !== $_POST['old_login'] || $password !== $_POST['password'] || $new_login !== $_POST['new_login'])
222 {
223 $error = 'forbidden_characters';
224 }
225 elseif($old_login !== $_SESSION['user']){
226 $error = 'bad_login_or_password';
227 }
228 elseif($old_login === $new_login){
229 $error = 'same_username_as_before';
230 }
231 else
232 {
233 $user = self::getUser($old_login, $entityManager);
234
235 if(password_verify($password, $user->getPassword()))
236 {
237 $user->setLogin($new_login);
238 $entityManager->flush();
239 $_SESSION['user'] = $new_login;
240
241 $url->addParams(['success_login' => 'new_login']);
242 $error = '';
243 }
244 else
245 {
246 $error = 'bad_login_or_password';
247 }
248 }
249 }
250
251 if(!empty($error)){
252 sleep(1);
253 $url->addParams(['error_login' => $error]);
254 }
255
256 header('Location: ' . $url);
257 die;
258 }
259
260 static public function updatePassword(EntityManager $entityManager): void
261 {
262 if(!$_SESSION['admin']) // superflux, fait dans le routeur
263 {
264 self::disconnect();
265 }
266
267 $captcha_solution = (isset($_SESSION['captcha']) && is_int($_SESSION['captcha'])) ? $_SESSION['captcha'] : 0;
268 $captcha_try = isset($_POST['captcha']) ? Captcha::controlInput($_POST['captcha']) : 0;
269 unset($_SESSION['captcha']);
270
271 $url = new URL(['page' => 'user_edit']);
272 isset($_GET['from']) ? $url->addParams(['from' => $_GET['from']]) : null;
273
274 $error = '';
275 if(!isset($_POST['login']) || empty($_POST['login'])
276 || !isset($_POST['old_password']) || empty($_POST['old_password'])
277 || !isset($_POST['new_password']) || empty($_POST['new_password'])
278 || !isset($_POST['modify_password_hidden']) || !empty($_POST['modify_password_hidden']))
279 {
280 $error = 'bad_login_or_password';
281 }
282 elseif($captcha_try != $captcha_solution) // le test!
283 {
284 $error = 'bad_solution_captcha';
285 }
286 else
287 {
288 // sécurisation de la saisie
289 $login = $_POST['login'];
290 $old_password = $_POST['old_password'];
291 $new_password = self::removeSpacesTabsCRLF(htmlspecialchars($_POST['new_password']));
292 // removeSpacesTabsCRLF pour éviter d'enregistrer une chaîne vide
293
294 // tests de conformité
295 if($login !== $_POST['login'] || $old_password !== $_POST['old_password'] || $new_password !== $_POST['new_password'])
296 {
297 $error = 'forbidden_characters';
298 }
299 elseif($login !== $_SESSION['user']){
300 $error = 'bad_login_or_password';
301 }
302 elseif($old_password === $new_password){
303 $error = 'same_password_as_before';
304 }
305 else
306 {
307 $user = self::getUser($login, $entityManager);
308
309 if(password_verify($old_password, $user->getPassword()))
310 {
311 $new_password = password_hash($new_password, PASSWORD_DEFAULT);
312 $user->setPassword($new_password);
313 $entityManager->flush();
314
315 $url->addParams(['success_password' => 'new_password']);
316 $error = '';
317 }
318 else
319 {
320 $error = 'bad_login_or_password';
321 }
322 }
323 }
324
325 if(!empty($error)){
326 sleep(1);
327 $url->addParams(['error_password' => $error]);
328 }
329
330 header('Location: ' . $url);
331 die;
332 }
333
334 static private function getUser(string $login, EntityManager $entityManager): ?User
335 {
336 $users = $entityManager->getRepository('App\Entity\User')->findBy(['login' => $login]);
337
338 if(count($users) === 0)
339 {
340 $_SESSION['user'] = '';
341 $_SESSION['admin'] = false;
342 }
343
344 foreach($users as $user)
345 {
346 if($user->getLogin() === $login)
347 {
348 return $user;
349 }
350 }
351 return null;
352 }
353
354 // erreurs à la création des mots de passe
355 static private function removeSpacesTabsCRLF(string $chaine): string
356 {
357 $cibles = [' ', "\t", "\n", "\r"]; // doubles quotes !!
358 return(str_replace($cibles, '', $chaine));
359 }
360} \ No newline at end of file
diff --git a/src/controller/ViewController.php b/src/controller/ViewController.php
new file mode 100644
index 0000000..69955c6
--- /dev/null
+++ b/src/controller/ViewController.php
@@ -0,0 +1,39 @@
1<?php
2// src/view/ViewController.php
3//
4// génère le HTML avec des Builder
5
6declare(strict_types=1);
7
8use App\Entity\Node;
9use Doctrine\ORM\EntityManager;
10use Symfony\Component\HttpFoundation\Request;
11use Symfony\Component\HttpFoundation\Response;
12
13class ViewController extends AbstractBuilder
14{
15 static public Node $root_node;
16
17 public function __construct(){}
18
19 public function buildView(Request $request, EntityManager $entityManager): Response
20 {
21 // accès au modèle
22 $director = new Director($entityManager, true);
23 $director->makeRootNode(htmlspecialchars($request->query->get('id') ?? ''));
24 self::$root_node = $director->getNode();
25
26 // mode modification d'une page activé
27 if($_SESSION['admin'] && $request->query->has('page')
28 && $request->query->has('action') && $request->query->get('action') === 'modif_page'
29 && $request->query->get('page') !== 'connexion' && $request->query->get('page') !== 'article' && $request->query->get('page') !== 'nouvelle_page' && $request->query->get('page') !== 'menu_chemins'){
30 // les contrôles de la 2è ligne devraient utiliser un tableau
31 MainBuilder::$modif_mode = true;
32 }
33
34 // construction de la page
35 $this->useChildrenBuilder(self::$root_node);
36
37 return new Response($this->html, 200);
38 }
39} \ No newline at end of file
diff --git a/src/controller/password.php b/src/controller/password.php
deleted file mode 100644
index 3d003da..0000000
--- a/src/controller/password.php
+++ /dev/null
@@ -1,328 +0,0 @@
1<?php
2// src/controller/password.php
3//
4// test mot de passe et captcha
5
6declare(strict_types=1);
7
8use Doctrine\ORM\EntityManager;
9use App\Entity\User;
10use App\Entity\Log;
11
12// exécutée dans installation.php à l'ouverture de chaque page
13function existUsers(EntityManager $entityManager)
14{
15 // lecture
16 $users = $entityManager->getRepository(User::class)->findAll();
17
18 // cas particulier table vide
19 if(count($users) === 0)
20 {
21 $_GET = [];
22 $_SESSION['user'] = '';
23 $_SESSION['admin'] = false;
24
25 // création d'un utilisateur, puis rechargement de la page
26 createPassword($entityManager);
27 }
28}
29
30
31function createPassword(EntityManager $entityManager)
32{
33 // fonction exécutée à priori deux fois d'affilée: affichage puis traitement de la saisie
34
35 unset($_SESSION['user']);
36
37 $captcha_solution = (isset($_SESSION['captcha']) && is_int($_SESSION['captcha'])) ? $_SESSION['captcha'] : 0;
38 $captcha_try = isset($_POST['captcha']) ? Captcha::controlInput($_POST['captcha']) : 0;
39
40 // II - traitement
41 $error = '';
42 if(!isset($_POST['captcha'])) // page création d'un compte rechargée
43 {
44 //$error = '';
45 }
46 elseif($captcha_try == 0)
47 {
48 $error = 'error_non_valid_captcha';
49 }
50 elseif($captcha_solution == 0)
51 {
52 //$error = '';
53 }
54 elseif($captcha_try != $captcha_solution) // le test!
55 {
56 $error = 'bad_solution_captcha';
57 }
58 elseif(!isset($_POST['password']) || empty($_POST['password'])
59 || (!isset($_POST['login']) || empty($_POST['login'])))
60 {
61 $error = 'bad_login_or_password';
62 }
63 else
64 {
65 $login = Security::secureString($_POST['login']);
66 $password = Security::secureString($_POST['password']);
67
68 // -> prévenir la validation par erreur d'une chaine "vide"
69 $login = removeSpacesTabsCRLF($login);
70 $password = removeSpacesTabsCRLF($password);
71
72 // conformité
73 if(isset($password) && isset($login)
74 && $password == $_POST['password'] && $login == $_POST['login'])
75 {
76 unset($_SESSION['captcha']);
77
78 // enregistrement et redirection
79 $password = password_hash($password, PASSWORD_DEFAULT);
80 $user = new App\Entity\User($login, $password);
81 $entityManager->persist($user);
82 $entityManager->flush();
83
84 header('Location: ' . new URL);
85 exit();
86 }
87 else
88 {
89 $error = 'bad_login_or_password';
90
91 // compteur dans la session et blocage de compte
92 }
93 }
94
95 // inséré dans $captchaHtml puis dans $formulaireNouveauMDP
96 $captcha = new Captcha;
97 // enregistrement de la réponse du captcha pour vérification
98 $_SESSION['captcha'] = $captcha->getSolution();
99
100
101 // I - affichage
102 $title = 'Bienvenue nageur bigouden';
103 $subHeading = 'Veuillez choisir les codes que vous utiliserez pour gérer le site.';
104
105 // même vue que la fonction changerMotDePasse()
106 require('../src/view/password.php');
107
108 echo($header);
109 if($error != '')
110 {
111 sleep(1);
112 echo($error_messages[$error]);
113 }
114 echo($formulaireNouveauMDP);
115 echo($error_messages['forbidden_characters']);
116 echo($footer);
117 die;
118}
119
120
121function connect(LoginBuilder $builder, EntityManager $entityManager)
122{
123 // déjà connecté
124 if($_SESSION['admin'])
125 {
126 header('Location: ' . new URL);
127 die;
128 }
129
130 // II - traitement
131 $_SESSION['user'] = '';
132 $_SESSION['admin'] = false;
133
134 $captcha_solution = (isset($_SESSION['captcha']) && is_int($_SESSION['captcha'])) ? $_SESSION['captcha'] : 0;
135 $captcha_try = isset($_POST['captcha']) ? Captcha::controlInput($_POST['captcha']) : 0;
136
137 $error = '';
138 if(!isset($_POST['captcha'])) // page rechargée
139 {
140 //$error = '';
141 }
142 elseif($captcha_try == 0)
143 {
144 $error = 'error_non_valid_captcha';
145 }
146 elseif($captcha_solution == 0)
147 {
148 //$error = '';
149 }
150 elseif($captcha_try != $captcha_solution) // le test!
151 {
152 $error = 'bad_solution_captcha';
153 }
154 elseif(!isset($_POST['login']) || empty($_POST['login'])
155 || !isset($_POST['password']) || empty($_POST['password']))
156 {
157 $error = 'bad_login_or_password';
158 }
159 else // c'est OK
160 {
161 $login = Security::secureString($_POST['login']);
162 $password = Security::secureString($_POST['password']);
163 $user = getUser($login, $entityManager);
164
165 // enregistrement et redirection
166 if(!empty($user) && $login === $user->getLogin() && password_verify($password, $user->getPassword()))
167 {
168 $log = new Log(true);
169 $entityManager->persist($log);
170 $entityManager->flush();
171
172 session_regenerate_id(true); // protection fixation de session, si l'attaquant a créé un cookie de session (attaque XSS), il est remplacé
173 //unset($_SESSION['captcha']);
174 $_SESSION['user'] = $login;
175 $_SESSION['admin'] = true;
176 $link = new URL(isset($_GET['from']) ? ['page' => $_GET['from']] : []);
177 isset($_GET['id']) ? $link->addParams(['id' => $_GET['id']]) : '';
178 header('Location: ' . $link);
179 die;
180 }
181 else
182 {
183 $log = new Log(false);
184 $entityManager->persist($log);
185 $entityManager->flush();
186 $error = 'bad_login_or_password';
187 }
188 }
189
190 // inséré dans $captchaHtml puis dans $formulaireNouveauMDP
191 $captcha = new Captcha;
192 // enregistrement de la réponse du captcha pour vérification
193 $_SESSION['captcha'] = $captcha->getSolution(); // int
194
195 // I - affichage
196 $title = "Connexion";
197 $subHeading = "Veuillez saisir votre identifiant (e-mail) et votre mot de passe.";
198
199 require('../src/view/password.php');
200
201 //$builder->addHTML($header);
202 if($error != '')
203 {
204 sleep(1);
205 $builder->addHTML($error_messages[$error]);
206 }
207 $builder->addHTML($formulaireConnexion);
208 //$builder->addHTML($warning_messages['message_cookie']);
209 $builder->addHTML($warning_messages['private_browsing']);
210 $builder->addHTML($footer);
211
212 //die;
213}
214
215
216function changePassword(EntityManager $entityManager): void
217{
218 // fonction exécutée à priori deux fois d'affilée: affichage puis traitement de la saisie
219
220 // II - traitement
221 $error = '';
222 $success = false;
223 if(empty($_POST)) // première fois ou page rechargée
224 {
225 //
226 }
227 elseif(!isset($_POST['login']) || empty($_POST['login'])
228 || !isset($_POST['old_password']) || empty($_POST['old_password'])
229 || !isset($_POST['new_password']) || empty($_POST['new_password'])
230 || !isset($_POST['modify_password_hidden']) || !empty($_POST['modify_password_hidden']))
231 {
232 $error = 'bad_login_or_password';
233 }
234 else
235 {
236 // sécurisation de la saisie
237 $new_password = Security::secureString($_POST['new_password']);
238 $login = Security::secureString($_POST['login']);
239 $old_password = Security::secureString($_POST['old_password']);
240
241 // éviter d'enregistrer une chaîne vide
242 $new_password = removeSpacesTabsCRLF($new_password);
243
244 // tests de conformité
245 if($login != $_POST['login'] || $old_password != $_POST['old_password'] || $new_password != $_POST['new_password'])
246 {
247 $error = 'forbidden_characters';
248 }
249 elseif($login !== $_SESSION['user']){
250 $error = 'bad_login_or_password';
251 }
252 else
253 {
254 $user = getUser($login, $entityManager);
255
256 if(password_verify($old_password, $user->getPassword()))
257 {
258 // enregistrement et redirection
259 $new_password = password_hash($new_password, PASSWORD_DEFAULT);
260 $user->setPassword($new_password);
261 $entityManager->flush();
262 $success = true;
263 }
264 else
265 {
266 $error = 'bad_login_or_password';
267 }
268 }
269 }
270
271
272 // I - affichage
273 $title = "Nouveau mot de passe";
274 $subHeading = "Veuillez vous identifier à nouveau puis saisir votre nouveau mot de passe.";
275
276 require('../src/view/password.php');
277
278 echo($header);
279 if($error != '')
280 {
281 sleep(1); // sécurité TRÈS insuffisante à la force brute
282 echo($error_messages[$error]);
283 }
284 elseif($success)
285 {
286 $success = false;
287 echo($alertJSNewPassword);
288 //header("Location: " . new URL(['page' => $_GET['from']])); // choisir "location" entre PHP et JS
289 die;
290 }
291 echo($formulaireModifMDP);
292 echo($footer);
293 die;
294}
295
296
297function getUser(string $login, EntityManager $entityManager): ?User
298{
299 $users = $entityManager->getRepository('App\Entity\User')->findBy(['login' => $login]);
300
301 if(count($users) === 0)
302 {
303 $_SESSION['user'] = '';
304 $_SESSION['admin'] = false;
305 }
306
307 foreach($users as $user)
308 {
309 if($user->getLogin() === $login)
310 {
311 return $user;
312 }
313 }
314 return null;
315}
316
317
318function disconnect()
319{
320 // nettoyage complet
321 $_SESSION = []; // mémoire vive
322 session_destroy(); // fichier côté serveur
323 setcookie('PHPSESSID', '', time() - 4200, '/'); // cookie de session
324 $link = new URL(['page' => $_GET['page']]);
325 isset($_GET['id']) ? $link->addParams(['id' => $_GET['id']]) : '';
326 header('Location: ' . $link);
327 die;
328} \ No newline at end of file