@@ -146,7 +146,7 @@ function save_courses_data($courses)
146146 }
147147
148148 if (!empty ($ msg )) {
149- echo Display::return_message ($ msg , 'normal ' , false );
149+ Display::addFlash (Display:: return_message ($ msg , 'normal ' , false ) );
150150 }
151151}
152152
@@ -180,65 +180,64 @@ function parse_csv_courses_data($file)
180180$ interbreadcrumb [] = ['url ' => 'index.php ' , 'name ' => get_lang ('Administration ' )];
181181
182182set_time_limit (0 );
183- $ csvCustomError = '' ;
184- $ topStaticErrorHtml = '' ;
185- $ delimiterError = false ;
186- $ errors = [];
187- Display::display_header ($ tool_name );
188183
189- if (isset ($ _POST ['formSent ' ]) && $ _POST ['formSent ' ]) {
184+ // Build the form first and protect it: FormValidator::protect() adds the CSRF
185+ // token and $form->validate() verifies it before any processing runs.
186+ $ form = new FormValidator (
187+ 'import ' ,
188+ 'post ' ,
189+ api_get_self (),
190+ null ,
191+ ['enctype ' => 'multipart/form-data ' ]
192+ );
193+ $ form ->protect ();
194+ $ form ->addHeader ($ tool_name );
195+ $ form ->addElement ('file ' , 'import_file ' , get_lang ('CSV file import location ' ));
196+ $ form ->addElement ('checkbox ' , 'add_me_as_teacher ' , null , get_lang ('Add me as teacher in the imported courses. ' ));
197+ $ form ->addButtonImport (get_lang ('Import ' ), 'save ' );
198+
199+ if ($ form ->validate ()) {
190200 if (empty ($ _FILES ['import_file ' ]['tmp_name ' ])) {
191- $ error_message = get_lang ('The file upload has failed. ' );
192- echo Display::return_message ($ error_message , 'error ' , false );
201+ Display::addFlash (Display::return_message (get_lang ('The file upload has failed. ' ), 'error ' , false ));
193202 } else {
194203 $ allowed_file_mimetype = ['csv ' ];
195204
196205 $ ext_import_file = substr ($ _FILES ['import_file ' ]['name ' ], strrpos ($ _FILES ['import_file ' ]['name ' ], '. ' ) + 1 );
197206
198207 if (!in_array ($ ext_import_file , $ allowed_file_mimetype )) {
199- echo Display::return_message (get_lang ('You must import a file corresponding to the selected format ' ), 'error ' );
208+ Display::addFlash (Display:: return_message (get_lang ('You must import a file corresponding to the selected format ' ), 'error ' ) );
200209 } else {
201210 $ check = Import::assertCommaSeparated ($ _FILES ['import_file ' ]['tmp_name ' ], true );
202211 if (true !== $ check ) {
203- $ csvCustomError = $ check ;
204- $ topStaticErrorHtml = Display::return_message ($ csvCustomError , 'error ' , false );
205- $ delimiterError = true ;
212+ Display::addFlash (Display::return_message ($ check , 'error ' , false ));
206213 } else {
207214 $ courses = parse_csv_courses_data ($ _FILES ['import_file ' ]['tmp_name ' ]);
208215 $ errors = validate_courses_data ($ courses );
209216 if (0 == count ($ errors )) {
210217 save_courses_data ($ courses );
218+ } else {
219+ $ error_message = '<ul> ' ;
220+ foreach ($ errors as $ error_course ) {
221+ $ error_message .= '<li> ' .get_lang ('Line ' ).' ' .$ error_course ['line ' ].': <strong> ' .$ error_course ['error ' ].'</strong>: ' ;
222+ $ error_message .= get_lang ('Course ' ).': ' .$ error_course ['Title ' ].' ( ' .$ error_course ['Code ' ].') ' ;
223+ $ error_message .= '</li> ' ;
224+ }
225+ $ error_message .= '</ul> ' ;
226+ Display::addFlash (Display::return_message ($ error_message , 'error ' , false ));
211227 }
212228 }
213229 }
214230 }
215- }
216- if (!empty ($ topStaticErrorHtml )) {
217- echo $ topStaticErrorHtml ;
218- }
219- if (isset ($ errors ) && 0 != count ($ errors )) {
220- $ error_message = '<ul> ' ;
221- foreach ($ errors as $ index => $ error_course ) {
222- $ error_message .= '<li> ' .get_lang ('Line ' ).' ' .$ error_course ['line ' ].': <strong> ' .$ error_course ['error ' ].'</strong>: ' ;
223- $ error_message .= get_lang ('Course ' ).': ' .$ error_course ['Title ' ].' ( ' .$ error_course ['Code ' ].') ' ;
224- $ error_message .= '</li> ' ;
225- }
226- $ error_message .= '</ul> ' ;
227- echo Display::return_message ($ error_message , 'error ' , false );
231+
232+ // Post/Redirect/Get: the CSRF token is single-use (validate() clears it),
233+ // so redirect to render the form again with a fresh token. All messages are
234+ // queued as flashes above and survive the redirect.
235+ header ('Location: ' .api_get_self ());
236+ exit ;
228237}
229238
230- $ form = new FormValidator (
231- 'import ' ,
232- 'post ' ,
233- api_get_self (),
234- null ,
235- ['enctype ' => 'multipart/form-data ' ]
236- );
237- $ form ->addHeader ($ tool_name );
238- $ form ->addElement ('file ' , 'import_file ' , get_lang ('CSV file import location ' ));
239- $ form ->addElement ('checkbox ' , 'add_me_as_teacher ' , null , get_lang ('Add me as teacher in the imported courses. ' ));
240- $ form ->addButtonImport (get_lang ('Import ' ), 'save ' );
241- $ form ->addElement ('hidden ' , 'formSent ' , 1 );
239+ Display::display_header ($ tool_name );
240+
242241$ form ->display ();
243242
244243$ content = '
0 commit comments