diff --git a/app/controllers/admin/courses.php b/app/controllers/admin/courses.php index 53fdbc4b4c3fefd3d94af6a6dc7995def7c0c54d..2ff2a9e2f5cf15214c80e3c62b9220a22469b757 100644 --- a/app/controllers/admin/courses.php +++ b/app/controllers/admin/courses.php @@ -706,7 +706,7 @@ class Admin_CoursesController extends AuthenticatedController foreach ($icons as $icon) { $d['contents'] .= '<li class="my-courses-navigation-item '. ($icon->getImage()->signalsAttention() ? 'my-courses-navigation-important' : '').'"> - <a href="'. URLHelper::getLink('seminar_main.php', ['auswahl' => $course->id, 'redirect_to' => $icon->getURL()]).'"'. ($icon->getTitle() ? ' title="'.htmlReady($icon->getTitle()).'"' : '') .'> + <a href="'. URLHelper::getLink('dispatch.php/course/go', ['to' => $course->id, 'redirect_to' => $icon->getURL()]).'"'. ($icon->getTitle() ? ' title="'.htmlReady($icon->getTitle()).'"' : '') .'> '. $icon->getImage()->asImg() .' </a> </li>'; diff --git a/app/controllers/api/oauth2/oauth2_controller.php b/app/controllers/api/oauth2/oauth2_controller.php index 6b3dacd37158609030c11bcd9fd21bd432bcea4c..e9208fce3aa26ec60aeeff7f9a9ec1d7b0d96123 100644 --- a/app/controllers/api/oauth2/oauth2_controller.php +++ b/app/controllers/api/oauth2/oauth2_controller.php @@ -15,13 +15,6 @@ abstract class OAuth2Controller extends StudipController { parent::before_filter($action, $args); - page_open([ - 'sess' => 'Seminar_Session', - 'auth' => 'Seminar_Default_Auth', - 'perm' => 'Seminar_Perm', - 'user' => 'Seminar_User', - ]); - $this->set_layout(null); $this->container = new Studip\OAuth2\Container(); diff --git a/app/controllers/blubber.php b/app/controllers/blubber.php index 8ede39ee478140a8f797d433b6e23b425282bac9..550770bbe23efc8061df19f91885928bbfb40b8c 100644 --- a/app/controllers/blubber.php +++ b/app/controllers/blubber.php @@ -423,7 +423,7 @@ class BlubberController extends AuthenticatedController ); PageLayout::postSuccess(sprintf(_('Studiengruppe "%s" wurde angelegt.'), htmlReady($course['name']))); - $this->redirect(URLHelper::getURL('seminar_main.php', ['auswahl' => $course->getId()])); + $this->redirect(URLHelper::getURL('dispatch.php/course/go', ['to' => $course->getId()])); } } diff --git a/app/controllers/consultation/admin.php b/app/controllers/consultation/admin.php index 21507edb0418176d60288f835322003f09b43e97..011e42462d1a13e54f9309d2499dcad50a1e6806 100644 --- a/app/controllers/consultation/admin.php +++ b/app/controllers/consultation/admin.php @@ -790,7 +790,7 @@ class Consultation_AdminController extends ConsultationController // Redirect to message write $_SESSION['sms_data'] = compact('p_rec'); - page_close(); + sess()->save(); $this->redirect(URLHelper::getURL( 'dispatch.php/messages/write', compact('default_subject') diff --git a/app/controllers/course/basicdata.php b/app/controllers/course/basicdata.php index f463a043cc7a8d6e47a68213dd431fc641dc0cde..4524153feca47ca5beeb2168ba658fa73fba685f 100644 --- a/app/controllers/course/basicdata.php +++ b/app/controllers/course/basicdata.php @@ -368,7 +368,7 @@ class Course_BasicdataController extends AuthenticatedController _('Veranstaltung kopieren'), $this->url_for( 'course/wizard/copy/' . $this->course_id, - ['studip_ticket' => Seminar_Session::get_ticket()] + ['studip_ticket' => get_ticket()] ), Icon::create('seminar') ); @@ -381,7 +381,7 @@ class Course_BasicdataController extends AuthenticatedController _('Sperrebene ändern') . ' (' . ($is_locked ? _('gesperrt') : _('nicht gesperrt')) . ')', $this->url_for( 'course/management/lock', - ['studip_ticket' => Seminar_Session::get_ticket()] + ['studip_ticket' => get_ticket()] ), Icon::create('lock-' . ($is_locked ? 'locked' : 'unlocked')) )->asDialog('size=auto'); @@ -397,7 +397,7 @@ class Course_BasicdataController extends AuthenticatedController $is_visible ? _('Veranstaltung verstecken') : _('Veranstaltung sichtbar schalten'), $this->url_for( 'course/management/change_visibility', - ['studip_ticket' => Seminar_Session::get_ticket()] + ['studip_ticket' => get_ticket()] ), Icon::create('visibility-' . ($is_visible ? 'visible' : 'invisible')) ); @@ -428,7 +428,7 @@ class Course_BasicdataController extends AuthenticatedController _('Veranstaltung löschen'), $this->url_for( 'course/archive/confirm', - ['studip_ticket' => Seminar_Session::get_ticket()] + ['studip_ticket' => get_ticket()] ), Icon::create('trash') )->asDialog('size=auto'); diff --git a/app/controllers/course/details.php b/app/controllers/course/details.php index 707b0ed990d30387f18e89bee0c07e526e38b04e..ab1c2a6921c1c8e5530567291bcdc9c028626260 100644 --- a/app/controllers/course/details.php +++ b/app/controllers/course/details.php @@ -39,7 +39,7 @@ class Course_DetailsController extends AuthenticatedController } $this->send_from_search_page = Request::get('send_from_search_page'); - if ($GLOBALS['SessionSeminar'] != $this->course->id + if (isset($GLOBALS['SessionSeminar']) && $GLOBALS['SessionSeminar'] != $this->course->id && !(int)$this->course->visible && !($GLOBALS['perm']->have_perm(Config::get()->SEM_VISIBILITY_PERM) || $GLOBALS['perm']->have_studip_perm('user', $this->course->id))) { @@ -52,7 +52,7 @@ class Course_DetailsController extends AuthenticatedController if ($this->course->getSemClass()->offsetGet('studygroup_mode')) { if ($GLOBALS['perm']->have_studip_perm('autor', $this->course->id)) { // participants may see seminar_main - $link = URLHelper::getUrl('seminar_main.php', ['auswahl' => $this->course->id]); + $link = URLHelper::getUrl('dispatch.php/course/go', ['to' => $this->course->id]); } else { $link = URLHelper::getUrl('dispatch.php/course/studygroup/details/' . $this->course->id, [ 'send_from_search_page' => $this->send_from_search_page, @@ -202,7 +202,7 @@ class Course_DetailsController extends AuthenticatedController $enrolment_info = null; - if ($GLOBALS['SessionSeminar'] === $this->course->id) { + if (isset($GLOBALS['SessionSeminar']) && $GLOBALS['SessionSeminar'] === $this->course->id) { Navigation::activateItem('/course/main/details'); } else { $enrolment_info = $this->course->getEnrolmentInformation($GLOBALS['user']->id); diff --git a/app/controllers/course/enrolment.php b/app/controllers/course/enrolment.php index e2c0e76b0444dc714f7d41283a2c0c7f78c6e15a..97aa62e863bc94c8829b60a6f2c9a291307022bf 100644 --- a/app/controllers/course/enrolment.php +++ b/app/controllers/course/enrolment.php @@ -49,7 +49,7 @@ class Course_EnrolmentController extends AuthenticatedController || ($enrolment_info->getCodeword() === 'free_access' && !User::findCurrent()) ) ) { - $redirect_url = URLHelper::getUrl('seminar_main.php', ['auswahl' => $this->course_id]); + $redirect_url = URLHelper::getUrl('dispatch.php/course/go', ['to' => $this->course_id]); if (Request::isXhr()) { $this->response->add_header('X-Location', $redirect_url); $this->render_nothing(); @@ -252,7 +252,7 @@ class Course_EnrolmentController extends AuthenticatedController if (!empty($course) && $course->admission_prelim) { $this->relocate(URLHelper::getLink('dispatch.php/course/details', ['sem_id' => $this->course_id])); } else { - $this->relocate(URLHelper::getLink('seminar_main.php', ['auswahl' => $this->course_id])); + $this->relocate(URLHelper::getLink('dispatch.php/course/go', ['to' => $this->course_id])); } } elseif ($enrol_user) { diff --git a/app/controllers/course/go.php b/app/controllers/course/go.php new file mode 100644 index 0000000000000000000000000000000000000000..03ae1dfa7f649de5e7800032acc5f87af81dcefc --- /dev/null +++ b/app/controllers/course/go.php @@ -0,0 +1,69 @@ +<?php +/** + * dispatch.php/course/go - startpage for course controller, formerly known as seminar_main.php + * + * @author André Noack <noack@data-quest.de> + * @license GPL2 or any later version + * @since 6.0 + */ + +class Course_GoController extends AuthenticatedController +{ + protected $allow_nobody = true; + + public function __construct(\Trails\Dispatcher $dispatcher) + { + if (Request::option('to')) { + Request::set('cid', Request::option('to')); + } + parent::__construct($dispatcher); + } + + public function index_action() + { + $course_id = Context::getId(); + + if (!$course_id && Request::get('cid')) { + $archive_id = Request::get('cid'); + $archived = ArchivedCourse::find($archive_id); + if ($archived) { + $this->redirect(URLHelper::getURL('dispatch.php/search/archive', [ + 'criteria' => $archived->name, + ])); + return; + } + } + + if (!$course_id) { + throw new CheckObjectException(_('Sie haben kein Objekt gewählt.')); + } + + //set visitdate for course, when coming from my_courses + if (Request::get('to')) { + object_set_visit($course_id, 0); + } + + + // gibt es eine Anweisung zur Umleitung? + $redirect_to = Request::get('redirect_to'); + if ($redirect_to) { + if (!is_internal_url($redirect_to)) { + throw new Exception('Invalid redirection'); + } + + $this->redirect(URLHelper::getURL($redirect_to, ['cid' => $course_id])); + return; + } + + // der Nutzer zum ersten + //Reiter der Veranstaltung weiter geleitet. + if (Navigation::hasItem("/course")) { + foreach (Navigation::getItem("/course")->getSubNavigation() as $index => $navigation) { + if ($index !== 'admin') { + $this->redirect(URLHelper::getURL($navigation->getURL())); + return; + } + } + } + } +} diff --git a/app/controllers/course/members.php b/app/controllers/course/members.php index 822f4a4df48addc304d841cbb463bf21edeb87e5..df36820c501811a3479094b517c50fee196662ce 100644 --- a/app/controllers/course/members.php +++ b/app/controllers/course/members.php @@ -143,7 +143,7 @@ class Course_MembersController extends AuthenticatedController $this->tutoren = $filtered_members['tutor']->toArray(); $this->autoren = $filtered_members['autor']->toArray(); $this->users = $filtered_members['user']->toArray(); - $this->studipticket = Seminar_Session::get_ticket(); + $this->studipticket = get_ticket(); $this->subject = $this->getSubject(); $this->groups = $this->status_groups; $this->semAdmissionEnabled = false; diff --git a/app/controllers/course/statusgroups.php b/app/controllers/course/statusgroups.php index cbd80ad40c50f10b637ae6f765a88ad3f4b63016..24efa022278273f917fe4bcb10294a82523407f6 100644 --- a/app/controllers/course/statusgroups.php +++ b/app/controllers/course/statusgroups.php @@ -1582,7 +1582,7 @@ class Course_StatusgroupsController extends AuthenticatedController _('Die Gruppen wurden in die Veranstaltung %s kopiert.'), sprintf( '<a href="%s">%s</a>', - URLHelper::getLink('seminar_main.php', ['auswahl' => $target_course_id], true), + URLHelper::getLink('dispatch.php/course/go', ['to' => $target_course_id], true), htmlReady($target_course->getFullName()) ), )); diff --git a/app/controllers/course/studygroup.php b/app/controllers/course/studygroup.php index e9a0f02e377255810951e2dd733400dfe1d023f7..981a152f2a5c2e9f7ca6c773755ef7175a7edb9a 100644 --- a/app/controllers/course/studygroup.php +++ b/app/controllers/course/studygroup.php @@ -108,7 +108,7 @@ class Course_StudygroupController extends AuthenticatedController $icon = $icon->copyWithRole('info'); $infotext = _('Mitgliedschaft bereits beantragt!'); } else { - $infolink = URLHelper::getURL('seminar_main.php', ['auswahl' => $studygroup->id]); + $infolink = URLHelper::getURL('dispatch.php/course/go', ['to' => $studygroup->id]); $infotext = _('Direkt zur Studiengruppe'); } } else if ($GLOBALS['perm']->have_perm('admin')) { @@ -205,7 +205,7 @@ class Course_StudygroupController extends AuthenticatedController Sidebar::get()->addWidget($actions); } // ... otherwise redirect us to the seminar else { - $this->redirect(URLHelper::getURL('seminar_main.php?auswahl=' . $id)); + $this->redirect(URLHelper::getURL('dispatch.php/course/go?to=' . $id)); } } @@ -408,7 +408,7 @@ class Course_StudygroupController extends AuthenticatedController } if (!$perm->have_studip_perm('tutor', $id)) { - $this->redirect(URLHelper::getURL('seminar_main.php', ['auswahl' => $id])); + $this->redirect(URLHelper::getURL('dispatch.php/course/go', ['to' => $id])); return; } @@ -570,7 +570,7 @@ class Course_StudygroupController extends AuthenticatedController $id = Context::getId(); if (!$perm->have_studip_perm('tutor', $id)) { - $this->redirect(URLHelper::getURL('seminar_main.php', ['auswahl' => $id])); + $this->redirect(URLHelper::getURL('dispatch.php/course/go', ['to' => $id])); exit; } diff --git a/app/controllers/debugbar.php b/app/controllers/debugbar.php index 9fc5286c693d189d38a47970c054257accedd5ab..3f43bd28feb9bfa0243341f4692805373b45744a 100644 --- a/app/controllers/debugbar.php +++ b/app/controllers/debugbar.php @@ -1,5 +1,5 @@ <?php -final class DebugbarController extends Trails\Controller +final class DebugbarController extends StudipController { public function __construct( Trails\Dispatcher $dispatcher, @@ -10,15 +10,23 @@ final class DebugbarController extends Trails\Controller public function css_action(): void { - $this->set_content_type('text/css;charset=utf-8'); - $this->render_nothing(); + $this->response->add_header('Content-Type', 'text/css;charset=utf-8'); + + ob_start(); $this->debugbar->getJavascriptRenderer()->dumpCssAssets(); + $content = ob_get_contents(); + ob_end_clean(); + $this->render_text($content); + } public function js_action(): void { - $this->set_content_type('text/javascript;charset=utf-8'); - $this->render_nothing(); + $this->response->add_header('Content-Type', 'text/javascript;charset=utf-8'); + ob_start(); $this->debugbar->getJavascriptRenderer()->setIncludeVendors(false)->dumpJsAssets(); + $content = ob_get_contents(); + ob_end_clean(); + $this->render_text($content); } } diff --git a/app/controllers/login.php b/app/controllers/login.php new file mode 100644 index 0000000000000000000000000000000000000000..09a7c6b07fb1573fe470e2af68271219c86e1253 --- /dev/null +++ b/app/controllers/login.php @@ -0,0 +1,173 @@ +<?php +/** + * login.php - login + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * @author André Noack <noack@data-quest.de> + * @license http://www.gnu.org/licenses/gpl-2.0.html GPL version 2 + * @category Stud.IP + */ +class LoginController extends AuthenticatedController +{ + protected $allow_nobody = true; + + public function __construct(\Trails\Dispatcher $dispatcher) + { + Config::get()->USER_VISIBILITY_CHECK = false; + parent::__construct($dispatcher); + } + + public function index_action() + { + if ($GLOBALS['user']->id !== 'nobody') { + $this->redirect(URLHelper::getURL('dispatch.php/start')); + return; + } + + if (Request::isXhr()) { + if (Request::isDialog()) { + $this->relocate(URLHelper::getURL($_SERVER['REQUEST_URI'])); + return; + } + throw new AccessDeniedException(); + } + + if (Request::submitted('user_config_submitted')) { + CSRFProtection::verifyUnsafeRequest(); + if (Request::submitted('unset_contrast')) { + $_SESSION['contrast'] = 0; + $this->redirect('login/index'); //we're too late to remove the high contrast mode, so we reload the page + return; + } + if (Request::submitted('set_contrast')) { + $_SESSION['contrast'] = 1; + } + + + foreach (array_keys($GLOBALS['INSTALLED_LANGUAGES']) as $language_key) { + if (Request::submitted('set_language_' . $language_key)) { + $_SESSION['forced_language'] = $language_key; + $_SESSION['_language'] = $language_key; + init_i18n($_SESSION['_language']); + } + } + if (!empty($_SESSION['contrast'])) { + \PageLayout::addStylesheet('accessibility.css'); + } + + } + if (Request::isPost()) { + CSRFProtection::verifyUnsafeRequest(); + + $check_auth = StudipAuthAbstract::CheckAuthentication(Request::get('loginname'), Request::get('password')); + + if ($check_auth['uid']) { + $uid = $check_auth['uid']; + if (isset($check_auth['need_email_activation']) && $check_auth['need_email_activation'] == $uid) { + $this->need_email_activation = $uid; + $_SESSION['semi_logged_in'] = $uid; + $this->redirect('login/activate_email', ['uid' => $uid]); + return; + } else { + auth()->setAuthenticatedUser($check_auth['user']); + Metrics::increment('core.login.succeeded'); + sess()->regenerateId(['auth', '_language', 'phpCAS', 'contrast']); + if (isset($_SESSION['redirect_after_login'] )) { + $this->redirect($_SESSION['redirect_after_login']); + return; + } + $this->redirect('start/index'); + return; + } + } else { + Metrics::increment('core.login.failed'); + $this->error_msg = $check_auth['error']; + } + } + + + if ($this->error_msg) { + PageLayout::postException(_('Bei der Anmeldung trat ein Fehler auf!'), $this->error_msg); + } + $this->uname = (isset($this->auth["uname"]) ? $this->auth["uname"] : Request::username('loginname')); + $this->self_registration_activated = Config::get()->ENABLE_SELF_REGISTRATION; + + $news_entries = StudipNews::GetNewsByRange('login', true, false); + if (class_exists('LoginFaq')) { + $this->faq_entries = LoginFaq::findBySQL("1 ORDER BY `faq_id` ASC"); + } + $this->news_entries = array_values($news_entries); + PageLayout::setHelpKeyword('Basis.AnmeldungLogin'); + PageLayout::disableSidebar(); + PageLayout::setBodyElementId('login'); + } + + public function activate_email_action() + { + PageLayout::setTitle(_('E-Mail Aktivierung')); + $uid = Request::option('uid'); + $user = User::find($uid); + + if (!$user) { + throw new \Trails\Exception(400); + } + if (Request::get('key')) { + $key = $user->validation_key; + + if (Request::get('key') === $key) { + $user->validation_key = ''; + $user->store(); + unset($_SESSION['semi_logged_in']); + PageLayout::postSuccess(_('Ihre E-Mail-Adresse wurde erfolgreich geändert.')); + $this->redirect(URLHelper::getURL('dispatch.php/start')); + return; + } else if ($key == '') { + PageLayout::postInfo(_('Ihre E-Mail-Adresse ist bereits geändert.')); + $this->redirect(URLHelper::getURL('dispatch.php/start')); + return; + } else { + if (Request::get('key')) { + PageLayout::postError(_("Falscher Bestätigungscode.")); + } + $this->mail_explain = true; + if ($_SESSION['semi_logged_in'] == Request::option('uid')) { + $this->reenter_mail = true; + } else { + PageLayout::postInfo(_('Sie können sich einloggen und sich den Bestätigungscode neu oder an eine andere E-Mail-Adresse schicken lassen.')); + $this->redirect(URLHelper::getURL('dispatch.php/start')); + return; + } + } + + // checking semi_logged_in is important to avoid abuse + } else if (Request::get('email1') && Request::get('email2') && $_SESSION['semi_logged_in'] == Request::option('uid')) { + if (Request::get('email1') == Request::get('email2')) { + // change mail + $tmp_user = User::find(Request::option('uid')); + if ($tmp_user && $tmp_user->changeEmail(Request::get('email1'), true)) { + $_SESSION['semi_logged_in'] = false; + } + + } else { + PageLayout::postError(_('Die eingegebenen E-Mail-Adressen stimmen nicht überein. Bitte überprüfen Sie Ihre Eingabe.')); + } + $this->mail_explain = true; + $this->reenter_mail = true; + } else { + $this->mail_explain = true; + } + } + + public function privacy_info_action() + { + // this page must be accessible during visibility decision + Config::get()->USER_VISIBILITY_CHECK = false; + + PageLayout::setTitle(_('Erläuterungen zum Datenschutz')); + } +} diff --git a/app/controllers/logout.php b/app/controllers/logout.php new file mode 100644 index 0000000000000000000000000000000000000000..22a93f09bb11cadd53168a7e6e2b6bc76f9bb317 --- /dev/null +++ b/app/controllers/logout.php @@ -0,0 +1,63 @@ +<?php +/** + * logout.php - logout + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * @author André Noack <noack@data-quest.de> + * @license http://www.gnu.org/licenses/gpl-2.0.html GPL version 2 + * @category Stud.IP + */ +class LogoutController extends AuthenticatedController +{ + protected $allow_nobody = true; + + public function index_action() + { + if ($GLOBALS['user']->id !== 'nobody') { + $my_messaging_settings = $GLOBALS['user']->cfg->MESSAGING_SETTINGS; + + //Wenn Option dafuer gewaehlt, alle ungelsesenen Nachrichten als gelesen speichern + if ($my_messaging_settings["logout_markreaded"]) { + Message::markAllAs(); + } + + $logout_user = $GLOBALS['user']->id; + $_language = $_SESSION['_language']; + $contrast = UserConfig::get($GLOBALS['user']->id)->USER_HIGH_CONTRAST; + + // Get auth plugin of user before logging out since the $auth object will + // be modified by the logout + $auth_plugin = StudipAuthAbstract::getInstance($GLOBALS['user']->auth_plugin); + + sess()->destroy(); + //Session changed zuruecksetzen + $timeout=(time()-(15 * 60)); + $GLOBALS['user']->set_last_action($timeout); + + // Perform logout from auth plugin (if possible) + if ($auth_plugin instanceof StudipAuthSSO) { + $auth_plugin->logout(); + } + + sess()->start(); + $_SESSION['_language'] = $_language; + if ($contrast) { + $_SESSION['contrast'] = $contrast; + } + NotificationCenter::addObserver(function() { + throw new NotificationVetoException(); + }, '__invoke', 'PageCloseWillExecute'); + PageLayout::postSuccess( + _('Sie sind nun aus dem System abgemeldet.'), + array_filter([$GLOBALS['UNI_LOGOUT_ADD']]) + ); + } + + $this->redirect(URLHelper::getURL('dispatch.php/start')); + } +} diff --git a/app/controllers/media_proxy.php b/app/controllers/media_proxy.php index b98b49c9c738f1139c26aba1e36828b3d009181e..7b37544fc373f6f915417eff1e3d2c25438121dd 100644 --- a/app/controllers/media_proxy.php +++ b/app/controllers/media_proxy.php @@ -34,7 +34,7 @@ class MediaProxyController extends StudipController $config = Config::GetInstance(); $modified_since = NULL; - if (!Seminar_Session::is_current_session_authenticated() || + if (!sess()->isCurrentSessionAuthenticated() || $config->getValue('LOAD_EXTERNAL_MEDIA') != 'proxy') { throw new AccessDeniedException(); } diff --git a/app/controllers/my_courses.php b/app/controllers/my_courses.php index 187d6c6e438956d52b6092331b562ec0920ee305..c7a6771aa6faa2eaae3931cf4b72a30dacdc90c9 100644 --- a/app/controllers/my_courses.php +++ b/app/controllers/my_courses.php @@ -334,7 +334,7 @@ class MyCoursesController extends AuthenticatedController public function decline_action($course_id, $waiting = null) { $course = Course::find($course_id); - $ticket_check = Seminar_Session::check_ticket(Request::option('studipticket')); + $ticket_check = check_ticket(Request::option('studipticket')); if (LockRules::Check($course_id, 'participants')) { $lockdata = LockRules::getObjectRule($course_id); PageLayout::postError(sprintf( @@ -419,8 +419,8 @@ class MyCoursesController extends AuthenticatedController PageLayout::postQuestion( $message, - $this->declineURL($course_id, ['cmd' => $cmd, 'studipticket' => Seminar_Session::get_ticket()]), - $this->declineURL($course_id, ['cmd' => 'back', 'studipticket' => Seminar_Session::get_ticket()]) + $this->declineURL($course_id, ['cmd' => $cmd, 'studipticket' => get_ticket()]), + $this->declineURL($course_id, ['cmd' => 'back', 'studipticket' => get_ticket()]) ); $this->redirect('my_courses/index'); return; diff --git a/app/controllers/my_institutes.php b/app/controllers/my_institutes.php index 0e15489aeb85255fee4ac759d7455c1f1d304e27..6093e72f8467bb1f450d32764050a39ba4d70d49 100644 --- a/app/controllers/my_institutes.php +++ b/app/controllers/my_institutes.php @@ -33,13 +33,13 @@ class MyInstitutesController extends AuthenticatedController public function decline_inst_action($inst_id) { $institut = Institute::find($inst_id); - $ticket_check = Seminar_Session::check_ticket(Request::option('studipticket')); + $ticket_check = check_ticket(Request::option('studipticket')); if (Request::option('cmd') !== 'kill' && Request::get('cmd') !== 'back') { $this->flash['decline_inst'] = true; $this->flash['inst_id'] = $inst_id; $this->flash['name'] = $institut->name; - $this->flash['studipticket'] = Seminar_Session::get_ticket(); + $this->flash['studipticket'] = get_ticket(); } elseif (Request::get('cmd') === 'kill' && $ticket_check && Request::get('cmd') !== 'back') { $changed = InstituteMember::deleteBySQL( "user_id = ? AND Institut_id = ? AND inst_perms = 'user'", diff --git a/app/controllers/oer/endpoints.php b/app/controllers/oer/endpoints.php index 1ce9626e891d2d08bf3187c1788a1586c79b38e9..bf398bf79e12555712f3f4fb56758ad811da18f4 100644 --- a/app/controllers/oer/endpoints.php +++ b/app/controllers/oer/endpoints.php @@ -322,7 +322,7 @@ class Oer_EndpointsController extends StudipController while (ob_get_level()) { ob_end_clean(); } - page_close(); + sess()->save(); if (!file_exists($this->material->getFilePath())) { throw new Exception(_('Die gewünschte Datei konnte nicht gefunden werden.')); diff --git a/app/controllers/registration.php b/app/controllers/registration.php index 4c550ceae8d8d1d72b9ab9f3d5c8b7aa69c04b1a..5ca4cfd01d0cb7051c044d5d7354c20d2c178c2a 100644 --- a/app/controllers/registration.php +++ b/app/controllers/registration.php @@ -124,22 +124,85 @@ class RegistrationController extends AuthenticatedController $this->registrationform->addStoreCallback( function (Form $form) { $new_user = $form->getLastPart()->getContextObject(); - - $GLOBALS['sess']->regenerate_session_id(['auth']); - $GLOBALS['auth']->unauth(); - $GLOBALS['auth']->auth['jscript'] = true; - $GLOBALS['auth']->auth['perm'] = $new_user['perms']; - $GLOBALS['auth']->auth['uname'] = $new_user['username']; - $GLOBALS['auth']->auth['auth_plugin'] = $new_user['auth_plugin']; - $GLOBALS['auth']->auth_set_user_settings($new_user->user_id); - $GLOBALS['auth']->auth['uid'] = $new_user['user_id']; - - Seminar_Register_Auth::sendValidationMail($new_user); - + sess()->regenerateId(); + auth()->setAuthenticatedUser($new_user); + auth()->sendValidationMail($new_user); return 1; } ); $this->registrationform->autoStore()->setURL(URLHelper::getURL('dispatch.php/start')); } + + public function email_validation_action() + { + if (!User::findCurrent()) { + $_SESSION['redirect_after_login'] = Request::url(); + sess()->save(); + $this->redirect(URLHelper::getURL('dispatch.php/login')); + return; + } + // hier wird noch mal berechnet, welches secret in der Bestaetigungsmail uebergeben wurde + $secret = Request::option('secret'); + PageLayout::setHelpKeyword('Basis.AnmeldungMail'); + PageLayout::setTitle(_('Bestätigung der E-Mail-Adresse')); + //user bereits vorhanden + if ($GLOBALS['perm']->have_perm('autor')) { + $info = sprintf(_('Sie haben schon den Status <b>%s</b> im System. + Eine Aktivierung des Accounts ist nicht mehr nötig, um Schreibrechte zu bekommen'), $GLOBALS['user']->perms); + $details = []; + $details[] = sprintf('<a href="%s">%s</a>', URLHelper::getLink('index.php'), _('zurück zur Startseite')); + $message = MessageBox::info($info, $details); + } + + // So, wer bis hier hin gekommen ist gehoert zur Zielgruppe... + // Volltrottel (oder abuse) + elseif (empty($secret)) { + $message = MessageBox::error(_('Sie müssen den vollständigen Link aus der Bestätigungsmail in die Adresszeile Ihres Browsers kopieren.')); + } + + // abuse (oder Volltrottel) + else { + if (!Token::isValid($secret, User::findCurrent()->id)) { + $error = _('Der übergebene <em>Secret-Code</em> ist nicht korrekt.'); + $details = []; + $details[] = _('Sie müssen unter dem Benutzernamen eingeloggt sein, für den Sie die Bestätigungsmail erhalten haben.'); + $details[] = _('Und Sie müssen den vollständigen Link aus der Bestätigungsmail in die Adresszeile Ihres Browsers kopieren.'); + $message = MessageBox::error($error, $details); + + // Mail an abuse + $REMOTE_ADDR = $_SERVER['REMOTE_ADDR']; + $Zeit = date("H:i:s, d.m.Y", time()); + $username = User::findCurrent()->username; + StudipMail::sendAbuseMessage("Validation", "Secret falsch\n\nUser: $username\n\nIP: $REMOTE_ADDR\nZeit: $Zeit\n"); + } // alles paletti, Status ändern + else { + $studip_user = User::findCurrent(); + $studip_user->perms = 'autor'; + if (!$studip_user->store()) { + $error = _('Fehler! Bitte wenden Sie sich an den Systemadministrator.'); + $message = MessageBox::error($error); + } else { + $success = _('Ihr Status wurde erfolgreich auf <em>autor</em> gesetzt.<br> + Damit dürfen Sie in den meisten Veranstaltungen schreiben, für die Sie sich anmelden.'); + $details = []; + $details[] = _('Einige Veranstaltungen erfordern allerdings bei der Anmeldung die Eingabe eines Passwortes. + Dieses Passwort erfahren Sie von den Lehrenden der Veranstaltung.'); + $message = MessageBox::success($success, $details); + + // Auto-Inserts + AutoInsert::instance()->saveUser($studip_user->id, "autor"); + + auth()->setAuthenticatedUser(\User::build(['user_id' => 'nobody', 'perms' => null])); + + $info = sprintf(_('Die Statusänderung wird erst nach einem erneuten %sLogin%s wirksam!<br> + Deshalb wurden Sie jetzt automatisch ausgeloggt.'), + '<a href="' . URLHelper::getLink('index.php') . '"><em>', + '</em></a>'); + $message .= MessageBox::info($info); + } + $this->message = $message; + } + } + } } diff --git a/app/controllers/search/globalsearch.php b/app/controllers/search/globalsearch.php index 05fcda294353eab1e66630036758c91adf2958ef..6901f483e78adfe2b2a7bfbdcc40701c1710cc45 100644 --- a/app/controllers/search/globalsearch.php +++ b/app/controllers/search/globalsearch.php @@ -31,7 +31,7 @@ class Search_GlobalsearchController extends AuthenticatedController PageLayout::addHeadElement('meta', [ 'name' => 'studip-cache-prefix', - 'content' => md5("{$_COOKIE[Seminar_Session::class]}-{$GLOBALS['user']->id}"), + 'content' => md5("{$_COOKIE[$GLOBALS['SESSION_OPTIONS']['name']]}-{$GLOBALS['user']->id}"), ]); PageLayout::setBodyElementId('globalsearch-page'); diff --git a/app/controllers/settings/avatar.php b/app/controllers/settings/avatar.php index 31bd7050233ff41eedb3f603242a83b4db533e56..067e346bbc3df54de967529fe6ba0894a5a542dd 100644 --- a/app/controllers/settings/avatar.php +++ b/app/controllers/settings/avatar.php @@ -5,8 +5,6 @@ class Settings_AvatarController extends AuthenticatedController public function before_filter(&$action, &$args) { parent::before_filter($action, $args); - // Ensure user is logged in - $GLOBALS['auth']->login_if($action !== 'logout' && $GLOBALS['auth']->auth['uid'] === 'nobody'); if (!$GLOBALS['perm']->have_profile_perm('user', User::findCurrent()->id)) { throw new AccessDeniedException(_('Sie dürfen dieses Profil nicht bearbeiten')); @@ -20,4 +18,4 @@ class Settings_AvatarController extends AuthenticatedController $avatar = Avatar::getAvatar($this->user_id); $this->avatar_url = $avatar->getURL(Avatar::NORMAL); } -} \ No newline at end of file +} diff --git a/app/controllers/settings/settings.php b/app/controllers/settings/settings.php index 9cd00c09d1f6f7d804e0aa3aa682de075b67d339..294b2881e0c84d8409f09e39ceb14c5c5a8ffae5 100644 --- a/app/controllers/settings/settings.php +++ b/app/controllers/settings/settings.php @@ -35,9 +35,6 @@ abstract class Settings_SettingsController extends AuthenticatedController parent::before_filter($action, $args); - // Ensure user is logged in - $GLOBALS['auth']->login_if($action !== 'logout' && $GLOBALS['auth']->auth['uid'] === 'nobody'); - // extract username $username = Request::username('username', $GLOBALS['user']->username); $this->user = User::findByUsername($username); @@ -95,23 +92,6 @@ abstract class Settings_SettingsController extends AuthenticatedController } } - /** - * Adjust url_for so it imitates the parameters behaviour of URLHelper. - * This way you can add parameters by adding an associative array as last - * argument. - * - * @param mixed $to Path segments of the url (String) or url parameters - * (Array) - * @return String Generated url - */ - public function url_for($to = ''/*, ...*/) - { - $arguments = func_get_args(); - $parameters = is_array(end($arguments)) ? array_pop($arguments) : []; - $url = call_user_func_array('parent::url_for', $arguments); - return URLHelper::getURL($url, $parameters); - } - /** * Gets the default template for an action. * @@ -224,14 +204,9 @@ abstract class Settings_SettingsController extends AuthenticatedController $should_logout = $action === 'logout' && $this->flash['logout-token'] === Request::get('token'); if ($should_logout) { - $GLOBALS['sess']->delete(); - $GLOBALS['auth']->logout(); + $this->redirect('dispatch.php/logout'); } parent::after_filter($action, $args); - - if ($should_logout) { - $GLOBALS['user']->set_last_action(time() - 15 * 60); - } } } diff --git a/app/controllers/start.php b/app/controllers/start.php index 82310959fcccc89652105766a7ecc0d342c67832..b655fc01b25fafb91051170d27a2af221ce38f70 100644 --- a/app/controllers/start.php +++ b/app/controllers/start.php @@ -317,7 +317,7 @@ class StartController extends AuthenticatedController public function resend_validation_mail_action() { if ($GLOBALS['perm']->get_perm() === 'user') { - Seminar_Register_Auth::sendValidationMail($GLOBALS['user']); + auth()->sendValidationMail(); PageLayout::postSuccess( _('Die Bestätigungsmail wurde erneut verschickt.') ); @@ -360,13 +360,11 @@ class StartController extends AuthenticatedController $this->redirect('start/edit_mail_address'); return; } - $user = new User($GLOBALS['user']->id); + $user = \User::findCurrent(); $user->Email = $email1; $user->store(); - $GLOBALS['user']->Email = $user->Email; - - Seminar_Register_Auth::sendValidationMail($user); + auth()->sendValidationMail($user); PageLayout::postMessage(MessageBox::success( _('Ihre Mailadresse wurde geändert und die Bestätigungsmail erneut verschickt.') )); diff --git a/app/controllers/terms.php b/app/controllers/terms.php index 679a34774774e7b20ff40c69dd0451da03cf1341..d3a829ef1f62e37ffb4674befb476eb3a153e118 100644 --- a/app/controllers/terms.php +++ b/app/controllers/terms.php @@ -33,7 +33,7 @@ class TermsController extends AuthenticatedController $this->redirectUser(); } else { $_SESSION['logout_ticket'] = get_ticket(); - $this->redirectUser('logout.php'); + $this->redirectUser('dispatch.php/logout'); } } elseif (Request::get('action') === 'denied') { if (trim(Config::get()->TERMS_CONFIG['denial_message'])) { diff --git a/app/controllers/web_migrate.php b/app/controllers/web_migrate.php index 3553f9041a438d02b9dcd28c44ff5f020c82bc41..bf24e32a75ea9551c01e84f97dafe7215913eb69 100644 --- a/app/controllers/web_migrate.php +++ b/app/controllers/web_migrate.php @@ -12,7 +12,6 @@ class WebMigrateController extends StudipController public function before_filter(&$action, &$args) { - $GLOBALS['auth']->login_if(!$GLOBALS['perm']->have_perm('root')); $GLOBALS['perm']->check('root'); parent::before_filter($action, $args); diff --git a/app/views/admin/autoinsert/index.php b/app/views/admin/autoinsert/index.php index a4a999e32bd4599e9bb271c5473095ede2d1cc78..33dfdcfff86c950748d03e5df66971dc4cd784f4 100644 --- a/app/views/admin/autoinsert/index.php +++ b/app/views/admin/autoinsert/index.php @@ -83,7 +83,7 @@ <? foreach ($auto_sems as $auto_sem): ?> <tr> <td> - <a href="<?= URLHelper::getLink('seminar_main.php', ['auswahl' => $auto_sem['seminar_id']]) ?>"> + <a href="<?= URLHelper::getLink('dispatch.php/course/go', ['to' => $auto_sem['seminar_id']]) ?>"> <?= htmlReady($auto_sem['Name']) ?> </a> </td> diff --git a/app/views/admin/user/_course_files.php b/app/views/admin/user/_course_files.php index caac81ad8d3e2d95a6718675d1356154495a26ad..f2a9eae1e9ebd639d9f4f96430f557babbc7d5be 100644 --- a/app/views/admin/user/_course_files.php +++ b/app/views/admin/user/_course_files.php @@ -43,12 +43,12 @@ <? foreach ($file_data as $data): ?> <tr> <td> - <a href="<?= URLHelper::getLink('seminar_main.php', ['auswahl' => $data['course']->id]) ?>"> + <a href="<?= URLHelper::getLink('dispatch.php/course/go', ['to' => $data['course']->id]) ?>"> <?= htmlReady($data['course']->veranstaltungsnummer) ?> </a> </td> <td> - <a href="<?= URLHelper::getLink('seminar_main.php', ['auswahl' => $data['course']->id]) ?>"> + <a href="<?= URLHelper::getLink('dispatch.php/course/go', ['to' => $data['course']->id]) ?>"> <?= htmlReady($data['course']->name) ?> </a> </td> diff --git a/app/views/admin/user/_course_list.php b/app/views/admin/user/_course_list.php index a7e090bfb553ff1e1b572171ba126f5028c0c534..9250d7cb3c9ae295d85ccee963f1e2d9b681f760 100644 --- a/app/views/admin/user/_course_list.php +++ b/app/views/admin/user/_course_list.php @@ -38,12 +38,12 @@ <? foreach ($_memberships as $membership): ?> <tr> <td> - <a href="<?= URLHelper::getLink('seminar_main.php', ['auswahl' => $membership->course->id]) ?>"> + <a href="<?= URLHelper::getLink('dispatch.php/course/go', ['to' => $membership->course->id]) ?>"> <?= htmlReady($membership->course->veranstaltungsnummer) ?> </a> </td> <td> - <a href="<?= URLHelper::getLink('seminar_main.php', ['auswahl' => $membership->course->id]) ?>"> + <a href="<?= URLHelper::getLink('dispatch.php/course/go', ['to' => $membership->course->id]) ?>"> <?= htmlReady($membership->course->name) ?> </a> </td> diff --git a/app/views/admin/user/_priority_list.php b/app/views/admin/user/_priority_list.php index e835a88309d3647d517e38b4d896702f742de66d..acb2ca09b649e75c169bde3d40897d9fbc76a3ef 100644 --- a/app/views/admin/user/_priority_list.php +++ b/app/views/admin/user/_priority_list.php @@ -31,12 +31,12 @@ <? $course = Course::find($priority['seminar_id']) ?> <tr> <td> - <a href="<?= URLHelper::getLink('seminar_main.php', ['auswahl' => $course->id]) ?>"> + <a href="<?= URLHelper::getLink('dispatch.php/course/go', ['to' => $course->id]) ?>"> <?= htmlReady($course->veranstaltungsnummer) ?> </a> </td> <td> - <a href="<?= URLHelper::getLink('seminar_main.php', ['auswahl' => $course->id]) ?>"> + <a href="<?= URLHelper::getLink('dispatch.php/course/go', ['to' => $course->id]) ?>"> <?= sprintf('%s (%s)', htmlReady($course->getFullName('type-name')), htmlReady($course->getFullName('sem-duration-name'))) ?> </a> </td> diff --git a/app/views/admin/user/_waiting_list.php b/app/views/admin/user/_waiting_list.php index 1fd07242e6b4f2a1f3abd7f454e1bce17b98a214..d4b306eabf4e927fcb2756b8ccb1d35659deb47f 100644 --- a/app/views/admin/user/_waiting_list.php +++ b/app/views/admin/user/_waiting_list.php @@ -32,12 +32,12 @@ <? foreach ($memberships as $membership): ?> <tr> <td> - <a href="<?= URLHelper::getLink('seminar_main.php', ['auswahl' => $membership->course->id]) ?>"> + <a href="<?= URLHelper::getLink('dispatch.php/course/go', ['to' => $membership->course->id]) ?>"> <?= htmlReady($membership->course->veranstaltungsnummer) ?> </a> </td> <td> - <a href="<?= URLHelper::getLink('seminar_main.php', ['auswahl' => $membership->course->id]) ?>"> + <a href="<?= URLHelper::getLink('dispatch.php/course/go', ['to' => $membership->course->id]) ?>"> <?= sprintf('%s (%s)', htmlReady($membership->course->getFullName('type-name')), htmlReady($membership->course->getFullName('sem-duration-name'))) ?> </a> </td> diff --git a/app/views/api/oauth2/authorize.php b/app/views/api/oauth2/authorize.php index 57d4ef61bde7ce3006bb3af1439dd8722a246273..f1bf2b0ef44949dd6e48c8c43d02b765d2c11a88 100644 --- a/app/views/api/oauth2/authorize.php +++ b/app/views/api/oauth2/authorize.php @@ -50,7 +50,7 @@ ) ?><br> </p> - <form action="<?= URLHelper::getLink('logout.php') ?>" method="post"> + <form action="<?= URLHelper::getLink('dispatch.php/logout') ?>" method="post"> <button class="as-link"> <small> <?= sprintf( diff --git a/app/views/course/enrolment/apply.php b/app/views/course/enrolment/apply.php index 8d4ecb98e68a0d92c0cadc85ac669bdf83e6570f..53397a8fb0d28d6e264a755ae92ff939f5f075b5 100644 --- a/app/views/course/enrolment/apply.php +++ b/app/views/course/enrolment/apply.php @@ -55,7 +55,7 @@ <div data-dialog-button> <?=Studip\LinkButton::createAccept( _('Zur Veranstaltung'), - URLHelper::getLink('seminar_main.php', ['auswahl' => $course_id]) + URLHelper::getLink('dispatch.php/course/go', ['to' => $course_id]) ) ?> </div> <? endif ?> diff --git a/app/views/course/scm/edit.php b/app/views/course/scm/edit.php index ea054c8332ea727ede1d7495262837a9d3c6bce9..8c5d11a032c7d491ed823b45eb24c57ce10c9867 100644 --- a/app/views/course/scm/edit.php +++ b/app/views/course/scm/edit.php @@ -54,7 +54,7 @@ <footer data-dialog-button> <?= Studip\Button::createAccept(_('Speichern'), 'submit') ?> <? if (!empty($first_entry)): ?> - <?= Studip\LinkButton::createCancel(_('Abbrechen'), URLHelper::getLink('seminar_main.php')) ?> + <?= Studip\LinkButton::createCancel(_('Abbrechen'), URLHelper::getLink('dispatch.php/course/go')) ?> <? else: ?> <?= Studip\LinkButton::createCancel(_('Abbrechen'), $controller->url_for('course/scm/' . $scm->id)) ?> <? endif; ?> diff --git a/app/views/course/studygroup/edit.php b/app/views/course/studygroup/edit.php index 28a8cc5901862c8e5f3c2d1f389487fb4113aad3..e3189f746e5f1f97180d627fee1b7fd67c7cd240 100644 --- a/app/views/course/studygroup/edit.php +++ b/app/views/course/studygroup/edit.php @@ -43,6 +43,6 @@ <footer> <?= Studip\Button::createAccept(_('Übernehmen'), ['title' => _("Änderungen übernehmen")]); ?> - <?= Studip\LinkButton::createCancel(_('Abbrechen'), URLHelper::getURL('seminar_main.php')); ?> + <?= Studip\LinkButton::createCancel(_('Abbrechen'), URLHelper::getURL('dispatch.php/course/go')); ?> </footer> </form> diff --git a/templates/login/_login_faq.php b/app/views/login/_login_faq.php similarity index 100% rename from templates/login/_login_faq.php rename to app/views/login/_login_faq.php diff --git a/templates/login/_login_news.php b/app/views/login/_login_news.php similarity index 100% rename from templates/login/_login_news.php rename to app/views/login/_login_news.php diff --git a/templates/login/_standard_loginform.php b/app/views/login/_standard_loginform.php similarity index 98% rename from templates/login/_standard_loginform.php rename to app/views/login/_standard_loginform.php index e111453fd3d8165a2c1af970e94dbb30fa49ebf3..4221dcdb7d1ada142d7cd7f2b294615c793a15bf 100644 --- a/templates/login/_standard_loginform.php +++ b/app/views/login/_standard_loginform.php @@ -60,10 +60,10 @@ $password_tooltip_text = (string) Config::get()->PASSWORD_TOOLTIP_TEXT; </a> <?= CSRFProtection::tokenTag() ?> - <input type="hidden" name="login_ticket" value="<?= htmlReady(Seminar_Session::get_ticket()) ?>"> + <input type="hidden" name="login_ticket" value="<?= htmlReady(get_ticket()) ?>"> <input type="hidden" name="resolution" value=""> <div class="login-button-wrapper"> <?= Button::create(_('Anmelden'), _('Login'), ['id' => 'submit_login']); ?> </div> -</form> \ No newline at end of file +</form> diff --git a/app/views/login/activate_email.php b/app/views/login/activate_email.php new file mode 100644 index 0000000000000000000000000000000000000000..366990a10087edddbc35f95a0c2d3d2b0dba80d2 --- /dev/null +++ b/app/views/login/activate_email.php @@ -0,0 +1,39 @@ +<?php if (isset($mail_explain)) : ?> + <form action="<?= URLHelper::getLink() ?>" method="post" class="default"> + <fieldset> + <legend> + <?= _('Sie haben Ihre E-Mail-Adresse geändert. + Um diese frei zu schalten müssen Sie den Ihnen an Ihre neue Adresse zugeschickten Aktivierungs Schlüssel im unten stehenden Eingabefeld eintragen.') ?> + </legend> + <?= CSRFProtection::tokenTag() ?> + <label> + <?=_('Aktivierungs Schlüssel')?> + <input type="text" name="key"> + </label> + <input name="uid" type="hidden" value="<?= htmlReady(Request::option('uid')) ?>"> + </fieldset> + + <footer><?= Studip\Button::createAccept() ?></footer> + </form> +<?php endif; ?> +<?php if (isset($reenter_mail)) : ?> + <form action="<?= URLHelper::getLink() ?>" method="post" class="default"> + <fieldset> + <legend> + <?= _('Sollten Sie keine E-Mail erhalten haben, können Sie sich einen neuen Aktivierungsschlüssel zuschicken lassen. Geben Sie dazu Ihre gewünschte E-Mail-Adresse unten an.') ?> + </legend> + <?= CSRFProtection::tokenTag() ?> + <label> + <?= _('Email') ?> + <input type="email" name="email1" required> + </label> + <label> + <?= _('Wiederholung') ?> + <input type="email" name="email2" required> + </label> + <input name="uid" type="hidden" value="<?= htmlReady(Request::option('uid')) ?>"> + </fieldset> + + <footer><?= Studip\Button::createAccept() ?></footer> + </form> +<?php endif; ?> diff --git a/templates/loginform.php b/app/views/login/index.php similarity index 59% rename from templates/loginform.php rename to app/views/login/index.php index ec2289956f5573ddaad74e0fbdea851d95437d69..b1b3dfab5b6f3fd7226d30de7e00f54e2becd3d3 100644 --- a/templates/loginform.php +++ b/app/views/login/index.php @@ -2,7 +2,6 @@ /** * @var array $loginerror * @var string $error_msg - * @var LoginFaq[] $faq_entries */ // Get background images (this should be resolved differently since mobile @@ -26,7 +25,7 @@ if (!match_route('web_migrate.php')) { } $show_login = !(current(StudipAuthAbstract::getInstance()) instanceof StudipAuthSSO) && StudipAuthAbstract::isLoginEnabled(); $show_hidden_login = !$show_login && StudipAuthAbstract::isLoginEnabled(); -$enable_faq = count($faq_entries) > 0; +$enable_faq = Config::get()->LOGIN_FAQ_VISIBILITY && count($faq_entries) > 0; $enable_news = Config::get()->LOGIN_NEWS_VISIBILITY && count($news_entries) > 0; ?> <main id="content" class="loginpage"> @@ -34,13 +33,7 @@ $enable_news = Config::get()->LOGIN_NEWS_VISIBILITY && count($news_entries) > 0; <div id="background-mobile" style="background: url(<?= $bg_mobile ?>) no-repeat top left/cover;"></div> <div id="login-wrapper"> - <?= Studip\VueApp::create('SystemNotificationManager') - ->withProps([ - 'id' => 'system-notifications', - 'class' => 'system-notifications-login', - 'notifications' => PageLayout::getMessages(MessageBox::class), - ]) - ?> + <div id="login-content-wrapper"> <div id="loginbox"> <header> @@ -54,28 +47,28 @@ $enable_news = Config::get()->LOGIN_NEWS_VISIBILITY && count($news_entries) > 0; <? endif ?> <nav class="<?= $show_hidden_login ? 'login-bottom' : '' ?>"> <? foreach (Navigation::getItem('/login') as $key => $nav): ?> - <? if ($nav->isVisible()): ?> - <? if ($key === 'standard_login' && $show_login) - continue; ?> - <? endif ?> - <? $name_and_title = explode(' - ', $nav->getTitle()) ?> - <? if (is_internal_url($url = $nav->getURL())): ?> - <? SkipLinks::addLink($name_and_title[0], URLHelper::getLink($url, ['cancel_login' => 1])) ?> - <a href="<?= URLHelper::getLink($url, ['cancel_login' => 1]) ?>" - <?= arrayToHtmlAttributes($nav->getLinkAttributes()) ?>> - <? else: ?> - <a href="<?= htmlReady($url) ?>" target="_blank" rel="noopener noreferrer"> - <? endif ?> - <p class="title"><?= htmlReady($name_and_title[0]) ?></p> - <p class="description"> - <?= htmlReady(!empty($name_and_title[1]) ? $name_and_title[1] : $nav->getDescription()) ?> - </p> + <? if ($nav->isVisible()): ?> + <? if ($key === 'standard_login' && $show_login) + continue; ?> + <? endif ?> + <? $name_and_title = explode(' - ', $nav->getTitle()) ?> + <? if (is_internal_url($url = $nav->getURL())): ?> + <? SkipLinks::addLink($name_and_title[0], URLHelper::getLink($url, ['cancel_login' => 1])) ?> + <a href="<?= URLHelper::getLink($url, ['cancel_login' => 1]) ?>" + <?= arrayToHtmlAttributes($nav->getLinkAttributes()) ?>> + <? else: ?> + <a href="<?= htmlReady($url) ?>" target="_blank" rel="noopener noreferrer"> + <? endif ?> + <p class="title"><?= htmlReady($name_and_title[0]) ?></p> + <p class="description"> + <?= htmlReady(!empty($name_and_title[1]) ? $name_and_title[1] : $nav->getDescription()) ?> + </p> </a> <? endforeach ?> <? if (Config::get()->ENABLE_SELF_REGISTRATION): ?> <a href="<?= URLHelper::getLink('dispatch.php/registration', ['cancel_login' => 1]) ?>" - title="<?= _('Registrieren, um das System erstmalig zu nutzen') ?>" class="link-registration"> + title="<?= _('Registrieren, um das System erstmalig zu nutzen') ?>" class="link-registration"> <?= _('Kein Zugang? Jetzt registrieren') ?> </a> <? endif; ?> @@ -137,49 +130,27 @@ $enable_news = Config::get()->LOGIN_NEWS_VISIBILITY && count($news_entries) > 0; }); // --> - <? if ($enable_faq) : ?> - STUDIP.domReady(() => { - const loginBox = document.getElementById('loginbox'); - const faqContent = document.getElementById('login-faq-content-wrapper'); - const htmlTag = document.documentElement; - - const adjustFaqHeight = () => { - if (!htmlTag.classList.contains('responsive-display')) { - const loginBoxHeight = loginBox.offsetHeight; - - const maxAllowedHeight = loginBoxHeight - 100; - - faqContent.style.maxHeight = `${Math.max(maxAllowedHeight, 0)}px`; - } - }; - - adjustFaqHeight(); - - window.addEventListener('resize', adjustFaqHeight); - }); - <? endif ?> - <? if ($enable_faq && $enable_news): ?> - const faqButton = document.getElementById('show-faq'); - const newsButton = document.getElementById('hide-faq'); - - faqButton.addEventListener('click', e => { - const faqBox = document.getElementById('login-faq-box'); - const newsBox = document.getElementById('login-news-box'); - newsBox.classList.add('hidden'); - faqBox.classList.remove('hidden'); - faqButton.classList.add('selected'); - newsButton.classList.remove('selected'); - }); + const faqButton = document.getElementById('show-faq'); + const newsButton = document.getElementById('hide-faq'); + + faqButton.addEventListener('click', e => { + const faqBox = document.getElementById('login-faq-box'); + const newsBox = document.getElementById('login-news-box'); + newsBox.classList.add('hidden'); + faqBox.classList.remove('hidden'); + faqButton.classList.add('selected'); + newsButton.classList.remove('selected'); + }); - newsButton.addEventListener('click', e => { - const faqBox = document.getElementById('login-faq-box'); - const newsBox = document.getElementById('login-news-box'); - faqBox.classList.add('hidden'); - newsBox.classList.remove('hidden'); - newsButton.classList.add('selected'); - faqButton.classList.remove('selected'); - }); + newsButton.addEventListener('click', e => { + const faqBox = document.getElementById('login-faq-box'); + const newsBox = document.getElementById('login-news-box'); + faqBox.classList.add('hidden'); + newsBox.classList.remove('hidden'); + newsButton.classList.add('selected'); + faqButton.classList.remove('selected'); + }); <? endif ?> </script> diff --git a/templates/privacy.php b/app/views/login/privacy_info.php similarity index 100% rename from templates/privacy.php rename to app/views/login/privacy_info.php diff --git a/app/views/my_courses/groups.php b/app/views/my_courses/groups.php index 689f51b9d96200853ecbb2dcbc8d6aac6ae3a0c5..ee9b96498562842c22f267e8cab79102d904f809 100644 --- a/app/views/my_courses/groups.php +++ b/app/views/my_courses/groups.php @@ -47,7 +47,7 @@ <? foreach ($group_members as $member): ?> <tr> <td> - <a href="<?= URLHelper::getLink('seminar_main.php?auswahl=' . $member['seminar_id']) ?>"> + <a href="<?= URLHelper::getLink('dispatch.php/course/go?to=' . $member['seminar_id']) ?>"> <?= htmlReady(Config::get()->IMPORTANT_SEMNUMBER ? $my_sem[$member['seminar_id']]['veranstaltungsnummer'] : '') ?> <?= htmlReady($my_sem[$member['seminar_id']]['name']) ?> </a> diff --git a/app/views/my_studygroups/_course.php b/app/views/my_studygroups/_course.php index 87af045625ece3eafdd0d752ef0cea21199959af..37c081e14b2b3a7df1dbf547c06b46f9686a4084 100644 --- a/app/views/my_studygroups/_course.php +++ b/app/views/my_studygroups/_course.php @@ -5,7 +5,7 @@ <?= StudygroupAvatar::getAvatar($group['seminar_id'])->getImageTag(Avatar::SMALL, ['title' => $group['name']]) ?> </td> <td style="text-align: left"> - <a href="<?= URLHelper::getLink('seminar_main.php', ['auswahl' => $group['seminar_id']]) ?>" + <a href="<?= URLHelper::getLink('dispatch.php/course/go', ['to' => $group['seminar_id']]) ?>" <?= $group['last_visitdate'] < $group['chdate'] ? 'style="color: red;"' : '' ?>> <?= htmlReady($group['name']) ?> </a> @@ -28,8 +28,8 @@ <? if (isset($nav) && $nav->isVisible(true)) : ?> <li class="my-courses-navigation-item <? if ($nav->getImage()->signalsAttention()) echo 'my-courses-navigation-important'; ?>"> <a href="<?= - URLHelper::getLink('seminar_main.php', - ['auswahl' => $group['seminar_id'], + URLHelper::getLink('dispatch.php/course/go', + ['to' => $group['seminar_id'], 'redirect_to' => $nav->getURL()]) ?>" <?= $nav->hasBadgeNumber() ? 'class="badge" data-badge-number="' . intval($nav->getBadgeNumber()) . '"' : '' ?>> <?= $nav->getImage()->asImg($nav->getLinkAttributes()) ?> </a> @@ -56,7 +56,7 @@ <? endif ?> <? elseif (!empty($group['binding'])) : ?> - <a href="<?= URLHelper::getLink('', ['auswahl' => $group['seminar_id'], 'cmd' => 'no_kill']) ?>"> + <a href="<?= URLHelper::getLink('', ['to' => $group['seminar_id'], 'cmd' => 'no_kill']) ?>"> <?= Icon::create('door-leave', Icon::ROLE_INACTIVE)->asImg(['title' => _('Die Teilnahme ist bindend. Bitte wenden Sie sich an die Lehrenden.')]) ?> </a> <? diff --git a/app/views/public_courses/index.php b/app/views/public_courses/index.php index 066ef7ae6ee3459b4db7871b041a738702c52b6e..8ecd0abfb4e0c597659754be4c961018f3420783 100644 --- a/app/views/public_courses/index.php +++ b/app/views/public_courses/index.php @@ -49,7 +49,7 @@ <tr> <td class="<?= $values['Schreibzugriff'] ? 'gruppe6' : 'gruppe2' ?>"> </td> <td> - <a href="<?= URLHelper::getLink('seminar_main.php?auswahl=' . $id) ?>"> + <a href="<?= URLHelper::getLink('dispatch.php/course/go?to=' . $id) ?>"> <?= htmlReady($values['name']) ?> </a> </td> @@ -68,7 +68,7 @@ $badge = ' class="badge" data-badge-number="' . intval($navigation->getBadgeNumber()) . '"'; } ?> - <a href="<?= URLHelper::getLink('seminar_main.php?auswahl='. $id . '&redirect_to=' . str_replace('?', '&', $navigation->getURL())) ?>"<?= $badge ?>> + <a href="<?= URLHelper::getLink('dispatch.php/course/go?to='. $id . '&redirect_to=' . str_replace('?', '&', $navigation->getURL())) ?>"<?= $badge ?>> <?= $navigation->getImage()->asImg($navigation->getLinkAttributes()) ?> </a> <? else: ?> diff --git a/app/views/questionnaire/context.php b/app/views/questionnaire/context.php index 96190d963c145536a6b6bc2c596272a4e4f65529..36953a666cf935f4626696c76b5d5815a2814be7 100644 --- a/app/views/questionnaire/context.php +++ b/app/views/questionnaire/context.php @@ -38,7 +38,7 @@ <label> <input type="checkbox" name="remove_sem[]" value="<?= htmlReady($assignment['range_id']) ?>" style="display: none;"> <span> - <a href="<?= URLHelper::getLink("seminar_main.php", ['auswahl' => $course->getId()]) ?>"> + <a href="<?= URLHelper::getLink("dispatch.php/course/go", ['to' => $course->getId()]) ?>"> <?= htmlReady((Config::get()->IMPORTANT_SEMNUMBER ? $course->veranstaltungsnummer." " : "").$course->name. ' ('.$course->semester_text.')') ?> </a> <?= Icon::create('trash')->asimg(['class' => 'text-bottom', 'title' => _('Zuweisung zur Veranstaltung aufheben.')]) ?> @@ -60,7 +60,7 @@ <input type="checkbox" name="remove_statusgruppe[]" value="<?= htmlReady($assignment['range_id']) ?>" style="display: none;"> <? $statusgruppe = Statusgruppen::find($assignment['range_id']) ?> <span> - <a href="<?= URLHelper::getLink("seminar_main.php", ['auswahl' => $statusgruppe->getId()]) ?>"> + <a href="<?= URLHelper::getLink("dispatch.php/course/go", ['to' => $statusgruppe->getId()]) ?>"> <?= htmlReady($statusgruppe->course['name'].": ".$statusgruppe->name) ?> </a> <?= Icon::create('trash')->asimg(['class' => 'text-bottom', 'title' => _('Zuweisung zur Veranstaltung aufheben.')]) ?> diff --git a/templates/email-validation.php b/app/views/registration/email_validation.php similarity index 100% rename from templates/email-validation.php rename to app/views/registration/email_validation.php diff --git a/app/views/settings/notification.php b/app/views/settings/notification.php index 54288197133c6d2c463a80f6ef4d1ef64ccaf8c3..1ee98883aa355833822b4c2c1c6e5a36a7baa354 100644 --- a/app/views/settings/notification.php +++ b/app/views/settings/notification.php @@ -69,7 +69,7 @@ <tr> <td class="gruppe<?= $seminars[$member['seminar_id']]['gruppe'] ?>"> </td> <td> - <a href="<?= URLHelper::getLink('seminar_main.php', ['auswahl' => $member['seminar_id']]) ?>"> + <a href="<?= URLHelper::getLink('dispatch.php/course/go', ['to' => $member['seminar_id']]) ?>"> <?= Config::get()->IMPORTANT_SEMNUMBER ? htmlReady($seminars[$member['seminar_id']]['sem_nr']) : '' ?> <?= htmlReady(my_substr($seminars[$member['seminar_id']]['name'], 0, 70)) ?> </a> diff --git a/app/views/studygroup/browse.php b/app/views/studygroup/browse.php index 6d0ebc4a3de94d0c891489e2938041f1ad046951..6362d6af7ece0c8ec04f31467ebbe22c4e6654b4 100644 --- a/app/views/studygroup/browse.php +++ b/app/views/studygroup/browse.php @@ -60,7 +60,7 @@ $headers = [ </td> <td class="studygroup-title"> <? if ($is_member): ?> - <a href="<?= URLHelper::getlink("seminar_main.php?auswahl=" . $group['Seminar_id']) ?>"> + <a href="<?= URLHelper::getlink("dispatch.php/course/go?to=" . $group['Seminar_id']) ?>"> <? else: ?> <a href="<?= URLHelper::getlink("dispatch.php/course/studygroup/details/" . $group['Seminar_id'], ['cid' => null]) ?>"> <? endif; ?> diff --git a/cli/studip_cli_env.inc.php b/cli/studip_cli_env.inc.php index a5ef8f46dd6a10e9978f82e362226446a8eb3ef1..b939e5d8ca2115ab29cd02603bfcf5348c6753d3 100644 --- a/cli/studip_cli_env.inc.php +++ b/cli/studip_cli_env.inc.php @@ -63,12 +63,6 @@ $CACHING_ENABLE = false; // set base url for URLHelper class URLHelper::setBaseUrl($ABSOLUTE_URI_STUDIP); -//cli scripts run always as faked (Stud.IP) root -$auth = new Seminar_Auth(); -$auth->auth = ['uid' => 'cli', - 'uname' => 'cli', - 'perm' => 'root']; - $faked_root = new User(); $faked_root->user_id = 'cli'; $faked_root->username = 'cli'; diff --git a/composer.json b/composer.json index 9c6118b7ceba77cba81d503c8c49e7f2905894df..7aef546f92209ea029b67eb42571a7aa76f08921 100644 --- a/composer.json +++ b/composer.json @@ -21,6 +21,9 @@ "lib/exceptions/", "lib/exceptions/course/" ], + "Studip\\Middleware\\": "lib/middleware/", + "Studip\\Session\\": "lib/session/", + "Studip\\Authentication\\": "lib/authentication/", "Trails\\": "lib/trails/", "": [ "lib/classes/", @@ -50,7 +53,6 @@ "lib/models/resources/", "lib/modules/", "lib/navigation/", - "lib/phplib/", "lib/plugins/core/", "lib/plugins/db/", "lib/plugins/engine/", @@ -58,7 +60,6 @@ ] }, "classmap": [ - "lib/phplib/email_validation.php", "lib/messaging.inc.php", "lib/plugins/core/StudIPPlugin.php", "app/controllers/module/mvv_controller.php", diff --git a/config/config_defaults.inc.php b/config/config_defaults.inc.php index 2f83fefc583fddad9474bc360b8cea3aed86a4dc..66b6900826dd4252731591791384bcbfeadb867a 100644 --- a/config/config_defaults.inc.php +++ b/config/config_defaults.inc.php @@ -70,6 +70,10 @@ $CACHING_ENABLE = $_ENV['STUDIP_CACHING_ENABLE'] ?? true; $CACHING_FILECACHE_PATH = $TMP_PATH . '/studip_cache'; $CACHE_IS_SESSION_STORAGE = $_ENV['STUDIP_CACHE_IS_SESSION_STORAGE'] ?? false; //store session data in cache +$SESSION_OPTIONS = []; +$SESSION_OPTIONS['lifetime'] = 7200; // session lifetime in seconds + + /*Stud.IP modules ---------------------------------------------------------------- enable or disable the Stud.IP internal modules, set and basic settings*/ diff --git a/lib/admin_search.inc.php b/lib/admin_search.inc.php index a6b2260d365b607128fdce96a1d26d1c9ba66d9b..93a45385e156f05af1e091713a63ec33f8b1f3d6 100644 --- a/lib/admin_search.inc.php +++ b/lib/admin_search.inc.php @@ -18,6 +18,6 @@ if (!Institute::findCurrent()) { $template->institutes = Institute::getMyInstitutes($GLOBALS['user']->id); echo $template->render(); - page_close(); + sess()->save(); die; } diff --git a/lib/authentication/Manager.php b/lib/authentication/Manager.php new file mode 100644 index 0000000000000000000000000000000000000000..64419cac723d36a5fe61955a29a181178d29d617 --- /dev/null +++ b/lib/authentication/Manager.php @@ -0,0 +1,152 @@ +<?php +/** + * Authentication Manager + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * @author André Noack <noack@data-quest.de> + */ +namespace Studip\Authentication; + +class Manager +{ + private $auth = []; + public function __construct(private $nobody = false) + { + } + + /** + * @return false|mixed + */ + public function getNobody(): mixed + { + return $this->nobody; + } + + public function setNobody($allow_nobody = false): void + { + $this->nobody = $allow_nobody; + } + + + public function start() + { + $this->auth =& $_SESSION['auth']; + + if (!$this->isAuthenticated()) { + $user = null; + if (($provider = \Request::option('sso'))) { + \Metrics::increment('core.sso_login.attempted'); + // then do login + $authplugin = \StudipAuthAbstract::GetInstance($provider); + if ($authplugin) { + $authplugin->authenticateUser('', ''); + if ($authplugin->getUser()) { + $user = $authplugin->getStudipUser($authplugin->getUser()); + $exp_d = \UserConfig::get($user->id)->EXPIRATION_DATE; + if ($exp_d > 0 && $exp_d < time()) { + throw new \AccessDeniedException( + _('Dieses Benutzerkonto ist abgelaufen. Wenden Sie sich bitte an die Administration.') + ); + } + if ($user->locked == 1) { + throw new \AccessDeniedException( + _('Dieser Benutzer ist gesperrt! Wenden Sie sich bitte an die Administration.') + ); + } + \Metrics::increment('core.sso_login.succeeded'); + sess()->regenerateId(['auth', '_language', 'phpCAS', 'contrast']); + } + } + } + if (!$user) { + if ($this->nobody && !\Request::get('again')) { + $this->setAuthenticatedUser(\User::build(['user_id' => 'nobody', 'perms' => null])); + } + if (!match_route('dispatch.php/login')) { + return false; + } + } + } else { + if ($this->auth['uid'] !== 'nobody' && \Request::get('again') && !match_route('dispatch.php/login')) { + return false; + } + $this->setAuthenticatedUser($this->auth['uid'] !== 'nobody' ? \User::find($this->auth['uid']) : \User::build(['user_id' => 'nobody', 'perms' => null])); + } + return true; + } + + public function isAuthenticated() + { + if (!is_array($this->auth)) { + $this->auth = []; + } + if (isset($this->auth['uid']) && $this->auth['uid'] === 'nobody' && (!$this->nobody || \Request::option('again'))) { + $this->auth['uid'] = null; + } + $cfg = \Config::GetInstance(); + //check if the user got kicked meanwhile, or if user is locked out + if (!empty($this->auth['uid']) && !in_array($this->auth['uid'], ['nobody'])) { + $user = null; + if (isset($GLOBALS['user']) && $GLOBALS['user']->id == $this->auth['uid']) { + $user = $GLOBALS['user']; + } else { + $user = \User::find($this->auth['uid']); + } + $exp_d = $user->username ? \UserConfig::get($user->id)->EXPIRATION_DATE : 0; + if (!$user->username || $user->locked || ($exp_d > 0 && $exp_d < time())) { + $this->auth = []; + } + } elseif ($cfg->getValue('MAINTENANCE_MODE_ENABLE') && \Request::username('loginname')) { + $user = \User::findByUsername(\Request::username('loginname')); + } + if ($cfg->getValue('MAINTENANCE_MODE_ENABLE') && $user->perms != 'root') { + $this->auth = []; + throw new \AccessDeniedException(_("Das System befindet sich im Wartungsmodus. Zur Zeit ist kein Zugriff möglich.")); + } + return @$this->auth['uid'] ? : false; + } + + public function setAuthenticatedUser(\User $user): void + { + $this->auth['uid'] = $user->id; + $GLOBALS['user'] = new \Seminar_User($user); + $GLOBALS['perm'] = new \Seminar_Perm(); + } + + public function sendValidationMail(\User $user = null): void + { + if (is_null($user)) { + $user = \User::findCurrent(); + } + + // template-variables for the include partial + $Zeit = date('H:i:s, d.m.Y', $user->mkdate); + $username = $user->username; + $Vorname = $user->vorname; + $Nachname = $user->nachname; + $Email = $user->email; + + // (re-)send the confirmation mail + $to = $user->email; + $token = \Token::create(7 * 24 * 60 * 60, $user->id); // Link is valid for 1 week + $url = $GLOBALS['ABSOLUTE_URI_STUDIP'] . 'dispatch.php/registration/email_validation?secret=' . $token; + $mail = new \StudipMail(); + $abuse = $mail->getReplyToEmail(); + + $lang_path = getUserLanguagePath($user->id); + + // include language-specific subject and mailbody + // TODO: This should be refactored so that the included file returns an array + include "locale/{$lang_path}/LC_MAILS/register_mail.inc.php"; // Defines $subject and $mailbody + + // send the mail + $mail->setSubject($subject ?? '') + ->addRecipient($to) + ->setBodyText($mailbody ?? '') + ->send(); + } +} diff --git a/lib/bootstrap-definitions.php b/lib/bootstrap-definitions.php index 7d4f93bd613c5202b223fdc1992fa95e320cc428..06380a830d5e3559aefdfbcf757a029d7ad60679 100644 --- a/lib/bootstrap-definitions.php +++ b/lib/bootstrap-definitions.php @@ -71,6 +71,19 @@ return [ }), PluginManager::class => DI\factory([PluginManager::class, 'getInstance']), + Studip\Session\Manager::class => DI\factory(function () { + if (Config::get()->CACHING_ENABLE && $GLOBALS['CACHE_IS_SESSION_STORAGE']) { + $session_handler = new Studip\Session\CacheSessionHandler($GLOBALS['SESSION_OPTIONS']['lifetime'] ?? null); + } else { + $session_handler = new Studip\Session\DbSessionHandler(); + } + $GLOBALS['SESSION_OPTIONS']['path'] = $GLOBALS['CANONICAL_RELATIVE_PATH_STUDIP']; + $GLOBALS['SESSION_OPTIONS']['secure'] = Request::protocol() == 'https'; + return new Studip\Session\Manager($session_handler, $GLOBALS['SESSION_OPTIONS']); + + }), + Studip\Authentication\Manager::class => DI\create(), + // PSR-17 HTTP Factories \Psr\Http\Message\RequestFactoryInterface::class => DI\get(Psr17Factory::class), \Psr\Http\Message\ResponseFactoryInterface::class => DI\get(Psr17Factory::class), diff --git a/lib/bootstrap.php b/lib/bootstrap.php index 2f8448ddf7a9382839141db652bf7a460ec5d78a..2d4e2e83da8b0a1c389d28a472511784d75eb029 100644 --- a/lib/bootstrap.php +++ b/lib/bootstrap.php @@ -115,7 +115,6 @@ if ($GLOBALS['ASSETS_URL'][0] === '/') { require $GLOBALS['STUDIP_BASE_PATH'] . '/config/config.inc.php'; require 'lib/helpers.php'; -require 'lib/phplib/page_open.php'; require_once 'lib/functions.php'; require_once 'lib/language.inc.php'; require_once 'lib/visual.inc.php'; @@ -204,21 +203,6 @@ register_shutdown_function(function ($timer) { //include 'tools/debug/StudipDebugPDO.class.php'; -/** - * @deprecated - */ -class DB_Seminar extends DB_Sql -{ - public function __construct($query = false) - { - $this->Host = $GLOBALS['DB_STUDIP_HOST']; - $this->Database = $GLOBALS['DB_STUDIP_DATABASE']; - $this->User = $GLOBALS['DB_STUDIP_USER']; - $this->Password = $GLOBALS['DB_STUDIP_PASSWORD']; - parent::__construct($query); - } -} - if (Config::get()->CALENDAR_ENABLE) { require_once 'lib/calendar_functions.inc.php'; } diff --git a/lib/classes/CSRFProtection.php b/lib/classes/CSRFProtection.php index 05532d462e69f61a1521fc0cf740a353f2ef704c..036aa932884ccf7dfb2accaccf5f2f2fb6e552dc 100644 --- a/lib/classes/CSRFProtection.php +++ b/lib/classes/CSRFProtection.php @@ -66,7 +66,7 @@ class CSRFProtection if (!isset(self::$storage)) { // w/o a session, throw an exception since we cannot use it if (session_id() === '') { - throw new SessionRequiredException(); + throw new SessionRequiredException(); } self::$storage =& $_SESSION; @@ -180,4 +180,38 @@ class CSRFProtection arrayToHtmlAttributes($attributes) ); } + + /** + * returns a random string token for XSRF prevention + * the string is stored in the session + * + * @static + * @return string + */ + public static function sessionticket() + { + $storage = &self::getStorage(); + + if (empty($storage['studipticket'])) { + $storage['studipticket'] = md5(uniqid('studipticket', 1)); + } + return $storage['studipticket']; + } + + /** + * checks the given string token against the one stored + * in the session + * + * @static + * @param string $studipticket + * @return bool + */ + public static function verifySessionticket($studipticket) + { + $storage = &self::getStorage(); + + $check = (isset($storage['studipticket']) && $storage['studipticket'] === $studipticket); + $storage['studipticket'] = null; + return $check; + } } diff --git a/lib/classes/Context.php b/lib/classes/Context.php index 389a8cc276170514b74dc191798b71ac50f3d9e3..e7b2e0146abb5440895f27525a403e6173ac7c48 100644 --- a/lib/classes/Context.php +++ b/lib/classes/Context.php @@ -246,7 +246,7 @@ class Context ); if (!$count) { header('Location: ' . URLHelper::getURL('dispatch.php/course/members/additional_input')); - page_close(); + sess()->save(); die; } } diff --git a/lib/classes/JsonApi/Middlewares/Auth/SessionStrategy.php b/lib/classes/JsonApi/Middlewares/Auth/SessionStrategy.php index 26c0bc22fe621d33a3c596f6cfa43be284a04359..a0f14f8645babe578ba6309a2aec2a94707fb958 100644 --- a/lib/classes/JsonApi/Middlewares/Auth/SessionStrategy.php +++ b/lib/classes/JsonApi/Middlewares/Auth/SessionStrategy.php @@ -24,7 +24,7 @@ class SessionStrategy implements Strategy } $isAuthenticated = - isset($GLOBALS['auth']) && $GLOBALS['auth']->is_authenticated() && 'nobody' !== $GLOBALS['user']->id; + isset($GLOBALS['user']) && 'nobody' !== $GLOBALS['user']->id; if ($isAuthenticated) { $this->user = $GLOBALS['user']->getAuthenticatedUser(); diff --git a/lib/classes/JsonApi/Middlewares/Authentication.php b/lib/classes/JsonApi/Middlewares/Authentication.php index 19da101535eedfcc33463bfc204782333c0306d0..ed534ad47baa9a8e561eb031aed89c08dc0d8399 100644 --- a/lib/classes/JsonApi/Middlewares/Authentication.php +++ b/lib/classes/JsonApi/Middlewares/Authentication.php @@ -80,17 +80,8 @@ class Authentication || 'nobody' === $GLOBALS['user']->id ) { $GLOBALS['user'] = new \Seminar_User($user); - $GLOBALS['auth'] = new \Seminar_Auth(); - $GLOBALS['auth']->auth = [ - 'uid' => $user->id, - 'uname' => $user->username, - 'perm' => $user->perms, - ]; - $GLOBALS['perm'] = new \Seminar_Perm(); $GLOBALS['MAIL_VALIDATE_BOX'] = false; - if (isset($GLOBALS['sess'])) { - $GLOBALS['sess']->delete(); - } + sess()->destroy(); setTempLanguage($user->id); } diff --git a/lib/classes/Markup.php b/lib/classes/Markup.php index 404bcb9418bd102f19a625b2e17f008864e66152..08a25ba8975472107c282bc65ee40fc6995858a2 100644 --- a/lib/classes/Markup.php +++ b/lib/classes/Markup.php @@ -584,8 +584,9 @@ function getMediaUrl($url) { // handle external media links $external_media = \Config::get()->LOAD_EXTERNAL_MEDIA; + if ($external_media === 'proxy' && - \Seminar_Session::is_current_session_authenticated() + sess()->isCurrentSessionAuthenticated() ) { // media proxy must be accessed by an internal link return encodeMediaProxyUrl($url); diff --git a/lib/classes/ModulesNotification.php b/lib/classes/ModulesNotification.php index f16ea1201cb09be9fcdaf0128a59a1b5dcd84007..96aa660e82a6eaaf7c2471604877308edd751e86 100644 --- a/lib/classes/ModulesNotification.php +++ b/lib/classes/ModulesNotification.php @@ -168,7 +168,7 @@ class ModulesNotification $base_url = URLHelper::setBaseURL(''); URLHelper::setBaseURl($base_url); if ($nav instanceof Navigation && $nav->isVisible(true)) { - $url = 'seminar_main.php?again=yes&auswahl=' . $seminar_id . '&redirect_to=' . strtr($nav->getURL(), '?', '&'); + $url = 'dispatch.php/course/go?again=yes&to=' . $seminar_id . '&redirect_to=' . strtr($nav->getURL(), '?', '&'); $icon = $nav->getImage(); $text = $nav->getTitle(); if (!$text) { diff --git a/lib/classes/ObjectdisplayHelper.php b/lib/classes/ObjectdisplayHelper.php index 145647ef36d7ca5060ab1cbeb0d8ec6381480f2f..b11f90d6eb155d9e16f8d7fd4909e7b7ac93a2d6 100644 --- a/lib/classes/ObjectdisplayHelper.php +++ b/lib/classes/ObjectdisplayHelper.php @@ -63,7 +63,7 @@ class ObjectdisplayHelper { ], 'Course' => [ 'link' => function($obj) { - return URLHelper::getLink('seminar_main.php', ['auswahl' => $obj->id]); + return URLHelper::getLink('dispatch.php/course/go', ['to' => $obj->id]); }, 'name' => function($obj) { return htmlReady($obj->name); diff --git a/lib/classes/PluginController.php b/lib/classes/PluginController.php index 867d6697e12c4067b630ef416f912a58893e9627..67fd7f4c121d483b9c60cc15c03ad25b68b06af5 100644 --- a/lib/classes/PluginController.php +++ b/lib/classes/PluginController.php @@ -15,6 +15,7 @@ class PluginController extends StudipController { public function __construct(PluginDispatcher $dispatcher) { + $this->with_session = false; //session for plugin is always initialized in plugins.php parent::__construct($dispatcher); $this->plugin = $dispatcher->current_plugin; diff --git a/lib/phplib/Seminar_Perm.php b/lib/classes/Seminar_Perm.php similarity index 100% rename from lib/phplib/Seminar_Perm.php rename to lib/classes/Seminar_Perm.php diff --git a/lib/phplib/Seminar_User.php b/lib/classes/Seminar_User.php similarity index 100% rename from lib/phplib/Seminar_User.php rename to lib/classes/Seminar_User.php diff --git a/lib/classes/StudipController.php b/lib/classes/StudipController.php index d103621b3e5a2bde805ed8c164a1a51944caeecf..33b7e38de3328e3041899e08cfd793cca9bf42b0 100644 --- a/lib/classes/StudipController.php +++ b/lib/classes/StudipController.php @@ -25,6 +25,21 @@ abstract class StudipController extends Trails\Controller protected $allow_nobody = true; //should 'nobody' allowed for this controller or redirected to login? protected $_autobind = false; + public function __construct(\Trails\Dispatcher $dispatcher) + { + parent::__construct($dispatcher); + if ($this->with_session) { + $slimapp = app()->get(Slim\App::class); + if ($slimapp) { + $slimapp->add(Studip\Middleware\SeminarOpenMiddleware::class); + $slimapp->add(Studip\Middleware\AuthenticationMiddleware::class); + auth()->setNobody($this->allow_nobody); + $slimapp->add(Studip\Middleware\SessionMiddleware::class); + } + } + } + + /** * @return false|void */ @@ -37,22 +52,8 @@ abstract class StudipController extends Trails\Controller parent::before_filter($action, $args); if ($this->with_session) { - # open session - page_open([ - 'sess' => 'Seminar_Session', - 'auth' => $this->allow_nobody ? 'Seminar_Default_Auth' : 'Seminar_Auth', - 'perm' => 'Seminar_Perm', - 'user' => 'Seminar_User' - ]); - - // show login-screen, if authentication is "nobody" - $GLOBALS['auth']->login_if((Request::get('again') || !$this->allow_nobody) && $GLOBALS['user']->id == 'nobody'); - // Setup flash instance $this->flash = Trails\Flash::instance(); - - // set up user session - include 'lib/seminar_open.php'; } // Set generic attribute that indicates whether the request was sent @@ -85,13 +86,11 @@ abstract class StudipController extends Trails\Controller } /** - * Extended method to inject extended response object. + * method to inject extended response object. */ - public function erase_response() + public function injectResponse(Psr\Http\Message\ResponseInterface $response) { - parent::erase_response(); - - $this->response = new StudipResponse(); + $this->response = new StudipResponse($response); } /** @@ -140,9 +139,6 @@ abstract class StudipController extends Trails\Controller $this->response->add_header('X-WikiLink', format_help_url(PageLayout::getHelpKeyword())); } - if ($this->with_session) { - page_close(); - } } /** @@ -644,7 +640,7 @@ abstract class StudipController extends Trails\Controller // If the relayed action should perform a redirect, do so if (isset($response->headers['Location'])) { header("Location: {$response->headers['Location']}"); - page_close(); + sess()->save(); die; } diff --git a/lib/classes/StudipCoreFormat.php b/lib/classes/StudipCoreFormat.php index bc3ded3096b9f767c1bb9530f13430acee6c7f93..fa3817b8e7f064eceb848c96a96b805c317d2f96 100644 --- a/lib/classes/StudipCoreFormat.php +++ b/lib/classes/StudipCoreFormat.php @@ -595,7 +595,7 @@ class StudipCoreFormat extends TextFormat } //Mediaproxy? - if (!$intern && $LOAD_EXTERNAL_MEDIA === "proxy" && Seminar_Session::is_current_session_authenticated()) { + if (!$intern && $LOAD_EXTERNAL_MEDIA === 'proxy' && sess()->isCurrentSessionAuthenticated()) { $media_url = $GLOBALS['ABSOLUTE_URI_STUDIP'] . 'dispatch.php/media_proxy?url=' . urlencode(decodeHTML(idna_link($url))); } else { $media_url = idna_link($url); diff --git a/lib/classes/StudipDispatcher.php b/lib/classes/StudipDispatcher.php index a41635a9034e30ef9a00c07b4e07712046d525ce..ea66c1c718e1d18ef26d77dc25879d319194bb3c 100644 --- a/lib/classes/StudipDispatcher.php +++ b/lib/classes/StudipDispatcher.php @@ -1,6 +1,8 @@ <?php use Psr\Container\ContainerInterface; +use Slim\Routing\RouteContext; +use Trails\Exception; /** * StudipDispatcher.php - create the default Trails dispatcher @@ -87,4 +89,16 @@ class StudipDispatcher extends Trails\Dispatcher return $this->container->make($class, ['dispatcher' => $this]); } + + public function getRouteCallable($uri) + { + $uri = $this->clean_request_uri((string) $uri); + [$controller_path, $unconsumed] = '' === $uri ? $this->default_route() : $this->parse($uri); + $controller = $this->load_controller($controller_path); + return function ($request, $response, array $args) use ($controller, $unconsumed) { + $controller->injectResponse($response); + $response = $controller->perform($unconsumed); + return $response->getPsrResponse(); + } ; + } } diff --git a/lib/classes/StudipResponse.php b/lib/classes/StudipResponse.php index a9f1a4c36997643edafe7ba358079fcc4946efb7..3031d7c72f7ca3709538169cb30b46fe883b92c4 100644 --- a/lib/classes/StudipResponse.php +++ b/lib/classes/StudipResponse.php @@ -1,55 +1,103 @@ <?php class StudipResponse extends Trails\Response { + + /** + * Constructor. + * @return void + */ + public function __construct(protected Psr\Http\Message\ResponseInterface $psr_response) + { + parent::__construct(); + } + + /** + * @param $name + * @param $value + * @return mixed + */ + public function __call($name, $value) + { + return $this->psr_response->$name($value); + } + + /** + * @return \Psr\Http\Message\ResponseInterface + */ + public function getPsrResponse(): \Psr\Http\Message\ResponseInterface + { + return $this->psr_response; + } + /** - * Outputs this response to the client using "echo" and "header". * - * This extension allows the body to be a callable and handles generators - * by outputting the chunks yielded by the generator. + * @return void */ public function output() { - if (isset($this->status)) { - $this->send_header( - "{$_SERVER['SERVER_PROTOCOL']} {$this->status} {$this->reason}", - true, - $this->status - ); - } + $status = sprintf('HTTP/%s %s %s' + , $this->psr_response->getProtocolVersion() + , $this->psr_response->getStatusCode() + , $this->psr_response->getReasonPhrase() + ); + header($status); - // Send headers - foreach ($this->headers as $k => $v) { - $this->send_header("{$k}: {$v}"); + foreach ($this->psr_response->getHeaders() as $name => $values) { + $responseHeader = sprintf('%s: %s' + , $name + , $this->psr_response->getHeaderLine($name) + ); + header($responseHeader, false); } + echo $this->psr_response->getBody(); + } - // Determine output - if (is_callable($this->body)) { - $output = call_user_func($this->body); + /** + * Sets the body of the response. + * + * @param string|Psr\Http\Message\StreamInterface $body the body + * + * @return static this response object. Useful for cascading method calls. + */ + public function set_body($body) + { + if ($body instanceof Psr\Http\Message\StreamInterface) { + $this->psr_response = $this->psr_response->withBody($body); } else { - $output = $this->body; + $this->psr_response->getBody()->write($body); } + return $this; + } - if ($output instanceof Generator) { - // Clear output buffer - while (ob_get_level()) { - ob_end_clean(); - } - - // Ensure generator will run to the end - $abort = ignore_user_abort(true); - - // Output chunks yielded by generator - foreach ($output as $chunk) { - if (!connection_aborted()) { - echo $chunk; - flush(); - } - } - - // Reset user abort to previous state - ignore_user_abort($abort); - } else { - echo $output; - } + + /** + * Sets the status code and an optional custom reason. If none is given, the + * standard reason phrase as of RFC 2616 is used. + * + * @param integer the status code + * @param string the custom reason, defaulting to the one given in RFC 2616 + * + * @return static this response object. Useful for cascading method calls. + */ + public function set_status($status, $reason = null) + { + $this->psr_response = $this->psr_response->withStatus($status, $reason ?? self::get_reason($status)); + return $this; + } + + + + /** + * Adds an additional header to the response. + * + * @param string the left hand key part + * @param string the right hand value part + * + * @return static this response object. Useful for cascading method calls. + */ + function add_header($key, $value) + { + $this->psr_response = $this->psr_response->withHeader($key, $value); + return $this; } } diff --git a/lib/classes/TwoFactorAuth.php b/lib/classes/TwoFactorAuth.php index b67f4befa2684458b70c8379669716d75fc4dc63..73e9f5ec015ff3aa63ca366ec624497932d2060f 100644 --- a/lib/classes/TwoFactorAuth.php +++ b/lib/classes/TwoFactorAuth.php @@ -240,7 +240,7 @@ final class TwoFactorAuth ], 'layouts/base.php' ); - page_close(); + sess()->save(); die; } diff --git a/lib/classes/UserManagement.php b/lib/classes/UserManagement.php index f4c47108e55ed3bf259494a54bb37a3423917950..961a872b00b3058c222276f3161a0b917cfc86df 100644 --- a/lib/classes/UserManagement.php +++ b/lib/classes/UserManagement.php @@ -1280,7 +1280,7 @@ class UserManagement WHERE a.user_id = ? AND a.inst_perms = 'admin'"; $statement = DBManager::get()->prepare($query); $statement->execute([ - $GLOBALS['auth']->auth['uid'], + $GLOBALS['user']->id, $this->user_data['auth_user_md5.user_id'], ]); $ok = $statement->fetchColumn(); diff --git a/lib/classes/auth_plugins/StudipAuthOAuth2.php b/lib/classes/auth_plugins/StudipAuthOAuth2.php index 2ed2a0f58bad48db8f315d9fad0d2fa574401c61..a67006777c2ee31c656f7a8048ba85c50072c302 100644 --- a/lib/classes/auth_plugins/StudipAuthOAuth2.php +++ b/lib/classes/auth_plugins/StudipAuthOAuth2.php @@ -75,7 +75,7 @@ final class StudipAuthOAuth2 extends StudipAuthSSO 'redirect' => Request::url(), ]; - page_close(); + sess()->save(); header('Location: ' . $authorizationUrl); die; } elseif ( diff --git a/lib/phplib/email_validation.php b/lib/classes/email_validation_class.php similarity index 100% rename from lib/phplib/email_validation.php rename to lib/classes/email_validation_class.php diff --git a/lib/classes/forms/Form.php b/lib/classes/forms/Form.php index 576ea43702a5214ca7d1014ca3f5451c5dc9dad0..e4d49379f5d11fbb05c6a0c4c3a50411938adcfa 100644 --- a/lib/classes/forms/Form.php +++ b/lib/classes/forms/Form.php @@ -300,7 +300,7 @@ class Form extends Part if ($this->success_message) { \PageLayout::postSuccess($this->success_message); } - page_close(); + sess()->save(); //This indicates that the form has been stored successfully. echo "STUDIPFORM_STORE_SUCCESS"; die(); @@ -330,7 +330,7 @@ class Form extends Part } header('Content-Type: application/json'); echo json_encode($output); - page_close(); + sess()->save(); die(); } return $this; diff --git a/lib/cronjobs/session_gc.php b/lib/cronjobs/session_gc.php index 54763ee0c4fe036f6b50d74675ec0a2e0dd3ecae..25d5f6c6f88b923030f5e3b417f2844ebd3a2155 100644 --- a/lib/cronjobs/session_gc.php +++ b/lib/cronjobs/session_gc.php @@ -22,8 +22,6 @@ class SessionGcJob extends CronJob public function execute($last_result, $parameters = []) { - $sess = new Seminar_Session(); - $sess->set_container(); - return $sess->gc(); + return sess()->doGarbageCollect(); } } diff --git a/lib/functions.php b/lib/functions.php index 39fb96655df9f5a4e60e9f9e5b538198744b07e1..29264fbf0ba705fdb34536b098a13ac1165fd1ac 100644 --- a/lib/functions.php +++ b/lib/functions.php @@ -345,10 +345,10 @@ function get_fullname($user_id = "", $format = "full" , $htmlready = false) function get_fullname_from_uname($uname = "", $format = "full", $htmlready = false) { static $cache; - global $auth, $_fullname_sql; + global $user, $_fullname_sql; if (!$uname) { - $uname = $auth->auth['uname']; + $uname = $user->username; } $hash = md5($uname . $format); @@ -379,10 +379,10 @@ function get_fullname_from_uname($uname = "", $format = "full", $htmlready = fal function get_username($user_id = "") { static $cache = []; - global $auth; + global $user; - if (!$user_id || $user_id === $auth->auth['uid']) { - return $auth->auth['uname'] ?? ''; + if (!$user_id || $user_id === $user->id) { + return $user->username ?? ''; } if (!isset($cache[$user_id])) { @@ -400,7 +400,7 @@ function get_username($user_id = "") * * uses global $online array if user is online * - * @global object $auth + * @global object user * @staticvar array $cache * * @param string $username if omitted, current user_id will be returned @@ -410,10 +410,10 @@ function get_username($user_id = "") function get_userid($username = "") { static $cache = []; - global $auth; + global $user; - if (!$username || $username == $auth->auth['uname']) { - return $auth->auth['uid']; + if (!$username || $username == $user->username) { + return $user->id; } // Read id from database if no cached version is available @@ -513,7 +513,6 @@ function StringToFloat($str) * passed archived seminar * * @global array $perm - * @global object $auth * @staticvar array $archiv_perms * * @param string $seminar_id the seminar in the archive @@ -641,7 +640,7 @@ function get_users_online_count($active_time = 10) */ function get_ticket() { - return Seminar_Session::get_ticket(); + return CSRFProtection::sessionticket(); } /** @@ -653,7 +652,7 @@ function get_ticket() */ function check_ticket($studipticket) { - return Seminar_Session::check_ticket($studipticket); + return CSRFProtection::verifySessionticket($studipticket); } /** @@ -1124,7 +1123,7 @@ function studip_default_exception_handler($exception) { $status = 403; $template = 'check_object_exception'; } elseif ($exception instanceof LoginException) { - $GLOBALS['auth']->login_if(true); + } else { if ($exception instanceOf Trails\Exception) { $status = $exception->getCode(); diff --git a/lib/helpers.php b/lib/helpers.php index bffed4a9acb47aff2c794f275c1dc870b506fef2..9bfedb1b17366628f397807beb6f14683a66e4bb 100644 --- a/lib/helpers.php +++ b/lib/helpers.php @@ -31,3 +31,19 @@ function app($entryId = null, $parameters = []) return $container->make($entryId, $parameters); } + +/** + * @return \Studip\Session\Manager + */ +function sess() : Studip\Session\Manager +{ + return app()->get(Studip\Session\Manager::class); +} + +/** + * @return \Studip\Authentication\Manager + */ +function auth() : Studip\Authentication\Manager +{ + return app()->get(Studip\Authentication\Manager::class); +} diff --git a/lib/middleware/AuthenticationMiddleware.php b/lib/middleware/AuthenticationMiddleware.php new file mode 100644 index 0000000000000000000000000000000000000000..739ce894261ac9838e5daff5cfd9577e3ade7479 --- /dev/null +++ b/lib/middleware/AuthenticationMiddleware.php @@ -0,0 +1,40 @@ +<?php +/** + * PSR 15 middleware Stud.IP Authentication + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * @author André Noack <noack@data-quest.de> + * @license http://www.gnu.org/licenses/gpl-2.0.html GPL version 2 + * @category Stud.IP + * @since 6.0 + */ +namespace Studip\Middleware; + +use Psr\Http\Message\ResponseFactoryInterface; +use Psr\Http\Message\ResponseInterface; +use Psr\Http\Message\ServerRequestInterface; +use Psr\Http\Server\MiddlewareInterface; +use Psr\Http\Server\RequestHandlerInterface; +use Studip\Authentication\Manager; + +final class AuthenticationMiddleware implements MiddlewareInterface +{ + public function __construct(private Manager $auth_manager, private ResponseFactoryInterface $response_factory) + { + } + + public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface + { + if ($this->auth_manager->start()) { + return $handler->handle($request); + } else { + $_SESSION['redirect_after_login'] = \Request::url(); + $response = $this->response_factory->createResponse(302); + return $response->withHeader('Location', \URLHelper::getURL('dispatch.php/login')); + } + } +} diff --git a/lib/middleware/SeminarOpenMiddleware.php b/lib/middleware/SeminarOpenMiddleware.php new file mode 100644 index 0000000000000000000000000000000000000000..108e0edbf3e604a41bb48d5ab03e2e78ac4178d3 --- /dev/null +++ b/lib/middleware/SeminarOpenMiddleware.php @@ -0,0 +1,295 @@ +<?php +/** + * PSR 15 middleware Stud.IP initialization + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * @author André Noack <noack@data-quest.de> + * @license http://www.gnu.org/licenses/gpl-2.0.html GPL version 2 + * @category Stud.IP + * @since 6.0 + */ + +namespace Studip\Middleware; + +use Psr\Http\Message\ResponseInterface; +use Psr\Http\Message\ServerRequestInterface; +use Psr\Http\Server\MiddlewareInterface; +use Psr\Http\Server\RequestHandlerInterface; +use Psr\Http\Message\ResponseFactoryInterface; + + +final class SeminarOpenMiddleware implements MiddlewareInterface +{ + + public function __construct(private ResponseFactoryInterface $response_factory) + { + } + + /** + * @param $page_code + * + * @return ResponseInterface + */ + public function startpageRedirect($page_code): ResponseInterface + { + switch ($page_code) { + case 1: + case 2: + $jump_page = 'dispatch.php/my_courses'; + break; + case 3: + $jump_page = 'dispatch.php/calendar/schedule'; + break; + case 4: + $jump_page = 'dispatch.php/contact'; + break; + case 5: + $jump_page = 'dispatch.php/calendar/calendar'; + break; + case 6: + // redirect to global blubberstream + // or no redirection if blubber isn't active + if (\Config::get()->BLUBBER_GLOBAL_MESSENGER_ACTIVATE) { + $jump_page = 'dispatch.php/blubber'; + } + break; + case 7: + $jump_page = 'dispatch.php/contents/overview'; + break; + } + $response = $this->response_factory->createResponse(302); + return $response->withHeader('Location', \URLHelper::getURL($jump_page)); + } + + /** + * @param ServerRequestInterface $request + * @param RequestHandlerInterface $handler + * + * @return ResponseInterface + */ + public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface + { + + global $user, $perm, $_language_path; + + + //INITS + $seminar_open_redirected = false; + $user_did_login = false; + + // session init starts here + if (empty($_SESSION['SessionStart'])) { + $_SESSION['SessionStart'] = time(); + $_SESSION['object_cache'] = []; + + // try to get accepted languages from browser + if (!isset($_SESSION['_language'])) { + $_SESSION['_language'] = get_accepted_languages(); + } + if (!$_SESSION['_language']) { + $_SESSION['_language'] = \Config::get()->DEFAULT_LANGUAGE; + } + } + + // user init starts here + if (is_object($user) && $user->id != "nobody") { + if ($_SESSION['SessionStart'] > \UserConfig::get( + $user->id + )->CURRENT_LOGIN_TIMESTAMP + ) { // just logged in + // store old CURRENT_LOGIN in LAST_LOGIN and set CURRENT_LOGIN to start of session + \UserConfig::get($user->id)->store( + 'LAST_LOGIN_TIMESTAMP', \UserConfig::get($user->id)->CURRENT_LOGIN_TIMESTAMP + ); + \UserConfig::get($user->id)->store('CURRENT_LOGIN_TIMESTAMP', $_SESSION['SessionStart']); + //find current semester and store it in $_SESSION['_default_sem'] + $current_sem = \Semester::findDefault(); + $_SESSION['_default_sem'] = $current_sem->semester_id ?? null; + //redirect user to another page if he want to, redirect is deferred to allow plugins to catch the UserDidLogin notification + if (\UserConfig::get($user->id)->PERSONAL_STARTPAGE > 0 && !isset($_SESSION['redirect_after_login']) + && !$perm->have_perm( + "root" + ) + ) { + $seminar_open_redirected = true; + } + unset($_SESSION['redirect_after_login']); + if (isset($_SESSION['contrast'])) { + \UserConfig::get($GLOBALS['user']->id)->store('USER_HIGH_CONTRAST', $_SESSION['contrast']); + unset($_SESSION['contrast']); + } + // store last language click + if (!empty($_SESSION['forced_language'])) { + \User::findCurrent()->preferred_language = $_SESSION['forced_language']; + \User::findCurrent()->store(); + $_SESSION['_language'] = $_SESSION['forced_language']; + } + $_SESSION['forced_language'] = null; + $user_did_login = true; + } + + \TwoFactorAuth::get()->secureSession(); + } + + if (!empty($_SESSION['contrast']) || \UserConfig::get($GLOBALS['user']->id)->USER_HIGH_CONTRAST) { + \PageLayout::addStylesheet('accessibility.css'); + } + + // init of output via I18N + $_language_path = init_i18n($_SESSION['_language']); + //force reload of config to get translated data + include $GLOBALS['STUDIP_BASE_PATH'] . '/config/config.inc.php'; + + + // Try to select the course or institute given by the parameter 'cid' + // in the current request. + + $course_id = (\Request::int('cancel_login') && (!is_object($user) || $user->id === 'nobody')) + ? null + : \Request::option('cid'); + + // Select the current course or institute if we got one from 'cid' or session. + // This also binds Context::getId() + // to the URL parameter 'cid' for all generated links. + if (isset($course_id)) { + \Context::set($course_id); + unset($course_id); + } + + if (\Request::int('disable_plugins') !== null && ($user->id === 'nobody' || $perm->have_perm('root'))) { + // deactivate non-core plugins + \PluginManager::getInstance()->setPluginsDisabled(\Request::int('disable_plugins')); + } + + // load the default set of plugins + \PluginEngine::loadPlugins(); + + // add navigation item for profile: add modules + if (\Navigation::hasItem('/profile/edit')) { + $plus_nav = new \Navigation(_('Mehr …'), 'dispatch.php/profilemodules/index'); + $plus_nav->setDescription(_('Mehr Stud.IP-Funktionen für Ihr Profil')); + \Navigation::addItem('/profile/modules', $plus_nav); + } + + if ($user_did_login) { + if (isset($_SESSION[\StudipAuthOAuth2::class]['redirect'])) { + $redirect = $_SESSION[\StudipAuthOAuth2::class]['redirect']; + unset($_SESSION[\StudipAuthOAuth2::class]); + $response = $this->response_factory->createResponse(302); + return $response->withHeader('Location', \URLHelper::getURL($redirect)); + } + \NotificationCenter::postNotification('UserDidLogin', $user->id); + } + + if (!\Request::isXhr() && $perm->have_perm('root')) { + if (!isset($_SESSION['migration-check']) || $_SESSION['migration-check']['timestamp'] < time() - 5 * 60) { + $migrator = new \Migrator( + "{$GLOBALS['STUDIP_BASE_PATH']}/db/migrations", + new \DBSchemaVersion('studip') + ); + + $_SESSION['migration-check'] = [ + 'disabled' => $_SESSION['migration-check']['disabled'] ?? false, + 'timestamp' => time(), + 'count' => $migrator->pendingMigrations() + ]; + } + + if (\Request::option('stop-migration-nag')) { + $_SESSION['migration-check']['disabled'] = true; + } + + if (empty($_SESSION['migration-check']['disabled']) + && $_SESSION['migration-check']['count'] > 0 + ) { + $info = sprintf( + _('Es gibt %u noch nicht ausgeführte Migration(en).'), + $_SESSION['migration-check']['count'] + ); + + $message = \MessageBox::info($info, [ + sprintf( + _('Zur %sMigrationsseite%s'), + '<a class="link-intern" href="' . \URLHelper::getLink('web_migrate.php') . '">', + '</a>' + ), + sprintf( + '<small><a href="%s">%s</a></small>', + \URLHelper::getLink('', ['stop-migration-nag' => true]), + _('Diese Nachricht bis zum nächsten Login nicht mehr anzeigen') + ) + ] + ); + \PageLayout::postMessage($message, 'migration-info'); + } + } + if ( + $GLOBALS['perm']->have_perm('root') + && \Config::get()->MIGRATION_START_VERSION + && \Config::get()->MIGRATION_START_VERSION < \StudipVersion::getStudipVersion(true) + && !\Config::get()->UPDATE_NEWS_SEEN + ) { + $message = \MessageBox::info( + _('Sie haben ein Stud.IP-Update durchgeführt.'), + [ + sprintf( + _('Zu den %sRelease-Notes%s'), + '<a class="link-intern" href="' . \URLHelper::getLink('dispatch.php/root_assistant') . '" data-dialog>', + '</a>' + ), + ] + ); + \PageLayout::postMessage($message, 'release-notes'); + } + + if ($seminar_open_redirected) { + $this->startpageRedirect(\UserConfig::get($user->id)->PERSONAL_STARTPAGE); + } + + // Show terms on first login + if (is_object($GLOBALS['user']) + && $GLOBALS['user']->needsToAcceptTerms() + && !match_route('dispatch.php/terms') + && !match_route('dispatch.php/siteinfo/*') + ) { + if (!\Request::isXhr()) { + $response = $this->response_factory->createResponse(302); + return $response->withHeader( + 'Location', \URLHelper::getURL( + 'dispatch.php/terms', + [ + 'return_to' => $_SERVER['REQUEST_URI'], + 'redirect_token' => \Token::create(600) + ], + true + ) + ); + } else { + throw new \Trails\Exception(400); + } + } + + if ( + \Config::get()->USER_VISIBILITY_CHECK + && is_object($GLOBALS['user']) + && $GLOBALS['user']->id !== 'nobody' + && !( + \Config::get()->DOZENT_ALWAYS_VISIBLE + && $perm->get_perm() === 'dozent' + ) + && !match_route('dispatch.php/siteinfo/*') + && $GLOBALS['user']->visible === 'unknown' + ) { + require_once('lib/user_visible.inc.php'); + $response = $this->response_factory->createResponse(200); + $response->getBody()->write((string)first_decision($GLOBALS['user']->id)); + return $response; + } + + return $handler->handle($request); + } +} diff --git a/lib/middleware/SessionMiddleware.php b/lib/middleware/SessionMiddleware.php new file mode 100644 index 0000000000000000000000000000000000000000..7c4f242dc95ef439935408b8d47650e68becdb24 --- /dev/null +++ b/lib/middleware/SessionMiddleware.php @@ -0,0 +1,43 @@ +<?php +/** + * PSR 15 middleware Stud.IP Session management + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * @author André Noack <noack@data-quest.de> + * @license http://www.gnu.org/licenses/gpl-2.0.html GPL version 2 + * @category Stud.IP + * @since 6.0 + */ +namespace Studip\Middleware; + +use Psr\Http\Message\ResponseInterface; +use Psr\Http\Message\ServerRequestInterface; +use Psr\Http\Server\MiddlewareInterface; +use Psr\Http\Server\RequestHandlerInterface; +use Studip\Session\Manager; + +final class SessionMiddleware implements MiddlewareInterface +{ + public function __construct(private Manager $session_manager) + { + } + + public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface + { + $this->session_manager->start(); + $response = $handler->handle($request); + try { + \NotificationCenter::postNotification('PageCloseWillExecute', null); + $this->session_manager->save(); + if (isset($GLOBALS['user'])) { + $GLOBALS['user']->set_last_action(); + } + \NotificationCenter::postNotification('PageCloseDidExecute', null); + } catch (\NotificationVetoException $e) {} + return $response; + } +} diff --git a/lib/navigation/AdminNavigation.php b/lib/navigation/AdminNavigation.php index 1dab05bf22e29e3f2a2b56be0bdac1522fe13306..62796d7abcf274c9963ef0d1737ee0de4189cb08 100644 --- a/lib/navigation/AdminNavigation.php +++ b/lib/navigation/AdminNavigation.php @@ -223,7 +223,7 @@ class AdminNavigation extends Navigation $navigation = new Navigation($back_jump, 'dispatch.php/institute/overview?auswahl=' . Context::getId()); $this->addSubNavigation('back_jump', $navigation); } else if (Context::isCourse() && !$archive_kill && !(isset($_SESSION['links_admin_data']['assi']) && $_SESSION['links_admin_data']['assi'])) { - $navigation = new Navigation($back_jump, 'seminar_main.php?auswahl=' . Context::getId()); + $navigation = new Navigation($back_jump, 'dispatch.php/course/go?to=' . Context::getId()); $this->addSubNavigation('back_jump', $navigation); } diff --git a/lib/navigation/AvatarNavigation.php b/lib/navigation/AvatarNavigation.php index 64bbdbc68a1db3be1adb31cbb5573b35bb350713..9e95bb0bd91bcaa1d12ceac55eeff866193584fa 100644 --- a/lib/navigation/AvatarNavigation.php +++ b/lib/navigation/AvatarNavigation.php @@ -46,7 +46,7 @@ class AvatarNavigation extends Navigation } // Link to logout - $navigation = new Navigation(_('Logout'), 'logout.php'); + $navigation = new Navigation(_('Logout'), 'dispatch.php/logout'); $navigation->setImage(Icon::create('door-leave')); $navigation->setRenderAsButton(); $this->addSubNavigation('logout', $navigation); diff --git a/lib/phplib/CT_Cache.php b/lib/phplib/CT_Cache.php deleted file mode 100644 index d4eccfa0a2702b7055e5c7197010a1c8b9e95d1c..0000000000000000000000000000000000000000 --- a/lib/phplib/CT_Cache.php +++ /dev/null @@ -1,68 +0,0 @@ -<?php - -## Copyright (c) 2011 Elmar Ludwig, University of Osnabrueck -## -## PHPLIB Data Storage Container using Stud.IP cache -## for use with Stud.IP and cache only! - -class CT_Cache -{ - protected const CACHE_KEY_PREFIX = 'session_data'; - protected const SESSION_LIFETIME = 7200; - - private $cache; - - public function ac_start() - { - $this->cache = \Studip\Cache\Factory::getCache(); - } - - public function ac_get_lock() - { - } - - public function ac_release_lock() - { - } - - public function ac_newid($str, $name = null) - { - return $this->ac_get_value($str) === false ? $str : false; - } - - public function ac_store($id, $name, $str) - { - $cache_key = self::CACHE_KEY_PREFIX . '/' . $id; - return $this->cache->write($cache_key, $str, ini_get('session.gc_maxlifetime') ?: self::SESSION_LIFETIME); - } - - public function ac_delete($id, $name = null) - { - $cache_key = self::CACHE_KEY_PREFIX . '/' . $id; - $this->cache->expire($cache_key); - } - - public function ac_gc($gc_time, $name = null) - { - } - - public function ac_halt($s) - { - echo "<b>$s</b>"; - exit; - } - - public function ac_get_value($id, $name = null) - { - $cache_key = self::CACHE_KEY_PREFIX . '/' . $id; - return $this->cache->read($cache_key); - } - - public function ac_get_changed($id, $name = null) - { - } - - public function ac_set_changed($id, $name, $timestamp) - { - } -} diff --git a/lib/phplib/CT_Sql.php b/lib/phplib/CT_Sql.php deleted file mode 100644 index 220af2241d8371541c5c6de0e1ccb1e566720160..0000000000000000000000000000000000000000 --- a/lib/phplib/CT_Sql.php +++ /dev/null @@ -1,101 +0,0 @@ -<?php - -## -## Copyright (c) 1998-2000 NetUSE AG -## Boris Erdmann, Kristian Koehntopp -## -## Copyright (c) 1998-2000 Sascha Schumann <sascha@schumann.cx> -## -## PHPLIB Data Storage Container using a SQL database -## for use with Stud.IP and PDO only! - -class CT_Sql { - - ## - ## Define these parameters by overwriting or by - ## deriving your own class from it (recommened) - ## - - var $database_table = "session_data"; - var $gzip_level = 0; - var $exists = ''; - - ## end of configuration - - function ac_start() { - } - - function ac_get_lock() { - return true; - } - - function ac_release_lock() { - return true; - } - - function ac_gc($gc_time, $name = null) { - return DBManager::get()->exec(sprintf("DELETE FROM %s WHERE changed < FROM_UNIXTIME(%s) ", - $this->database_table, - (time() - ($gc_time * 60)) - )); - } - - function ac_store($id, $name, $str) { - $db = DBManager::get(); - if ($this->gzip_level){ - $str = gzcompress($str, $this->gzip_level); - } - if ($this->exists === $id) { - $stmt = $db->prepare(sprintf("UPDATE %s SET val = ? WHERE sid = ?", $this->database_table)); - } else { - $stmt = $db->prepare(sprintf("REPLACE INTO %s ( val, sid ) VALUES (?, ?)", $this->database_table)); - } - $stmt->execute([$str, $id]); - return $stmt->rowCount(); - } - - function ac_delete($id, $name = null) { - return DBManager::get()->exec(sprintf("DELETE FROM %s WHERE sid = '%s' LIMIT 1", - $this->database_table, - $id)); - } - - function ac_get_value($id, $name = null) { - $rs = DBManager::get()->query(sprintf("SELECT val FROM %s where sid = '%s'", - $this->database_table, - $id)); - $str = $rs->fetchColumn(); - if ($this->gzip_level){ - $str = @gzuncompress($str); - } - if ($str) $this->exists = $id; - return $str; - } - - function ac_get_changed($id, $name = null){ - $rs = DBManager::get()->query(sprintf("SELECT UNIX_TIMESTAMP(changed) FROM %s WHERE sid = '%s'", - $this->database_table, - $id)); - return $rs->fetchColumn(); - } - - function ac_set_changed($id, $name, $timestamp){ - $db = DBManager::get(); - $stmt = $db->prepare(sprintf("UPDATE %s SET changed = FROM_UNIXTIME(?) WHERE sid = ?", $this->database_table)); - $stmt->execute([$timestamp, $id]); - return $stmt->rowCount(); - } - - function ac_newid($str, $name = null) { - $db = DBManager::get(); - $query = "SELECT sid FROM " . $this->database_table . " WHERE sid = '$str'"; - if (!$db->query($query)->fetchColumn()) { - return $str; - } else { - return FALSE; - } - } - - function ac_halt($s) { - } -} diff --git a/lib/phplib/DB_Sql.php b/lib/phplib/DB_Sql.php deleted file mode 100644 index 1a6170308f3b84d17676a39b8e3e56d0a66d869a..0000000000000000000000000000000000000000 --- a/lib/phplib/DB_Sql.php +++ /dev/null @@ -1,260 +0,0 @@ -<?php - -/* - * Copyright (C) 2007 - Marcus Lunzenauer <mlunzena@uos.de> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - */ - - -class DB_Sql { - - /* public: connection parameters */ - public $Host = ""; - public $Database = ""; - public $User = ""; - public $Password = ""; - - /* public: configuration parameters */ - public $Auto_Free = 1; ## Set to 1 for automatic mysql_free_result() - public $Debug = 0; ## Set to 1 for debugging messages. - public $Halt_On_Error = "yes"; ## "yes" (halt with message), "no" (ignore errors quietly), "report" (ignore errror, but spit a warning) - - /* public: result array and current row number */ - public $Record = []; - public $Row; - public $RowCount; - public $ColumnCount; - - /* public: current error number and error text */ - public $Errno = 0; - public $Error = ""; - - protected $pdo; - protected $resultSet; - - /* public: constructor */ - function __construct($query = "") { - $this->pdo = DBManager::get(); - $this->query($query); - } - - function link_id() { - return TRUE; - } - - function query_id() { - return !is_null($this->resultSet); - } - - /* public: discard the query result */ - function free() { - $this->resultSet = NULL; - $this->Errno = NULL; - $this->Error = NULL; - $this->Row = 0; - $this->RowCount = null; - $this->ColumnCount = null; - } - - /* public: perform a query */ - function query($Query_String) { - - $Query_String = trim($Query_String); - if ($Query_String == "") { - return 0; - } - - # New query, discard previous result. - $this->free(); - - if ($this->Debug) { - printf("Debug: query = %s<br>\n", $Query_String); - } - if(mb_stripos($Query_String, 'select') === 0 || mb_stripos($Query_String, 'show') === 0){ - - $this->resultSet = $this->pdo->query($Query_String); - - # Will return nada if it fails. That's fine. - return $this->resultSet; - } else { - $this->RowCount = $this->pdo->exec($Query_String); - return $this->RowCount; - } - } - - /* public: walk result set */ - function next_record() { - if (!$this->resultSet) { - //$this->halt("next_record called with no query pending."); - return 0; - } - - $this->Record = $this->resultSet->fetch(); - $this->Row += 1; - /* - $this->Errno = $this->resultSet->errorCode(); - $this->Error = $this->resultSet->errorInfo(); - */ - $stat = is_array($this->Record); - if ($this->Row == $this->num_rows()) { - $this->ColumnCount = $this->resultSet->ColumnCount(); - $this->resultSet = null; - } - return $stat; - } - - /* public: evaluate the result (size, width) */ - function affected_rows() { - return $this->num_rows(); - } - - function num_rows() { - return (!is_null($this->RowCount) ? $this->RowCount : ($this->resultSet ? ($this->RowCount = $this->resultSet->rowCount()) : FALSE)); - } - - function num_fields() { - return (!is_null($this->ColumnCount) ? $this->ColumnCount : ($this->resultSet ? ($this->ColumnCount = $this->resultSet->ColumnCount()) : FALSE)); - } - - /* public: shorthand notation */ - function nf() { - return $this->num_rows(); - } - - function np() { - print $this->num_rows(); - } - - function f($Name) { - return $this->Record[$Name]; - } - - function p($Name) { - print $this->Record[$Name]; - } - - /* public: return table metadata */ - function metadata($table='',$full=false) { - $count = 0; - $id = 0; - $res = []; - - /* - * Due to compatibility problems with Table we changed the behavior - * of metadata(); - * depending on $full, metadata returns the following values: - * - * - full is false (default): - * $result[]: - * [0]["table"] table name - * [0]["name"] field name - * [0]["type"] field type - * [0]["len"] field length - * [0]["flags"] field flags - * - * - full is true - * $result[]: - * ["num_fields"] number of metadata records - * [0]["table"] table name - * [0]["name"] field name - * [0]["type"] field type - * [0]["len"] field length - * [0]["flags"] field flags - * ["meta"][field name] index of field named "field name" - * The last one is used, if you have a field name, but no index. - * Test: if (isset($result['meta']['myfield'])) { ... - */ - - // if no $table specified, assume that we are working with a query - // result - if ($table) { - throw new Exception('Not yet implemented.'); - $this->connect(); - $id = @mysql_list_fields($this->Database, $table); - if (!$id) - $this->halt("Metadata query failed."); - } else { - if (is_null($this->resultSet)) - $this->halt("No query specified."); - } - - $count = $this->resultSet->ColumnCount(); - - // made this IF due to performance (one if is faster than $count if's) - if (!$full) { - for ($i = 0; $i < $count; $i++) { - $meta = $this->resultSet->getColumnMeta($i); - $res[$i]["table"] = $meta['table']; - $res[$i]["name"] = $meta['name']; - $res[$i]["type"] = $meta['native_type']; - $res[$i]["len"] = $meta['len']; - $res[$i]["flags"] = $meta['flags']; - } - } else { // full - throw new Exception('Not yet implemented.'); - $res["num_fields"]= $count; - - for ($i=0; $i<$count; $i++) { - $res[$i]["table"] = @mysql_field_table ($id, $i); - $res[$i]["name"] = @mysql_field_name ($id, $i); - $res[$i]["type"] = @mysql_field_type ($id, $i); - $res[$i]["len"] = @mysql_field_len ($id, $i); - $res[$i]["flags"] = @mysql_field_flags ($id, $i); - $res["meta"][$res[$i]["name"]] = $i; - } - } - - // free the result only if we were called on a table - if ($table) { - throw new Exception('Not yet implemented.'); - @mysql_free_result($id); - } - - return $res; - } - - /* private: error handling */ - function halt($msg) { - if ($this->Halt_On_Error == "no") - return; - - $this->haltmsg($msg); - - if ($this->Halt_On_Error != "report") - die("Session halted."); - } - - function haltmsg($msg) { - printf("</td></tr></table><b>Database error:</b> %s<br>\n", $msg); - printf("<b>MySQL Error</b>: %s (%s)<br>\n", - $this->Errno, - join(':',$this->Error)); - } - - /* public: perform a query using format string*/ - function queryf($format /* , .. */) { - - // get args - $args = func_get_args(); - - // get format string - $format = array_shift($args); - - // do something - return $this->query(vsprintf($format, $args)); - } - - /** - * perform a query with caching directive for mysql - * @param string $Query_String - * @return Resultset | int - */ - public function cache_query($Query_String) { - trigger_error(__CLASS__ . ' no longer supports query caching - use query() instead.', E_USER_DEPRECATED); - return $this->query($Query_String); - } -} diff --git a/lib/phplib/Seminar_Auth.php b/lib/phplib/Seminar_Auth.php deleted file mode 100644 index 4150df5fe2e139c1addb389cd94218a093857c68..0000000000000000000000000000000000000000 --- a/lib/phplib/Seminar_Auth.php +++ /dev/null @@ -1,455 +0,0 @@ -<?php - -/** - * Seminar_Auth.php - * - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * @author André Noack <noack@data-quest.de> - * @copyright 2000 Stud.IP Core-Group - * @license http://www.gnu.org/licenses/gpl-2.0.html GPL version 2 - */ -class Seminar_Auth -{ - /** - * @var string - */ - public $classname; - - /** - * @var string - */ - public $error_msg = ""; - - /** - * @var array - */ - protected $persistent_slots = ["auth", "classname"]; - - /** - * @var bool - */ - protected $nobody = false; ## If true, a default auth is created... - - /** - * @var string - */ - protected $cancel_login = "cancel_login"; ## The name of a button that can be - ## used to cancel a login form - /** - * @var array - */ - public $auth = []; ## Data array - - public $need_email_activation = null; - - /** - * - */ - function __construct() - { - $this->classname = get_class($this); - } - - /** - * @param $f - * @return $this - */ - function check_feature($f) - { - if ($this->classname != $f) { - $clone = new $f; - $clone->auth = $this->auth; - return $clone; - } else { - return $this; - } - } - - /** - * Check current auth state. Should be one of - * 1) Not logged in (no valid auth info or auth expired) - * 2) Logged in (valid auth info) - * 3) Login in progress (if $this->cancel_login, revert to state 1) - - * @return int - */ - protected function getState(): int - { - if ($this->is_authenticated()) { - $uid = $this->auth['uid']; - switch ($uid) { - case 'form': - # Login in progress - if (Request::option($this->cancel_login)) { - # If $this->cancel_login is set, delete all auth info and set - # state to "Not logged in", so eventually default or automatic - # authentication may take place - $this->unauth(); - $state = 1; - } else { - # Set state to "Login in progress" - $state = 3; - } - break; - default: - # User is authenticated and auth not expired - $state = 2; - break; - } - } else { - # User is not (yet) authenticated - $this->unauth(); - $state = 1; - } - - return $state; - } - - /** - * @return bool - * @throws RuntimeException - */ - public function start() - { - global $sess; - - switch ($this->getState()) { - case 1: - # No valid auth info or auth is expired - - # Check for user supplied automatic login procedure - if ($uid = $this->auth_preauth()) { - $this->auth["uid"] = $uid; - $sess->regenerate_session_id([ - '_language', - 'auth', - 'contrast', - 'phpCAS', - StudipAuthOAuth2::class - ]); - $sess->freeze(); - $GLOBALS['user'] = new Seminar_User($this->auth['uid']); - return true; - } - - if ($this->nobody) { - # Authenticate as nobody - $this->auth["uid"] = "nobody"; - return true; - } else { - # Show the login form - $this->auth_loginform(); - $this->auth["uid"] = "form"; - $sess->freeze(); - exit; - } - case 2: - # Valid auth info - # do nothin - break; - case 3: - # Login in progress, check results and act accordingly - $uid = $this->auth_validatelogin(); - if ($uid) { - $this->auth["uid"] = $uid; - $keep_session_vars = ['auth', 'forced_language', '_language', 'contrast', 'oauth2']; - if ($this->auth['perm'] === 'root') { - $keep_session_vars[] = 'plugins_disabled'; - } - $sess->regenerate_session_id($keep_session_vars); - $sess->freeze(); - $GLOBALS['user'] = new Seminar_User($this->auth['uid']); - return true; - } else { - $this->auth_loginform(); - $this->auth["uid"] = "form"; - $sess->freeze(); - exit; - } - default: - # This should never happen. Complain. - throw new RuntimeException("Error in auth handling: invalid state reached."); - } - - return false; - } - - - /** - * @return array - */ - function __sleep() - { - return $this->persistent_slots; - } - - - /** - * - */ - function unauth() - { - $this->auth = []; - $this->auth["uid"] = ""; - $this->auth["perm"] = ""; - } - - - /** - * - */ - function logout() - { - $_SESSION['auth'] = null; - $this->unauth(); - $GLOBALS['auth'] = $this; - } - - /** - * @param $ok - * @return bool - */ - function login_if($ok) - { - if ($ok) { - $this->unauth(); # We have to relogin, so clear current auth info - $this->nobody = false; # We are forcing login, so default auth is - # disabled - $this->start(); # Call authentication code - } - return true; - } - - /** - * @return bool - * @throws AccessDeniedException - */ - function is_authenticated() - { - $cfg = Config::GetInstance(); - //check if the user got kicked meanwhile, or if user is locked out - if (!empty($this->auth['uid']) && !in_array($this->auth['uid'], ['form', 'nobody'])) { - $user = null; - if (isset($GLOBALS['user']) && $GLOBALS['user']->id == $this->auth['uid']) { - $user = $GLOBALS['user']->getAuthenticatedUser(); - } else { - $user = User::find($this->auth['uid']); - } - if (!$user->username || $user->isBlocked()) { - $this->unauth(); - } - } elseif ($cfg->getValue('MAINTENANCE_MODE_ENABLE') && Request::username('loginname')) { - $user = User::findByUsername(Request::username('loginname')); - } - if ($cfg->getValue('MAINTENANCE_MODE_ENABLE') && $user->perms != 'root') { - $this->unauth(); - throw new AccessDeniedException(_("Das System befindet sich im Wartungsmodus. Zur Zeit ist kein Zugriff möglich.")); - } - return @$this->auth['uid'] ? : false; - } - - /** - * @return bool - */ - function auth_preauth() - { - // is Single Sign On activated? - if (($provider = Request::option('sso'))) { - - $this->check_environment(); - - Metrics::increment('core.sso_login.attempted'); - - // then do login - if (($authplugin = StudipAuthAbstract::GetInstance($provider))) { - $user = $authplugin->authenticateUser('', ''); - if ($user) { - if ($user->isExpired()) { - throw new AccessDeniedException(_('Dieses Benutzerkonto ist abgelaufen. Wenden Sie sich bitte an die Administration.')); - } - if ($user->locked == 1) { - throw new AccessDeniedException(_('Dieser Benutzer ist gesperrt! Wenden Sie sich bitte an die Administration.')); - } - $this->auth["jscript"] = true; - $this->auth["perm"] = $user->perms; - $this->auth["uname"] = $user->username; - $this->auth["auth_plugin"] = $user->auth_plugin; - $this->auth_set_user_settings($user); - - Metrics::increment('core.sso_login.succeeded'); - - return $user->id; - } else { - PageLayout::postMessage(MessageBox::error($authplugin->plugin_name . ': ' . _('Login fehlgeschlagen'), $authplugin->error_msg ? [$authplugin->error_msg] : []),md5($authplugin->error_msg)); - } - } - } - - return false; - } - - /** - * - */ - function auth_loginform() - { - if (Request::isXhr()) { - if (Request::isDialog()) { - header('X-Location: ' . URLHelper::getURL($_SERVER['REQUEST_URI'])); - page_close(); - die(); - } - throw new AccessDeniedException(); - } - - if (Request::submitted('user_config_submitted')) { - CSRFProtection::verifyUnsafeRequest(); - if (Request::submitted('unset_contrast')) { - $_SESSION['contrast'] = 0; - } - if (Request::submitted('set_contrast')) { - $_SESSION['contrast'] = 1; - } - - foreach (array_keys($GLOBALS['INSTALLED_LANGUAGES']) as $language_key) { - if (Request::get('set_language') === $language_key) { - $_SESSION['forced_language'] = $language_key; - $_SESSION['_language'] = $language_key; - } - } - } - $this->check_environment(); - - PageLayout::setBodyElementId('login'); - - // load the default set of plugins - PluginEngine::loadPlugins(); - - if (Request::get('loginname') && empty($_COOKIE[get_class($GLOBALS['sess'])])) { - $login_template = $GLOBALS['template_factory']->open('nocookies'); - } else if (isset($this->need_email_activation)) { - $this->unauth(); - header('Location: ' . URLHelper::getURL('activate_email.php?cancel_login=1&key=&uid=' . $this->need_email_activation)); - page_close(); - die(); - } else { - $news_entries = StudipNews::GetNewsByRange('login', true, false); - unset($_SESSION['semi_logged_in']); // used by email activation - $login_template = $GLOBALS['template_factory']->open('loginform'); - if (isset($this->auth['uname']) && $this->error_msg) { - PageLayout::postError(_('Bei der Anmeldung trat ein Fehler auf!'), $this->error_msg); - } - $login_template->error_msg = $this->error_msg; - $login_template->uname = $this->auth['uname'] ?? Request::username('loginname'); - $login_template->self_registration_activated = Config::get()->ENABLE_SELF_REGISTRATION; - $login_template->logout = Request::bool('logout', false); - $login_template->faq_entries = []; - $login_template->news_entries = array_values($news_entries); - - if (Config::get()->getValue('LOGIN_FAQ_VISIBILITY')) { - $login_template->faq_entries = LoginFaq::findBySQL('1'); - } - } - PageLayout::setHelpKeyword('Basis.AnmeldungLogin'); - $header_template = $GLOBALS['template_factory']->open('header'); - $header_template->current_page = _('Login'); - $header_template->link_params = ['cancel_login' => 1]; - - include 'lib/include/html_head.inc.php'; - echo $header_template->render(); - echo $login_template->render(); - include 'lib/include/html_end.inc.php'; - page_close(); - } - - /** - * @return bool - */ - function auth_validatelogin() - { - //prevent replay attack - if (!Seminar_Session::check_ticket(Request::option('login_ticket'))) { - return false; - } - - $this->check_environment(); - - $this->auth["uname"] = Request::get('loginname'); // This provides access for "loginform.ihtml" - $this->auth["jscript"] = Request::get('resolution') != ""; - - $check_auth = StudipAuthAbstract::CheckAuthentication(Request::get('loginname'), Request::get('password')); - - if ($check_auth['uid']) { - $uid = $check_auth['uid']; - if (isset($check_auth['need_email_activation']) && $check_auth['need_email_activation'] == $uid) { - $this->need_email_activation = $uid; - $_SESSION['semi_logged_in'] = $uid; - return false; - } - $user = $check_auth['user']; - $this->auth["perm"] = $user->perms; - $this->auth["uname"] = $user->username; - $this->auth["auth_plugin"] = $user->auth_plugin; - $this->auth_set_user_settings($user); - - Metrics::increment('core.login.succeeded'); - - return $uid; - } else { - Metrics::increment('core.login.failed'); - $this->error_msg = $check_auth['error']; - return false; - } - } - - /** - * @param $user - */ - function auth_set_user_settings($user) - { - $divided = explode('x', Request::get('resolution')); - $this->auth["xres" . ""] = !empty($divided[0]) ? (int) $divided[0] : 1024; //default - $this->auth['yres'] = !empty($divided[1]) ? (int)$divided[1] : 768; //default - // Change X-Resulotion on Multi-Screen Systems (as Matrox Graphic-Adapters are) - if ($this->auth['xres'] / $this->auth['yres'] > 2) { - $this->auth['xres'] = $this->auth['xres'] / 2; - } - $user = User::toObject($user); - //restore user-specific language preference - if ($user->preferred_language) { - // we found a stored setting for preferred language - $_SESSION['_language'] = $user->preferred_language; - } - } - - /** - * setup dummy user environment - */ - function check_environment() - { - global $_language_path; - - if (!isset($GLOBALS['user']) || $GLOBALS['user']->id !== 'nobody') { - $GLOBALS['user'] = new Seminar_User('nobody'); - $GLOBALS['perm'] = new Seminar_Perm(); - $GLOBALS['auth'] = $this; - } - - if (empty($_SESSION['_language'])) { - $_SESSION['_language'] = get_accepted_languages(); - } - - // init of output via I18N - $_language_path = init_i18n($_SESSION['_language']); - include $GLOBALS['STUDIP_BASE_PATH'] . '/config/config.inc.php'; - - if (!empty($_SESSION['contrast'])) { - PageLayout::addStylesheet('accessibility.css'); - } - } -} diff --git a/lib/phplib/Seminar_Default_Auth.php b/lib/phplib/Seminar_Default_Auth.php deleted file mode 100644 index 146c5888be46be6e38cff2d72178b68ce5529b29..0000000000000000000000000000000000000000 --- a/lib/phplib/Seminar_Default_Auth.php +++ /dev/null @@ -1,19 +0,0 @@ -<?php - -/** - * Seminar_Default_Auth.php - * - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * @author André Noack <noack@data-quest.de> - * @copyright 2000 Stud.IP Core-Group - * @license http://www.gnu.org/licenses/gpl-2.0.html GPL version 2 - */ -class Seminar_Default_Auth extends Seminar_Auth -{ - protected $nobody = true; -} diff --git a/lib/phplib/Seminar_Register_Auth.php b/lib/phplib/Seminar_Register_Auth.php deleted file mode 100644 index 5bf10f188468a543f39f4c9be9528ba71272a7c5..0000000000000000000000000000000000000000 --- a/lib/phplib/Seminar_Register_Auth.php +++ /dev/null @@ -1,242 +0,0 @@ -<?php - -/** - * Seminar_Register_Auth.php - * - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * @author André Noack <noack@data-quest.de> - * @copyright 2000 Stud.IP Core-Group - * @license http://www.gnu.org/licenses/gpl-2.0.html GPL version 2 - */ -class Seminar_Register_Auth extends Seminar_Auth -{ - public function start() - { - global $sess; - - switch ($this->getState()) { - # No valid auth info or auth is expired - case 1: - - if ($this->nobody) { - # Authenticate as nobody - $this->auth['uid'] = 'nobody'; - return true; - } else { - # Show the registration form - $this->auth_registerform(); - $this->auth['uid'] = 'form'; - exit; - } - # Login in progress, check results and act accordingly - case 3: - $uid = $this->auth_doregister(); - if ($uid) { - $this->auth['uid'] = $uid; - $GLOBALS['user'] = new Seminar_User($this->auth['uid']); - return true; - } else { - $this->auth_registerform(); - $this->auth['uid'] = 'form'; - $sess->freeze(); - exit; - } - } - - return parent::start(); - } - - public function auth_registerform() - { - $this->check_environment(); - - // load the default set of plugins - PluginEngine::loadPlugins(); - - if (!$_COOKIE[get_class($GLOBALS['sess'])]) { - $register_template = $GLOBALS['template_factory']->open('nocookies'); - } else { - $register_template = $GLOBALS['template_factory']->open('register/form'); - $register_template->validator = new email_validation_class(); - $register_template->error_msg = $this->error_msg; - $register_template->username = Request::get('username'); - $register_template->Vorname = Request::get('Vorname'); - $register_template->Nachname = Request::get('Nachname'); - $register_template->Email = Request::get('Email'); - $register_template->title_front = Request::get('title_front'); - $register_template->title_rear = Request::get('title_rear'); - $register_template->geschlecht = Request::int('geschlecht', 0); - } - PageLayout::setHelpKeyword('Basis.AnmeldungRegistrierung'); - PageLayout::setTitle(_('Registrierung')); - - echo $register_template->render( - [], - $GLOBALS['template_factory']->open('layouts/base.php') - ); - } - - /** - * @return bool|string - */ - public function auth_doregister() - { - $this->check_environment(); - - $this->error_msg = ''; - - $this->auth['uname'] = Request::username('username'); // This provides access for "crcregister.ihtml" - - $validator = new email_validation_class(); // Klasse zum Ueberpruefen der Eingaben - $validator->timeout = 10; // Wie lange warten wir auf eine Antwort des Mailservers? - - if (!Seminar_Session::check_ticket(Request::option('login_ticket'))) { - return false; - } - - $username = trim(Request::get('username')); - $Vorname = trim(Request::get('Vorname')); - $Nachname = trim(Request::get('Nachname')); - - // accept only registered domains if set - if (Config::get()->EMAIL_DOMAIN_RESTRICTION) { - $Email = trim(Request::get('Email')) . '@' . trim(Request::get('emaildomain')); - } else { - $Email = trim(Request::get('Email')); - } - - if (!$validator->ValidateUsername($username)) { - $this->error_msg = $this->error_msg . _('Der gewählte Benutzername ist zu kurz!') . '<br>'; - return false; - } // username syntaktisch falsch oder zu kurz - // auf doppelte Vergabe wird weiter unten getestet. - - if (!$validator->ValidatePassword(Request::get('password'))) { - $this->error_msg = $this->error_msg . _('Das Passwort ist zu kurz, zu lang oder enthält nicht erlaubte Zeichen!') . '<br>'; - return false; - } - - if (!$validator->ValidateName($Vorname)) { - $this->error_msg = $this->error_msg . _('Der Vorname fehlt oder ist unsinnig!') . '<br>'; - return false; - } // Vorname nicht korrekt oder fehlend - if (!$validator->ValidateName($Nachname)) { - $this->error_msg = $this->error_msg . _('Der Nachname fehlt oder ist unsinnig!') . '<br>'; - return false; // Nachname nicht korrekt oder fehlend - } - if (!$validator->ValidateEmailAddress($Email)) { - $this->error_msg = $this->error_msg . _('Die E-Mail-Adresse fehlt oder ist falsch geschrieben!') . '<br>'; - return false; - } // E-Mail syntaktisch nicht korrekt oder fehlend - - $REMOTE_ADDR = $_SERVER['REMOTE_ADDR']; - $Zeit = date('H:i:s, d.m.Y'); - - if (!$validator->ValidateEmailHost($Email)) { // Mailserver nicht erreichbar, ablehnen - $this->error_msg = $this->error_msg . _('Der Mailserver ist nicht erreichbar, bitte überprüfen Sie, ob Sie E-Mails mit der angegebenen Adresse verschicken und empfangen können!') . '<br>'; - return false; - } else { // Server ereichbar - if (!$validator->ValidateEmailBox($Email)) { // aber user unbekannt. Mail an abuse! - StudipMail::sendAbuseMessage('Register', "Emailbox unbekannt\n\nUser: $username\nEmail: $Email\n\nIP: $REMOTE_ADDR\nZeit: $Zeit\n"); - $this->error_msg = $this->error_msg . _('Die angegebene E-Mail-Adresse ist nicht erreichbar, bitte überprüfen Sie Ihre Angaben!') . '<br>'; - return false; - } else { - ; // Alles paletti, jetzt kommen die Checks gegen die Datenbank... - } - } - - $check_uname = StudipAuthAbstract::CheckUsername($username); - - if ($check_uname['found']) { - $this->error_msg = $this->error_msg . _('Der gewählte Benutzername ist bereits vorhanden!') . '<br>'; - return false; // username schon vorhanden - } - - if (User::countBySQL('Email = ?', [$Email])) { - $this->error_msg = $this->error_msg . _('Die angegebene E-Mail-Adresse wird bereits von einem anderen Benutzer verwendet. Sie müssen eine andere E-Mail-Adresse angeben!') . '<br>'; - return false; // Email schon vorhanden - } - - // alle Checks ok, Benutzer registrieren... - $hasher = UserManagement::getPwdHasher(); - $new_user = new User(); - $new_user->username = $username; - $new_user->perms = 'user'; - $new_user->password = $hasher->HashPassword(Request::get('password')); - $new_user->vorname = $Vorname; - $new_user->nachname = $Nachname; - $new_user->email = $Email; - $new_user->geschlecht = Request::int('geschlecht'); - $new_user->title_front = trim(Request::get('title_front', Request::get('title_front_chooser'))); - $new_user->title_rear = trim(Request::get('title_rear', Request::get('title_rear_chooser'))); - $new_user->auth_plugin = 'standard'; - $new_user->store(); - - if (!$new_user->user_id) { - return false; - } - - self::sendValidationMail($new_user); - - $this->auth['perm'] = $new_user->perms; - $this->auth['uname'] = $new_user->username; - $this->auth['auth_plugin'] = $new_user->auth_plugin; - - return $new_user->user_id; - } - - /** - * Send a validation mail to the passed user - * - * @param User $user a user-object or id of the user - * to resend the validation mail for - */ - public static function sendValidationMail($user){ - // if no user-object is given interpret it as a user-id - if (is_string($user)) { - $user = new User($user); - } - - // template-variables for the include partial - $Zeit = date('H:i:s, d.m.Y', $user->mkdate); - $username = $user->username; - $Vorname = $user->vorname; - $Nachname = $user->nachname; - $Email = $user->email; - - // (re-)send the confirmation mail - $to = $user->email; - $token = Token::create(7 * 24 * 60 * 60, $user->id); // Link is valid for 1 week - $url = $GLOBALS['ABSOLUTE_URI_STUDIP'] . 'email_validation.php?secret=' . $token; - $mail = new StudipMail(); - $abuse = StudipMail::getAbuseEmail(); - - $lang_path = getUserLanguagePath($user->id); - - // include language-specific subject and mailbody - // TODO: This should be refactored so that the included file returns an array - include "locale/{$lang_path}/LC_MAILS/register_mail.inc.php"; // Defines $subject and $mailbody - - // send the mail - $mail->setSubject($subject ?? '') - ->addRecipient($to) - ->setBodyText($mailbody ?? '') - ->send(); - } - - /** - * Validates a given hash for a given user id. - * @param string $secret Secret to validate - * @param string $user_id User id - * @return bool - */ - public static function validateSecret($secret, $user_id) - { - return Token::isValid($secret, $user_id); - } -} diff --git a/lib/phplib/Seminar_Session.php b/lib/phplib/Seminar_Session.php deleted file mode 100644 index 8324062dbe175638febfa93ec0ab076f51c07ca3..0000000000000000000000000000000000000000 --- a/lib/phplib/Seminar_Session.php +++ /dev/null @@ -1,436 +0,0 @@ -<?php - -/** - * PHPLib Sessions using PHP 4 build-in sessions and PHPLib storage container - * - * @copyright (c) 1998,1999 NetUSE GmbH Boris Erdmann, Kristian Koehntopp, - * 2000 Maxim Derkachev <kot@books.ru>, - * 2000 Teodor Cimpoesu <teo@digiro.net> - * @author André Noack <noack@data-quest.de> Maxim Derkachev <kot@books.ru>, - * Teodor Cimpoesu <teo@digiro.net>,Ulf Wendel <uw@netuse.de> - */ -class Seminar_Session -{ - /** - * Current session id. - * - * @var string - * @see id(), Session() - */ - private $id; - - - /** - * Current session name also cookie name - * - * @var string - * @see name(), Session() - */ - private $name; - - /** - * - * @var string - */ - private $cookie_path; - - /** - * If set, the domain for which the session cookie is set. - * - * @var string - */ - private $cookie_domain; - - /** - * If set, the domain for which the session cookie is set. - * - * @var bool - */ - private $cookie_secure = false; - - /** - * If set, the domain for which the session cookie is set. - * - * @var bool - */ - private $cookie_httponly = true; - - /** - * session storage module - user, files or mm - * - * @var string - */ - private $module = 'user'; - - - /** - * where to save session files if module == files - * - * @var string - */ - private $save_path; - - - /** - * Name of data storage container - * - * var string - */ - private $that_class = 'CT_Sql'; - - /** - * - * @var object CT_* - */ - private $that; - - /** - * Purge all session data older than this. - * - * @var int - */ - private $gc_time; - - - /** - * @var - */ - private static $studipticket; - /** - * @var - */ - private static $current_session_state; - - /** - * Returns true, if the current session is valid and belongs to an - * authenticated user. Does not start a session. - * - * @static - * @return bool - */ - public static function is_current_session_authenticated() - { - return self::get_current_session_state() == 'authenticated'; - } - - /** - * Returns the state of the current session. Does not start a session. - * possible return values: - * 'authenticated' - session is valid and user is authenticated - * 'nobody' - session is valid, but user is not authenticated - * false - no valid session - * - * @static - * @return string|false - */ - public static function get_current_session_state() - { - - if (!is_null(self::$current_session_state)) { - return self::$current_session_state; - } - $state = false; - if (isset($GLOBALS['user']) && is_object($GLOBALS['user'])) { - $state = in_array($GLOBALS['user']->id, ['nobody', 'form']) ? 'nobody' : 'authenticated'; - } else { - $sid = $_COOKIE[__CLASS__]; - if ($sid) { - $session_vars = self::get_session_vars($sid); - $session_auth = $session_vars['auth']->auth; - if ($session_auth['uid'] && !in_array($session_auth['uid'], ['nobody', 'form'])) { - $state = 'authenticated'; - } else { - $state = in_array($session_auth['uid'], ['nobody', 'form']) ? 'nobody' : false; - } - } - } - return (self::$current_session_state = $state); - } - - /** - * returns a SessionDecoder object containing the session variables - * for the given session id - * - * @static - * @param string $sid a session id - * @return SessionDecoder - */ - public static function get_session_vars($sid) - { - $sess = $GLOBALS['sess'] ?? null; - if (!is_object($sess)) { - $sess = new self(); - } - $storage_class = $sess->that_class; - $storage = new $storage_class(); - $storage->ac_start(); - return new SessionDecoder($storage->ac_get_value($sid)); - } - - /** - * returns a random string token for XSRF prevention - * the string is stored in the session - * - * @static - * @return string - */ - public static function get_ticket() - { - if (!self::$studipticket) { - self::$studipticket = $_SESSION['last_ticket'] = md5(uniqid('studipticket', 1)); - } - return self::$studipticket; - } - - /** - * checks the given string token against the one stored - * in the session - * - * @static - * @param string $studipticket - * @return bool - */ - public static function check_ticket($studipticket) - { - $check = (isset($_SESSION['last_ticket']) && $_SESSION['last_ticket'] == $studipticket); - $_SESSION['last_ticket'] = null; - return $check; - } - - - /** - * - */ - function __construct() - { - if (Config::get()->CACHING_ENABLE && $GLOBALS['CACHE_IS_SESSION_STORAGE']) { - $this->that_class = 'CT_Cache'; - } - $this->cookie_path = $this->cookie_path ?: $GLOBALS['CANONICAL_RELATIVE_PATH_STUDIP']; - $this->cookie_secure = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on'; - $this->name(get_class($this)); - } - - /** - * Start a new session or recovers from an existing session - * - * @return boolean session_start() return value - * @access public - */ - function start() - { - $this->set_container(); - - session_set_cookie_params( - 0, - implode('/', array_map('rawurlencode', explode('/', $this->cookie_path))), - $this->cookie_domain, - $this->cookie_secure, - $this->cookie_httponly - ); - session_cache_limiter("nocache"); - //check for illegal cookiename - if ( - !isset($_COOKIE[$this->name]) - || mb_strlen($_COOKIE[$this->name]) !== 32 - || preg_match('/[^0-9a-f]+/', $_COOKIE[$this->name]) - ) { - do { - $new_id = md5(bin2hex(random_bytes(128))); - } while (!$this->that->ac_newid($new_id)); - - session_id($new_id); - } - - $ok = session_start(); - $this->id = session_id(); - return $ok; - } - - /** - * Sets or returns the name of the current session - * - * @param string If given, sets the session name - * @return string session_name() return value - * @access public - */ - function name($name = '') - { - if ($name) { - $this->name = $name; - $ok = session_name($name); - } else { - $ok = session_name(); - } - return $ok; - } - - /** - * ? - * - */ - function set_container() - { - - switch ($this->module) { - case "user" : - $name = $this->that_class; - $this->that = new $name; - $this->that->ac_start(); - // set custom session handlers - session_set_save_handler([$this, 'open'], - [$this, 'close'], - [$this, 'thaw'], - [$this, 'freeze'], - [$this, 'del'], - [$this, 'gc'] - ); - break; - - case "mm": - session_module_name('mm'); - break; - - case "files": - default: - if ($this->save_path) { - session_save_path($this->save_path); - } - session_module_name('files'); - break; - } - } - - /** - * @param array $keep_session_vars - */ - function regenerate_session_id($keep_session_vars = []) - { - $keep = []; - if (is_array($_SESSION)) { - foreach (array_keys($_SESSION) as $k) { - if (in_array($k, $keep_session_vars)) { - $keep[$k] = $_SESSION[$k]; - } - } - $_SESSION = []; - } - $this->delete(); - $this->start(); - foreach ($keep_session_vars as $k) { - $_SESSION[$k] = $keep[$k] ?? null; - } - } - - /** - * Delete the current session destroying all registered data. - * - * Note that it does more but the PHP 4 session_destroy it also - * throws away a cookie is there's one. - * - * @return boolean session_destroy return value - * @access public - */ - function delete() - { - $cookie_params = session_get_cookie_params(); - setCookie( - $this->name, - '', - 0, - implode('/', array_map('rawurlencode', explode('/', $cookie_params['path']))), - $cookie_params['domain'], - $cookie_params['secure'], - $cookie_params['httponly'] - ); - $_COOKIE[$this->name] = ""; - $_SESSION = []; - return session_destroy(); - } - - // the following functions used in session_set_save_handler - - /** - * Open callback - * - */ - function open() - { - return true; - } - - - /** - * Close callback - * - */ - function close() - { - return true; - } - - - /** - * Delete callback - */ - function del() - { - if ($this->module == 'user') { - $this->that->ac_delete($this->id, $this->name); - } - return true; - } - - - /** - * Write callback. - * - */ - function freeze($id = null, $sess_data = null) - { - if ($this->module == 'user') { - if (!isset($sess_data)) { - $sess_data = session_encode(); - } - $r = $this->that->ac_store($this->id, $this->name, $sess_data); - if (!$r) { - $this->that->ac_halt("Session: freeze() failed."); - } - } - return true; - } - - /** - * Read callback. - */ - function thaw() - { - if ($this->module == 'user') { - return $this->that->ac_get_value(session_id(), $this->name) ?: ''; - } - return ''; - } - - /** - * @return bool - */ - function gc() - { - if ($this->module === 'user') { - //bail out if cronjob activated and not called in cli context - if ( - Config::getInstance()->getValue('CRONJOBS_ENABLE') - && ($task = CronjobTask::findOneByClass(SessionGcJob::class)) - && count($task->schedules->findBy('active', 1)) - && PHP_SAPI !== 'cli' - ) { - return false; - } - if (empty($this->gc_time)) { - $this->gc_time = ini_get("session.gc_maxlifetime"); - } - return (bool)$this->that->ac_gc($this->gc_time, $this->name); - } - return true; - } -} diff --git a/lib/phplib/page_open.php b/lib/phplib/page_open.php deleted file mode 100644 index 699d50d7314b82ee1af183201cc9b190c245171f..0000000000000000000000000000000000000000 --- a/lib/phplib/page_open.php +++ /dev/null @@ -1,62 +0,0 @@ -<?php -/* -* Session Management for PHP3 -* -* Copyright (c) 1998-2000 NetUSE AG -* Boris Erdmann, Kristian Koehntopp -* -* -*/ - -function page_open($feature) { - - # enable sess and all dependent features. - if (isset($feature["sess"])) { - $GLOBALS['sess'] = new $feature["sess"]; - $GLOBALS['sess']->start(); - - # the auth feature depends on sess - if (isset($feature["auth"])) { - - if (isset($_SESSION['auth'])) { - $_SESSION['auth'] = $_SESSION['auth']->check_feature($feature["auth"]); - } else { - $_SESSION['auth'] = new $feature["auth"]; - } - $_SESSION['auth']->start(); - - $GLOBALS['auth'] =& $_SESSION['auth']; - - # the perm feature depends on auth and sess - if (isset($feature["perm"])) { - - if (!isset($GLOBALS['perm'])) { - $GLOBALS['perm'] = new $feature["perm"]; - } - } - - # the user feature depends on auth and sess - if (isset($feature["user"])) { - if (!isset($GLOBALS['user'])) { - $GLOBALS['user'] = new $feature["user"]($GLOBALS['auth']->auth["uid"]); - } - } - } - } -} - -function page_close() { - try { - NotificationCenter::postNotification('PageCloseWillExecute', null); - } catch (NotificationVetoException $e) { - return; - } - if (is_object($GLOBALS['sess'])) { - @session_write_close(); - } - - if (is_object($GLOBALS['user'])) { - $GLOBALS['user']->set_last_action(); - } - NotificationCenter::postNotification('PageCloseDidExecute', null); -} diff --git a/lib/phplib/prepend4.php b/lib/phplib/prepend4.php deleted file mode 100644 index abe332958246065c03bc534ec6e3e0d1bd38f2f4..0000000000000000000000000000000000000000 --- a/lib/phplib/prepend4.php +++ /dev/null @@ -1,78 +0,0 @@ -<!doctype html> -<html lang="de"> - <head> - <meta charset="utf-8"> - <title>Stud.IP-Konfigurationsfehler</title> - <script> - document.createElement("mark"); - </script> - <style> - body { - margin: auto; - width: 40em; - font-family: Futura, "Century Gothic", AppleGothic, sans-serif; - } - p { - line-height: 1.5em; - margin-top: 1.5em; - margin-bottom: 1.5em; - } - mark { - display: inline-block; - background: #ffff88; - border: 1px dotted #888; - padding: 0.5em; - } - code { - font-family: "Monaco", "Courier New", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", monospace; - background-color: #f8f8ff; - padding: 0.5em; - line-height: 1.5em; - } - p code { - padding: 0; - background: none; - } - </style> - </head> - <body> - <h1>Fehler in der PHP-Konfiguration Ihrer Stud.IP-Installation</h1> - <p> - Für den Betrieb von Stud.IP bis zur Version 2.0 war es erforderlich, - die Konfiguration des PHP-Moduls Ihres Webservers anzupassen, damit - folgende Zeile – evtl. leicht verändert – enthalten ist: - </p> - - <code> - auto_prepend_file = /usr/local/studip/lib/phplib/prepend4.php - </code> - - <p> - Diese Konfigurationsoption wird für Stud.IP ab der Version 2.0 nicht mehr - verwendet. - </p> - - <p> - <mark> - Entfernen Sie daher bitte die genannte Zeile aus Ihrer Konfiguration, - um diese Fehlermeldung zu verhindern. - </mark> - Typischerweise finden Sie diese in einer der folgenden Dateien: - <code>php.ini</code>, <code>httpd.conf</code> oder in einer - <code>.htaccess</code> Datei. - </p> - - <p> - Wenn Sie dafür weitere Hilfe benötigen, besuchen Sie bitte das - Forum im - <a href="http://develop.studip.de/studip/seminar_main.php?auswahl=a70c45ca747f0ab2ea4acbb17398d370">Developer-Board</a>. - </p> - - <p> - Vielen Dank, Ihre Stud.IP-CoreGroup - </p> - - </body> -</html> -<? -exit(); diff --git a/lib/plugins/core/StudIPPlugin.php b/lib/plugins/core/StudIPPlugin.php index cbcac648c136ddae7d7971c9001ebd6c2d53439d..a747119c8a14b51550648675c570a20498584752 100644 --- a/lib/plugins/core/StudIPPlugin.php +++ b/lib/plugins/core/StudIPPlugin.php @@ -184,20 +184,35 @@ abstract class StudIPPlugin } /** - * This method dispatches all actions. - * - * @param string part of the dispatch path that was not consumed + * This method formerly dispatches all actions. Left in place for + * compatibility + * @param string $unconsumed_path part of the dispatch path that was not consumed * * @return void */ public function perform($unconsumed_path) { + + } + + /** + * This method returns callable for slim app + * + * @param string $unconsumed_path part of the dispatch path that was not consumed + * + * @return Closure + * @throws \Trails\Exceptions\UnknownAction + */ + public function getRouteCallable(string $unconsumed_path): Closure + { + $this->perform($unconsumed_path); $args = explode('/', $unconsumed_path); $action = $args[0] !== '' ? array_shift($args).'_action' : 'show_action'; if (!method_exists($this, $action)) { try { - app(PluginDispatcher::class, ['plugin' => $this])->dispatch($unconsumed_path); + $dispatcher = app(PluginDispatcher::class, ['plugin' => $this]); + return $dispatcher->getRouteCallable($unconsumed_path); } catch (Trails\Exceptions\UnknownAction $exception) { if (count($args) > 0) { throw $exception; @@ -206,10 +221,16 @@ abstract class StudIPPlugin } } } else { - call_user_func_array([$this, $action], $args); + $that = $this; + return function ($request, $response, array $otherargs) use ($action, $args, $that) { + ob_start(); + call_user_func_array([$that, $action], $args); + $content = ob_get_contents(); + $response->getBody()->write($content); + return $response; + }; } } - /** * Callback function called after enabling a plugin. * The plugin's ID is transmitted for convenience. diff --git a/lib/plugins/engine/PluginManager.php b/lib/plugins/engine/PluginManager.php index 919e175f65ee20c675add6ecdf767a4b772a0209..6177e00e8b7dd499e64c9ae2bcbb00c1dd54fdeb 100644 --- a/lib/plugins/engine/PluginManager.php +++ b/lib/plugins/engine/PluginManager.php @@ -609,7 +609,7 @@ class PluginManager */ public function getPlugin ($class) { - $user = $GLOBALS['user']->id; + $user = $GLOBALS['user']->id ?? 'nobody' ; $plugin_info = $this->getPluginInfo($class); $plugin = null; diff --git a/lib/seminar_open.php b/lib/seminar_open.php deleted file mode 100644 index 4fb856fc7248e185f0e39e1e56b60ff7273458df..0000000000000000000000000000000000000000 --- a/lib/seminar_open.php +++ /dev/null @@ -1,266 +0,0 @@ -<?php -# Lifter002: TODO -# Lifter007: TODO -# Lifter003: TODO -# Lifter010: TODO -/* -seminar_open.php - Initialises a Stud.IP sesssion -Copyright (C) 2000 Stefan Suchi <suchi@data-quest.de> - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ - -/** - * @addtogroup notifications - * - * Logging in triggers a UserDidLogin notification. The user's ID is - * transmitted as subject of the notification. - */ - -//redirect the user where he want to go today.... -function startpage_redirect($page_code) { - switch ($page_code) { - case 1: - case 2: - $jump_page = "dispatch.php/my_courses"; - break; - case 3: - $jump_page = "dispatch.php/calendar/schedule"; - break; - case 4: - $jump_page = "dispatch.php/contact"; - break; - case 5: - $jump_page = "dispatch.php/calendar/calendar"; - break; - case 6: - // redirect to global blubberstream - // or no redirection if blubber isn't active - if (Config::get()->BLUBBER_GLOBAL_MESSENGER_ACTIVATE) { - $jump_page = "dispatch.php/blubber"; - } - break; - case 7: - $jump_page = "dispatch.php/contents/overview"; - break; - } - - page_close(); - header ('Location: ' . URLHelper::getURL($jump_page)); - exit; -} - -global $i_page, - $SessionSeminar, - $sess, $auth, $user, $perm, $_language_path; - -//get the name of the current page in $i_page -$i_page = basename($_SERVER['PHP_SELF']); - -//INITS -$seminar_open_redirected = false; -$user_did_login = false; - -// session init starts here -if (empty($_SESSION['SessionStart']) || $_SESSION['SessionStart'] == 0) { - $_SESSION['SessionStart'] = time(); - $_SESSION['object_cache'] = []; - - // try to get accepted languages from browser - if (!isset($_SESSION['_language'])) { - $_SESSION['_language'] = get_accepted_languages(); - } - if (!$_SESSION['_language']) { - $_SESSION['_language'] = Config::get()->DEFAULT_LANGUAGE; - } -} - -// user init starts here -if ($auth->is_authenticated() && is_object($user) && $user->id != "nobody") { - if ($_SESSION['SessionStart'] > UserConfig::get($user->id)->CURRENT_LOGIN_TIMESTAMP) { // just logged in - // store old CURRENT_LOGIN in LAST_LOGIN and set CURRENT_LOGIN to start of session - UserConfig::get($user->id)->store('LAST_LOGIN_TIMESTAMP', UserConfig::get($user->id)->CURRENT_LOGIN_TIMESTAMP); - UserConfig::get($user->id)->store('CURRENT_LOGIN_TIMESTAMP', $_SESSION['SessionStart']); - //find current semester and store it in $_SESSION['_default_sem'] - $current_sem = Semester::findDefault(); - $_SESSION['_default_sem'] = $current_sem->semester_id; - //redirect user to another page if he want to, redirect is deferred to allow plugins to catch the UserDidLogin notification - if (UserConfig::get($user->id)->PERSONAL_STARTPAGE > 0 && $i_page == "index.php" && !$perm->have_perm("root")) { - $seminar_open_redirected = TRUE; - } - if (isset($_SESSION['contrast'])) { - UserConfig::get($GLOBALS['user']->id)->store('USER_HIGH_CONTRAST', $_SESSION['contrast']); - unset($_SESSION['contrast']); - } - // store last language click - if (!empty($_SESSION['forced_language'])) { - User::findCurrent()->preferred_language = $_SESSION['forced_language']; - User::findCurrent()->store(); - $_SESSION['_language'] = $_SESSION['forced_language']; - } - $_SESSION['forced_language'] = null; - $user_did_login = true; - } - - TwoFactorAuth::get()->secureSession(); -} - -if (!empty($_SESSION['contrast']) || UserConfig::get($GLOBALS['user']->id)->USER_HIGH_CONTRAST) { - PageLayout::addStylesheet('accessibility.css'); -} - -// init of output via I18N -$_language_path = init_i18n($_SESSION['_language']); -//force reload of config to get translated data -include $GLOBALS['STUDIP_BASE_PATH'] . '/config/config.inc.php'; - -// Try to select the course or institute given by the parameter 'cid' -// in the current request. - -$course_id = (Request::int('cancel_login') && (!is_object($user) || $user->id === 'nobody')) - ? null - : Request::option('cid'); - -// Select the current course or institute if we got one from 'cid' or session. -// This also binds Context::getId() -// to the URL parameter 'cid' for all generated links. -if (isset($course_id)) { - Context::set($course_id); - unset($course_id); -} - -if (Request::int('disable_plugins') !== null && ($user->id === 'nobody' || $perm->have_perm('root'))) { - // deactivate non-core plugins - PluginManager::getInstance()->setPluginsDisabled(Request::int('disable_plugins')); -} - -// load the default set of plugins -PluginEngine::loadPlugins(); - -// add navigation item for profile: add modules -if (Navigation::hasItem('/profile/edit')) { - $plus_nav = new Navigation(_('Mehr …'), 'dispatch.php/profilemodules/index'); - $plus_nav->setDescription(_("Mehr Stud.IP-Funktionen für Ihr Profil")); - Navigation::addItem('/profile/modules', $plus_nav); -} - -if ($user_did_login) { - if (isset($_SESSION[StudipAuthOAuth2::class]['redirect'])) { - $redirect = $_SESSION[StudipAuthOAuth2::class]['redirect']; - unset($_SESSION[StudipAuthOAuth2::class]); - - page_close(); - header('Location: ' . $redirect); - die; - } - - NotificationCenter::postNotification('UserDidLogin', $user->id); -} - -if (!Request::isXhr() && $perm->have_perm('root')) { - if (!isset($_SESSION['migration-check']) || $_SESSION['migration-check']['timestamp'] < time() - 5 * 60) { - $migrator = new Migrator( - "{$GLOBALS['STUDIP_BASE_PATH']}/db/migrations", - new DBSchemaVersion('studip') - ); - - $_SESSION['migration-check'] = [ - 'disabled' => $_SESSION['migration-check']['disabled'] ?? false, - 'timestamp' => time(), - 'count' => $migrator->pendingMigrations() - ]; - } - - if (Request::option('stop-migration-nag')) { - $_SESSION['migration-check']['disabled'] = true; - } - - if (empty($_SESSION['migration-check']['disabled']) - && $_SESSION['migration-check']['count'] > 0 - ) { - $info = sprintf( - _('Es gibt %u noch nicht ausgeführte Migration(en).'), - $_SESSION['migration-check']['count'] - ); - - $message = MessageBox::info($info,[ - sprintf( - _('Zur %sMigrationsseite%s'), - '<a class="link-intern" href="' . URLHelper::getLink('web_migrate.php') . '">', - '</a>' - ), - sprintf( - '<small><a href="%s">%s</a></small>', - URLHelper::getLink('', ['stop-migration-nag' => true]), - _('Diese Nachricht bis zum nächsten Login nicht mehr anzeigen') - ) - ] - ); - PageLayout::postMessage($message, 'migration-info'); - } -} - -if ( - $GLOBALS['perm']->have_perm('root') - && Config::get()->MIGRATION_START_VERSION - && Config::get()->MIGRATION_START_VERSION < StudipVersion::getStudipVersion(true) - && !Config::get()->UPDATE_NEWS_SEEN -) { - $message = MessageBox::info( - _('Sie haben ein Stud.IP-Update durchgeführt.'), - [ - sprintf( - _('Zu den %sRelease-Notes%s'), - '<a class="link-intern" href="' . URLHelper::getLink('dispatch.php/root_assistant') . '" data-dialog>', - '</a>' - ), - ] - ); - PageLayout::postMessage($message, 'release-notes'); -} - -if ($seminar_open_redirected) { - startpage_redirect(UserConfig::get($user->id)->PERSONAL_STARTPAGE); -} - -// Show terms on first login -if (is_object($GLOBALS['user']) - && $GLOBALS['user']->needsToAcceptTerms() - && !match_route('dispatch.php/terms') - && !match_route('dispatch.php/siteinfo/*')) -{ - if (!Request::isXhr()) { - header('Location: ' . URLHelper::getURL('dispatch.php/terms', ['return_to' => $_SERVER['REQUEST_URI'], 'redirect_token' => Token::create(600)], true)); - } else { - throw new Trails\Exception(400); - } - page_close(); - die; -} - -if ( - Config::get()->USER_VISIBILITY_CHECK - && is_object($GLOBALS['user']) - && $GLOBALS['user']->id !== 'nobody' - && !( - Config::get()->DOZENT_ALWAYS_VISIBLE - && $perm->get_perm() === 'dozent' - ) - && !match_route('dispatch.php/siteinfo/*') -) { - require_once('lib/user_visible.inc.php'); - first_decision($GLOBALS['user']->id); -} diff --git a/lib/session/CacheSessionHandler.php b/lib/session/CacheSessionHandler.php new file mode 100644 index 0000000000000000000000000000000000000000..c416ceb348e152586a50e3ba8242dd19186dd31c --- /dev/null +++ b/lib/session/CacheSessionHandler.php @@ -0,0 +1,100 @@ +<?php +/** + * Session handler for using Stud.IP Cache as session storage + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * @author André Noack <noack@data-quest.de> + */ +namespace Studip\Session; + +class CacheSessionHandler implements \SessionHandlerInterface, \SessionIdInterface, \SessionUpdateTimestampHandlerInterface +{ + + const CACHE_KEY_PREFIX = 'session_data'; + + private $session_lifetime = 7200; + + private $cache; + + public function __construct($session_lifetime = null) + { + if ($session_lifetime) { + $this->session_lifetime = $session_lifetime; + } + } + + /** + * @inheritDoc + */ + public function close(): bool + { + return true; + } + + /** + * @inheritDoc + */ + public function destroy($id): bool + { + $cache_key = self::CACHE_KEY_PREFIX . '/' . $id; + $this->cache->expire($cache_key); + return true; + } + + /** + * @inheritDoc + */ + public function gc($max_lifetime): int|false + { + return false; + } + + /** + * @inheritDoc + */ + public function open($path, $name): bool + { + $this->cache = \Studip\Cache\Factory::getCache(); + return true; + } + + /** + * @inheritDoc + */ + public function read($id): string|false + { + $cache_key = self::CACHE_KEY_PREFIX . '/' . $id; + return $this->cache->read($cache_key); + } + + /** + * @inheritDoc + */ + public function write($id, $data): bool + { + $cache_key = self::CACHE_KEY_PREFIX . '/' . $id; + return (bool)$this->cache->write($cache_key, $data, $this->session_lifetime); + } + + public function create_sid(): string + { + do { + $new_id = md5(bin2hex(random_bytes(128))); + } while (!$this->read($new_id)); + return $new_id; + } + + public function updateTimestamp(string $id, string $data): bool + { + return $this->write($id, $data); + } + + public function validateId(string $id): bool + { + return (bool)$this->read($id); + } +} diff --git a/lib/session/DbSessionHandler.php b/lib/session/DbSessionHandler.php new file mode 100644 index 0000000000000000000000000000000000000000..05a31a486e6c705b1f06388722662dd58942b73b --- /dev/null +++ b/lib/session/DbSessionHandler.php @@ -0,0 +1,114 @@ +<?php +/** + * Session handler for using Stud.IP database as session storage + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * @author André Noack <noack@data-quest.de> + */ + +namespace Studip\Session; +use \DBManager, \Config, \CronjobTask; + +class DbSessionHandler implements \SessionHandlerInterface, \SessionIdInterface, \SessionUpdateTimestampHandlerInterface +{ + + private $exists; + + /** + * @inheritDoc + */ + public function close(): bool + { + return true; + } + + /** + * @inheritDoc + */ + public function destroy($id): bool + { + return (bool)DBManager::get()->execute("DELETE FROM session_data WHERE sid = ? LIMIT 1", [$id]); + } + + /** + * @inheritDoc + */ + public function gc($max_lifetime): false|int + { + //bail out if cronjob activated and not called in cli context + if (Config::getInstance()->getValue('CRONJOBS_ENABLE') + && ($task = array_pop(CronjobTask::findByClass('SessionGcJob'))) + && count($task->schedules->findBy('active', 1)) + && PHP_SAPI !== 'cli' + ) { + return false; + } + return DBManager::get()->execute("DELETE FROM session_data WHERE changed < FROM_UNIXTIME(?) ", [time() - $max_lifetime]); + } + + /** + * @inheritDoc + */ + public function open($path, $name): bool + { + return true; + } + + /** + * @inheritDoc + */ + #[\ReturnTypeWillChange] + public function read($id) + { + $str = DBManager::get()->fetchColumn("SELECT val FROM session_data where sid = ?", [$id]); + if ($str) { + $this->exists = $id; + } + return (string)$str; + } + + /** + * @inheritDoc + */ + public function write($id, $data): bool + { + $db = DBManager::get(); + if ($this->exists === $id) { + $stmt = $db->prepare("UPDATE session_data SET val = ? WHERE sid = ?"); + } else { + $stmt = $db->prepare("REPLACE INTO session_data ( val, sid ) VALUES (?, ?)"); + } + return (bool) $stmt->execute([$data, $id]); + } + + public function exists($id) + { + return (bool)DBManager::get()->fetchColumn("SELECT 1 FROM session_data where sid = ?", [$id]); + } + + public function create_sid(): string + { + do { + $new_id = md5(bin2hex(random_bytes(128))); + } while ($this->exists($new_id)); + $this->exists = null; + return $new_id; + } + + public function updateTimestamp(string $id, string $data): bool + { + DBManager::get()->execute("UPDATE session_data SET changed = CURRENT_TIMESTAMP() WHERE sid = ?", [$id]); + return true; + } + + public function validateId(string $id): bool + { + return (bool)$this->exists($id); + } + + +} diff --git a/lib/session/Manager.php b/lib/session/Manager.php new file mode 100644 index 0000000000000000000000000000000000000000..ea95dbea469357ff61afee8ad246bd520fc396bc --- /dev/null +++ b/lib/session/Manager.php @@ -0,0 +1,229 @@ +<?php +/** + * Session manager for Stud.IP + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * @author André Noack <noack@data-quest.de> + */ +namespace Studip\Session; + + +class Manager +{ + /** + * @var \SessionHandlerInterface + */ + protected \SessionHandlerInterface $handler; + /** + * @var array + */ + protected array $options = [ + 'name' => 'Seminar_Session', + 'lifetime' => 7200, + 'path' => null, + 'domain' => null, + 'secure' => false, + 'httponly' => true, + 'samesite' => 'Lax', + 'cache_limiter' => 'nocache' + ]; + /** + * @var null + */ + protected $current_session_state = null; + + + /** + * @param \SessionHandlerInterface $session_handler + * @param array $session_options + */ + public function __construct(\SessionHandlerInterface $session_handler, array $session_options = []) + { + $this->handler = $session_handler; + $keys = array_keys($this->options); + foreach ($keys as $key) { + if (array_key_exists($key, $session_options)) { + $this->options[$key] = $session_options[$key]; + if ($key === 'path') { + $this->options[$key] = implode('/', array_map('rawurlencode', explode('/', $this->options[$key] ))); + } + } + } + } + + /** + * @return void + */ + public function start(): void + { + if (!$this->isStarted()) { + + ini_set('session.use_strict_mode', 1); + $current = session_get_cookie_params(); + + $lifetime = (int)($this->options['lifetime'] ?: $current['lifetime']); + $path = $this->options['path'] ?: $current['path']; + $domain = $this->options['domain'] ?: $current['domain']; + $samesite = $this->options['samesite'] ?: $current['samesite']; + $secure = (bool)$this->options['secure']; + $httponly = (bool)$this->options['httponly']; + + session_set_cookie_params(compact('lifetime', 'path', 'domain', 'secure', 'samesite', 'httponly')); + session_name($this->options['name']); + session_cache_limiter('nocache'); + session_set_save_handler($this->handler, true); + + session_start(); + } + } + + /** + * @return bool + */ + public function isStarted(): bool + { + return session_status() === PHP_SESSION_ACTIVE; + } + + /** + * @param array $keep_session_vars + * @return void + */ + public function regenerateId(array $keep_session_vars = []): void + { + if (!$this->isStarted()) { + return; + } + + $keep = []; + if (is_array($_SESSION)) { + foreach (array_keys($_SESSION) as $k) { + if (in_array($k, $keep_session_vars)) { + $keep[$k] = $_SESSION[$k]; + } + } + $_SESSION = []; + } + session_regenerate_id(true); + + foreach ($keep_session_vars as $k) { + $_SESSION[$k] = $keep[$k] ?? null; + } + } + + /** + * @return string + */ + public function getName(): string + { + return $this->options['name']; + } + + /** + * @return void + */ + public function destroy(): void + { + if (!$this->isStarted()) { + return; + } + + if (ini_get('session.use_cookies')) { + $params = session_get_cookie_params(); + setcookie( + $this->getName(), + '', + time() - 42000, + $params['path'], + $params['domain'], + $params['secure'], + $params['httponly'] + ); + } + $_COOKIE[$this->getName()] = ''; + session_unset(); + session_destroy(); + } + + /** + * @return void + */ + public function save() : void + { + session_write_close(); + } + + /** + * Returns true, if the current session is valid and belongs to an + * authenticated user. Does not start a session. + * + * @static + * @return bool + */ + public function isCurrentSessionAuthenticated(): bool + { + return self::getCurrentSessionState() === 'authenticated'; + } + + /** + * Returns the state of the current session. Does not start a session. + * possible return values: + * 'authenticated' - session is valid and user is authenticated + * 'nobody' - session is valid, but user is not authenticated + * false - no valid session + * + * @static + * @return string|false + */ + public function getCurrentSessionState(): false|string|null + { + + if (!is_null($this->current_session_state)) { + return $this->current_session_state; + } + $state = false; + if (isset($GLOBALS['user']) && is_object($GLOBALS['user'])) { + $state = in_array($GLOBALS['user']->id, ['nobody', 'form']) ? 'nobody' : 'authenticated'; + } else { + $sid = $_COOKIE[$this->getName()]; + if ($sid) { + $session_vars = $this->getSessionVars($sid); + $session_auth = $session_vars['auth']; + if ($session_auth['uid'] && !in_array($session_auth['uid'], ['nobody', 'form'])) { + $state = 'authenticated'; + } else { + $state = in_array($session_auth['uid'], ['nobody', 'form']) ? 'nobody' : false; + } + } + } + return ($this->current_session_state = $state); + } + + /** + * returns a SessionDecoder object containing the session variables + * for the given session id + * + * @static + * @param string $sid a session id + * @return \SessionDecoder + */ + public function getSessionVars($sid): \SessionDecoder + { + $data = $this->handler->read($sid); + return new \SessionDecoder($data); + } + + /** + * force garbage collect + * + * @return void + */ + public function doGarbageCollect(): void + { + $this->handler->gc($this->options['lifetime']); + } +} diff --git a/lib/user_visible.inc.php b/lib/user_visible.inc.php index 5de2a073664568a2a9798aaa8c996876163c24df..3bfb7d9b0924e12d0062c279a7eb84b38e1d529e 100644 --- a/lib/user_visible.inc.php +++ b/lib/user_visible.inc.php @@ -255,9 +255,7 @@ function first_decision($userid) { $template = $GLOBALS['template_factory']->open("../locale/$user_language/LC_HELP/visibility_decision.php"); $template->set_layout('layouts/base.php'); - echo $template->render(); - page_close(); - die; + return $template->render(); } diff --git a/locale/de/LC_HELP/visibility_decision.php b/locale/de/LC_HELP/visibility_decision.php index 918370ec77105e7cf97ae35680135f18e86a2fb3..fb0db7e03b0bdf9c32376967e06b4b5596ff34ce 100644 --- a/locale/de/LC_HELP/visibility_decision.php +++ b/locale/de/LC_HELP/visibility_decision.php @@ -27,7 +27,7 @@ </ul> </td> </tr> - + <tr> <td style="background:#ddffdd; border:1px solid #d0d7e3;" valign="top"> <p><b>Wenn Sie sichtbar sind, dann</b></p> @@ -67,7 +67,7 @@ <tr> <td colspan="3"> <p> - Weitere Informationen entnehme Sie bitte den + Weitere Informationen entnehme Sie bitte den <a href="<?=URLHelper::getURL(Config::get()->PRIVACY_URL, ['cancel_login' => 1], true) ?>" target="_bank">Datenschutzerklärungen</a>. </p> </td> diff --git a/public/activate_email.php b/public/activate_email.php deleted file mode 100644 index 25e70f31b4a9939e55d20f18ada85fb41cae052f..0000000000000000000000000000000000000000 --- a/public/activate_email.php +++ /dev/null @@ -1,124 +0,0 @@ -<?php -# Lifter007: TODO -# Lifter003: TODO -# Lifter010: TODO - -$_GET['cancel_login'] = '1'; - -require '../lib/bootstrap.php'; - -use Studip\Button, Studip\LinkButton; - -ob_start(); - -page_open(['sess' => 'Seminar_Session', 'auth' => 'Seminar_Default_Auth', 'perm' => 'Seminar_Perm', 'user' => 'Seminar_User']); - -function head($headline, $red=False) { - echo sprintf('<h1>%s</h1>', $headline); -} - -function footer() { -} - -function reenter_mail() { - echo '<br>'; - echo '<form action="' . URLHelper::getLink() . '" method="post" class="default">'; - echo '<fieldset>'; - echo '<legend>'._('Sollten Sie keine E-Mail erhalten haben, können Sie sich einen neuen Aktivierungsschlüssel zuschicken lassen. Geben Sie dazu Ihre gewünschte E-Mail-Adresse unten an') . '</legend>' - . CSRFProtection::tokenTag() - .'<input type="hidden" name="uid" value="'. htmlReady(Request::option('uid')) .'">' - .'<label>' . _('E-Mail') - .'<input type="email" name="email1" required>' - .'</label>' - .'<label>' . _('Wiederholung') - .'<input type="email" name="email2" required>' - .'</label>'; - echo '</fieldset>'; - echo '<footer>' . Button::createAccept() . '</footer>'; - echo '</form>'; -} - -function mail_explain() { - echo '<form action="' . URLHelper::getLink() . '" method="post" class="default">'; - echo '<fieldset>'; - echo '<legend>' . _('Sie haben Ihre E-Mail-Adresse geändert. - Um diese frei zu schalten müssen Sie den Ihnen an Ihre neue Adresse zugeschickten Aktivierungs Schlüssel im unten stehenden Eingabefeld eintragen.') . '</legend>'; - echo CSRFProtection::tokenTag(); - echo '<label>' . _('Aktivierungs Schlüssel') - .'<input type="text" name="key"><input name="uid" type="hidden" value="'.htmlReady(Request::option('uid')).'">'; - echo '</fieldset>'; - echo '<footer>' . Button::createAccept() . '</footer>'; - echo '</form>'; - -} - -if(!Request::option('uid')) - header("Location: index.php"); - -URLHelper::addLinkParam('cancel_login', 1); - -// set up user session -include 'lib/seminar_open.php'; - -// display header -PageLayout::setTitle(_('E-Mail Aktivierung')); - -$uid = Request::option('uid'); -if(Request::get('key') !== null) { - - $db = DBManager::get(); - $sth = $db->prepare("SELECT validation_key FROM auth_user_md5 WHERE user_id=?"); - $sth->execute([$uid]); - $result = $sth->fetch(); - $key = $result['validation_key']; - - if(Request::get('key') == $key) { - $sth = $db->prepare("UPDATE auth_user_md5 SET validation_key='' WHERE user_id=?"); - $sth->execute([$uid]); - unset($_SESSION['semi_logged_in']); - head(PageLayout::getTitle()); - PageLayout::postSuccess(_('Ihre E-Mail-Adresse wurde erfolgreich geändert.')); - printf(' <a href="' . URLHelper::getLink('index.php') . '">%s</a>', _('Zum Login')); - } else if ($key == '') { - head(PageLayout::getTitle()); - PageLayout::postInfo(_('Ihre E-Mail-Adresse ist bereits geändert.')); - printf(' <a href="' . URLHelper::getLink('index.php') . '">%s</a>', _('Zum Login')); - } else { - if (Request::get('key')) { - PageLayout::postError(_("Falscher Bestätigungscode.")); - } - head(PageLayout::getTitle()); - mail_explain(); - if($_SESSION['semi_logged_in'] == Request::option('uid')) { - reenter_mail(); - } else { - printf(_('Sie können sich %seinloggen%s und sich den Bestätigungscode neu oder an eine andere E-Mail-Adresse schicken lassen.'), - '<a href="' . URLHelper::getLink('index.php?again=yes') . '">', '</a>'); - } - } - -// checking semi_logged_in is important to avoid abuse -} else if(Request::get('email1') && Request::get('email2') && $_SESSION['semi_logged_in'] == Request::option('uid')) { - if(Request::get('email1') == Request::get('email2')) { - // change mail - $tmp_user = User::find(Request::option('uid')); - if($tmp_user && $tmp_user->changeEmail(Request::get('email1'), true)) { - $_SESSION['semi_logged_in'] = False; - } - - } else { - PageLayout::postError(_('Die eingegebenen E-Mail-Adressen stimmen nicht überein. Bitte überprüfen Sie Ihre Eingabe.')); - } - mail_explain(); - reenter_mail(); -} else { - // this never happens unless someone manipulates urls (or the presented link within the mail is broken) - head(PageLayout::getTitle()); - mail_explain(); - reenter_mail(); -} - -$template = $GLOBALS['template_factory']->open('layouts/base.php'); -$template->content_for_layout = ob_get_clean(); -echo $template->render(); -page_close(); diff --git a/public/datenschutz.php b/public/datenschutz.php deleted file mode 100644 index 0eb134f5c99da123f80b94164375868a560e6756..0000000000000000000000000000000000000000 --- a/public/datenschutz.php +++ /dev/null @@ -1,37 +0,0 @@ -<?php -/** - * datenschutz.php - * - * privacy guidelines for Stud.IP - * - * PHP version 5 - * - * @author Elmar Ludwig - * @author Michael Riehemann <michael.riehemann@uni-oldenburg.de> - * @copyright 2009 Stud.IP - * @license http://www.gnu.org/licenses/gpl.html GPL Licence 3 - * @package studip_core - * @access public - */ - -require '../lib/bootstrap.php'; - -page_open([ - 'sess' => 'Seminar_Session', - 'auth' => 'Seminar_Default_Auth', - 'perm' => 'Seminar_Perm', - 'user' => 'Seminar_User' -]); - -// set up user session -include 'lib/seminar_open.php'; - -// this page must be accessible during visibility decision -Config::get()->USER_VISIBILITY_CHECK = false; - -PageLayout::setTitle(_('Erläuterungen zum Datenschutz')); - -$template = $template_factory->open('privacy'); -$template->set_layout('layouts/base.php'); - -echo $template->render(); diff --git a/public/dispatch.php b/public/dispatch.php index 77c593310f9d94edcab0c568fe5eb97583b63b2f..8bc346df8be84175455cbe60ba64585149ae4195 100644 --- a/public/dispatch.php +++ b/public/dispatch.php @@ -1,8 +1,6 @@ <?php -# Lifter002: TODO -# Lifter007: TODO -# Lifter003: TODO -# Lifter010: TODO +use Slim\App; +use Slim\Factory\AppFactory; /* * index.php - <short-description> @@ -21,5 +19,17 @@ require '../lib/bootstrap.php'; // prepare environment URLHelper::setBaseUrl($GLOBALS['ABSOLUTE_URI_STUDIP']); -$dispatcher = app(\Trails\Dispatcher::class); -$dispatcher->dispatch(Request::pathInfo()); +// Build PHP_DI Container +$container = app(); + +// Instantiate the app +AppFactory::setContainer($container); +$app = AppFactory::create(); +$container->set(App::class, $app); +$app->setBasePath($GLOBALS['CANONICAL_RELATIVE_PATH_STUDIP'] . 'dispatch.php'); + +$studip_dispatcher = app(\Trails\Dispatcher::class); +$route_callable = $studip_dispatcher->getRouteCallable(Request::pathInfo()); +$app->any(Request::pathInfo(), $route_callable); +NotificationCenter::postNotification('SLIM_BEFORE_RUN', $app); +$app->run(); diff --git a/public/email_validation.php b/public/email_validation.php deleted file mode 100644 index f877aee0afc00c7b57de97c07bbfceff7b51616a..0000000000000000000000000000000000000000 --- a/public/email_validation.php +++ /dev/null @@ -1,108 +0,0 @@ -<?php -# Lifter002: TEST -# Lifter003: TEST -# Lifter007: TEST -# Lifter010: DONE - not applicable -/* -email_validation.php - Hochstufung eines user auf Status autor, wenn erfolgreich per Mail zurueckgemeldet -Copyright (C) 2001 Stefan Suchi <suchi@gmx.de> - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -require '../lib/bootstrap.php'; - -page_open([ - 'sess' => 'Seminar_Session', - 'auth' => 'Seminar_Auth', - 'perm' => 'Seminar_Perm', - 'user' => 'Seminar_User' -]); -$auth->login_if($auth->auth['uid'] == 'nobody'); -$perm->check('user'); -// nobody hat hier nix zu suchen... - -include 'lib/seminar_open.php'; // initialise Stud.IP-Session - -// hier wird noch mal berechnet, welches secret in der Bestaetigungsmail uebergeben wurde -$secret = Request::option('secret'); -PageLayout::setHelpKeyword('Basis.AnmeldungMail'); -PageLayout::setTitle(_('Bestätigung der E-Mail-Adresse')); - -//user bereits vorhanden -if ($perm->have_perm('autor')) { - $info = sprintf(_('Sie haben schon den Status <b>%s</b> im System. - Eine Aktivierung des Accounts ist nicht mehr nötig, um Schreibrechte zu bekommen'), $auth->auth['perm']); - $details = []; - $details[] = sprintf('<a href="%s">%s</a>', URLHelper::getLink('index.php'), _('zurück zur Startseite')); - $message = MessageBox::info($info, $details); -} - -// So, wer bis hier hin gekommen ist gehoert zur Zielgruppe... -// Volltrottel (oder abuse) -else if (empty($secret)) { - $message = MessageBox::error(_('Sie müssen den vollständigen Link aus der Bestätigungsmail in die Adresszeile Ihres Browsers kopieren.')); -} - -// abuse (oder Volltrottel) -else if (!Seminar_Register_Auth::validateSecret($secret, $user->id)) { - $error = _('Der übergebene <em>Secret-Code</em> ist nicht korrekt.'); - $details = []; - $details[] = _('Sie müssen unter dem Benutzernamen eingeloggt sein, für den Sie die Bestätigungsmail erhalten haben.'); - $details[] = _('Und Sie müssen den vollständigen Link aus der Bestätigungsmail in die Adresszeile Ihres Browsers kopieren.'); - $message = MessageBox::error($error, $details); - - // Mail an abuse - $REMOTE_ADDR=getenv("REMOTE_ADDR"); - $Zeit=date("H:i:s, d.m.Y",time()); - $username = $auth->auth["uname"]; - StudipMail::sendAbuseMessage("Validation", "Secret falsch\n\nUser: $username\n\nIP: $REMOTE_ADDR\nZeit: $Zeit\n"); -} - -// alles paletti, Status ändern -else { - $studip_user = User::findCurrent(); - $studip_user->perms = 'autor'; - if (!$studip_user->store()) { - $error = _('Fehler! Bitte wenden Sie sich an den Systemadministrator.'); - $details = [$query]; - $message = MessageBox::error($error, $details); - } else { - $success = _('Ihr Status wurde erfolgreich auf <em>autor</em> gesetzt.<br> - Damit dürfen Sie in den meisten Veranstaltungen schreiben, für die Sie sich anmelden.'); - $details = []; - $details[] = _('Einige Veranstaltungen erfordern allerdings bei der Anmeldung die Eingabe eines Passwortes. - Dieses Passwort erfahren Sie von den Lehrenden der Veranstaltung.'); - $message = MessageBox::success($success, $details); - - // Auto-Inserts - AutoInsert::instance()->saveUser($user->id, "autor"); - - $auth->logout(); // einen Logout durchführen, um erneuten Login zu erzwingen - - $info = sprintf(_('Die Statusänderung wird erst nach einem erneuten %sLogin%s wirksam!<br> - Deshalb wurden Sie jetzt automatisch ausgeloggt.'), - '<a href="index.php?again=yes"><em>', - '</em></a>'); - $message .= MessageBox::info($info); - } -} - -$template = $GLOBALS['template_factory']->open('email-validation'); -$template->set_layout($GLOBALS['template_factory']->open('layouts/base.php')); -$template->message = $message; -echo $template->render(); - -page_close(); diff --git a/public/index.php b/public/index.php index abba9015187173857f3f442fd5e69e99c459983e..19772338f24fcf38f72c85e0946da61b29f4865d 100644 --- a/public/index.php +++ b/public/index.php @@ -19,12 +19,5 @@ require '../lib/bootstrap.php'; -page_open(['sess' => 'Seminar_Session', 'auth' => 'Seminar_Default_Auth', 'perm' => 'Seminar_Perm', 'user' => 'Seminar_User']); +header('Location: ' . URLHelper::getURL('dispatch.php/start')); -$auth->login_if($user->id === 'nobody'); -include 'lib/seminar_open.php'; // initialise Stud.IP-Session - -// if new start page is in use, redirect there (if logged in) -if ($auth->is_authenticated() && $user->id != 'nobody') { - header('Location: ' . URLHelper::getURL('dispatch.php/start')); -} diff --git a/public/jsonapi.php b/public/jsonapi.php index 4b2ba4bfef3676f1efb9f90398568d8b15a7f2a1..8d69b5108e2e716a4edf53e7e39135f3c0ed9366 100644 --- a/public/jsonapi.php +++ b/public/jsonapi.php @@ -9,13 +9,6 @@ require '../lib/bootstrap.php'; // Set base url for URLHelper class URLHelper::setBaseUrl($GLOBALS['CANONICAL_RELATIVE_PATH_STUDIP']); -page_open([ - 'sess' => 'Seminar_Session', - 'auth' => 'Seminar_Default_Auth', - 'perm' => 'Seminar_Perm', - 'user' => 'Seminar_User', -]); - // Instantiate the app $container = app(); AppFactory::setContainer($container); @@ -29,6 +22,11 @@ $app->setBasePath($GLOBALS['CANONICAL_RELATIVE_PATH_STUDIP'] . 'jsonapi.php'); $middleware = require 'lib/classes/JsonApi/middleware.php'; $middleware($app); +//register stud.ip session/auth middleware +$app->add(app(Studip\Middleware\AuthenticationMiddleware::class)); +auth()->setNobody(true); +$app->add(app(Studip\Middleware\SessionMiddleware::class)); + // Register routes $routes = require 'lib/classes/JsonApi/routes.php'; $routes($app); diff --git a/public/logout.php b/public/logout.php index 6f941949c4cc5cf585d92c726484a0d6859f94cc..aee2701eea893560a34fcd1247d455a2daf4d7ca 100644 --- a/public/logout.php +++ b/public/logout.php @@ -25,69 +25,4 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. require '../lib/bootstrap.php'; -page_open(["sess" => "Seminar_Session", "auth" => "Seminar_Default_Auth", "perm" => "Seminar_Perm", "user" => "Seminar_User"]); - -require_once 'lib/messaging.inc.php'; - -// Redirect to index page if request is not a post request or logout ticket is -// missing -if ( - !Request::isPost() - && !( - isset($_SESSION['logout_ticket']) - && check_ticket($_SESSION['logout_ticket']) - ) -) { - header('Location: ' . URLHelper::getURL('index.php')); - page_close(); - die; -} - -//nur wenn wir angemeldet sind sollten wir dies tun! -if ($auth->auth['uid'] !== 'nobody') { - $my_messaging_settings = $GLOBALS['user']->cfg->MESSAGING_SETTINGS; - - //Wenn Option dafuer gewaehlt, alle ungelsesenen Nachrichten als gelesen speichern - if ($my_messaging_settings["logout_markreaded"]) { - Message::markAllAs(); - } - - $logout_user = $user->id; - $_language = $_SESSION['_language']; - $contrast = UserConfig::get($GLOBALS['user']->id)->USER_HIGH_CONTRAST; - - // Get auth plugin of user before logging out since the $auth object will - // be modified by the logout - $auth_plugin = StudipAuthAbstract::getInstance($auth->auth['auth_plugin']); - - //Logout aus dem Sessionmanagement - $auth->logout(); - $sess->delete(); - - page_close(); - - //Session changed zuruecksetzen - $timeout=(time()-(15 * 60)); - $user->set_last_action($timeout); - - $sess->start(); - $_SESSION['_language'] = $_language; - if ($contrast) { - $_SESSION['contrast'] = $contrast; - } - - PageLayout::postSuccess( - _('Sie sind nun aus dem System abgemeldet.'), - array_filter([$GLOBALS['UNI_LOGOUT_ADD']]) - ); - - // Perform logout from auth plugin (if possible) - if ($auth_plugin instanceof StudipAuthSSO) { - $auth_plugin->logout(); - } -} else { - $sess->delete(); - page_close(); -} - -header('Location: ' . URLHelper::getURL('index.php?logout=1')); +header('Location: ' . URLHelper::getURL('dispatch.php/logout')); diff --git a/public/plugins.php b/public/plugins.php index 99373a053fd58691eb6e4e2bf5dff09b3f1ba18b..176ccfa98f24ca14176ecffaa1022c054bfecc90 100644 --- a/public/plugins.php +++ b/public/plugins.php @@ -1,6 +1,4 @@ <?php -# Lifter007: TEST - /* * Copyright (C) 2007 - Marcus Lunzenauer <mlunzena@uos.de> * @@ -10,61 +8,74 @@ * the License, or (at your option) any later version. */ +use Psr\Http\Message\ResponseFactoryInterface; +use Psr\Http\Message\ServerRequestInterface; +use Slim\App; +use Slim\Factory\AppFactory; +use Psr\Http\Server\RequestHandlerInterface; + require '../lib/bootstrap.php'; -// set base url for URLHelper class -URLHelper::setBaseUrl($GLOBALS['CANONICAL_RELATIVE_PATH_STUDIP']); +// prepare environment +URLHelper::setBaseUrl($GLOBALS['ABSOLUTE_URI_STUDIP']); -// initialize Stud.IP-Session -page_open([ - 'sess' => 'Seminar_Session', - 'auth' => 'Seminar_Default_Auth', - 'perm' => 'Seminar_Perm', - 'user' => 'Seminar_User', -]); +// Build PHP_DI Container +$container = app(); -try { - require_once 'lib/seminar_open.php'; +// Instantiate the app +AppFactory::setContainer($container); +$app = AppFactory::create(); +$container->set(App::class, $app); +$app->setBasePath($GLOBALS['CANONICAL_RELATIVE_PATH_STUDIP'] . 'plugins.php'); +$plugin_dispatch = function (ServerRequestInterface $request, RequestHandlerInterface $handler) use ($app) { + $responseFactory = app(ResponseFactoryInterface::class); + try { + // get plugin class from request + $dispatch_to = Request::pathInfo(); + list($plugin_class, $unconsumed) = PluginEngine::routeRequest($dispatch_to); - // get plugin class from request - $dispatch_to = Request::pathInfo(); - list($plugin_class, $unconsumed) = PluginEngine::routeRequest($dispatch_to); + // handle legacy forum plugin URLs + if ($plugin_class === 'coreforum') { + $response = $responseFactory->createResponse(302); + return $response->withHeader('Location', URLHelper::getURL('dispatch.php/course/forum/' . $unconsumed)); + } - // handle legacy forum plugin URLs - if ($plugin_class === 'coreforum') { - header('Location: ' . URLHelper::getURL('dispatch.php/course/forum/' . $unconsumed)); - die(); - } + // retrieve corresponding plugin info + $plugin_manager = PluginManager::getInstance(); + $plugin_info = $plugin_manager->getPluginInfo($plugin_class); - // retrieve corresponding plugin info - $plugin_manager = PluginManager::getInstance(); - $plugin_info = $plugin_manager->getPluginInfo($plugin_class); + // create an instance of the queried plugin + $plugin = PluginEngine::getPlugin($plugin_class); - // create an instance of the queried plugin - $plugin = PluginEngine::getPlugin($plugin_class); + // user is not permitted, show login screen + if (is_null($plugin)) { + // TODO (mlunzena) should not getPlugin throw this exception? + throw new AccessDeniedException(_('Sie besitzen keine Rechte zum Aufruf dieses Plugins.')); + } - // user is not permitted, show login screen - if (is_null($plugin)) { - // TODO (mlunzena) should not getPlugin throw this exception? - throw new AccessDeniedException(_('Sie besitzen keine Rechte zum Aufruf dieses Plugins.')); - } + // set default page title + PageLayout::setTitle($plugin->getPluginName()); - // set default page title - PageLayout::setTitle($plugin->getPluginName()); + // deprecated, the plugin should override perform() instead + if (is_callable([$plugin, 'initialize'])) { + $plugin->initialize(); + } - // deprecated, the plugin should override perform() instead - if (is_callable([$plugin, 'initialize'])) { - $plugin->initialize(); + $route_callable = $plugin->getRouteCallable($unconsumed); + $app->any(Request::pathInfo(), $route_callable); + } catch (AccessDeniedException $ade) { + $_SESSION['redirect_after_login'] = Request::url(); + $response = $responseFactory->createResponse(302); + return $response->withHeader('Location', URLHelper::getURL('dispatch.php/login')); } + return $handler->handle($request); +}; - // let the show begin - $plugin->perform($unconsumed); -} catch (AccessDeniedException $ade) { - global $auth; - - $auth->login_if($auth->auth['uid'] == 'nobody'); - throw $ade; -} +$app->add($plugin_dispatch); +$app->add(app(Studip\Middleware\SeminarOpenMiddleware::class)); +$app->add(app(Studip\Middleware\AuthenticationMiddleware::class)); +auth()->setNobody(true); +$app->add(app(Studip\Middleware\SessionMiddleware::class)); -// close the page -page_close(); +NotificationCenter::postNotification('SLIM_BEFORE_RUN', $app); +$app->run(); diff --git a/public/seminar_main.php b/public/seminar_main.php index 831f1b47e4467972a1e5d025cc07f645c0e1093e..a4ac2fe0c9ad24910442b61601ea4283597ef1ac 100644 --- a/public/seminar_main.php +++ b/public/seminar_main.php @@ -23,63 +23,5 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - require '../lib/bootstrap.php'; - -ob_start(); -page_open(["sess" => "Seminar_Session", "auth" => "Seminar_Default_Auth", "perm" => "Seminar_Perm", "user" => "Seminar_User"]); -$auth->login_if(Request::get('again') && ($auth->auth["uid"] == "nobody")); - -if (Request::option('auswahl')) { - Request::set('cid', Request::option('auswahl')); -} - -include ('lib/seminar_open.php'); // initialise Stud.IP-Session - -// -- here you have to put initialisations for the current page - -$course_id = Context::getId(); - -if (!$course_id && Request::get('cid')) { - $archive_id = Request::get('cid'); - $archived = ArchivedCourse::find($archive_id); - if ($archived) { - header('Location: ' . URLHelper::getURL('dispatch.php/search/archive', [ - 'criteria' => $archived->name, - ])); - die; - } -} - -if (!$course_id) { - throw new CheckObjectException(_('Sie haben kein Objekt gewählt.')); -} - -//set visitdate for course, when coming from my_courses -if (Request::get('auswahl')) { - object_set_visit($course_id, 0); -} - - -// gibt es eine Anweisung zur Umleitung? -$redirect_to = Request::get('redirect_to'); -if ($redirect_to) { - if (!is_internal_url($redirect_to)) { - throw new Exception('Invalid redirection'); - } - - header('Location: '.URLHelper::getURL($redirect_to, ['cid' => $course_id])); - die; -} - -// der Nutzer zum ersten -//Reiter der Veranstaltung weiter geleitet. -if (Navigation::hasItem("/course")) { - foreach (Navigation::getItem("/course")->getSubNavigation() as $index => $navigation) { - if ($index !== 'admin') { - header('Location: ' . URLHelper::getURL($navigation->getURL())); - die; - } - } -} - +header('Location: ' . URLHelper::getURL('dispatch.php/course/go', $_GET)); diff --git a/public/sendfile.php b/public/sendfile.php index 571713ef08ba1522d60cbfcb70520dd24b708fd8..6c5d120e30f0eed328bcda5e2e569a7b4590cad3 100644 --- a/public/sendfile.php +++ b/public/sendfile.php @@ -39,10 +39,10 @@ ob_start(); require '../lib/bootstrap.php'; -page_open(["sess" => "Seminar_Session", - "auth" => "Seminar_Default_Auth", - "perm" => "Seminar_Perm", - "user" => "Seminar_User"]); +$sess = sess(); +$auth = auth(); +$auth->setNobody(true); +$sess->start(); //Load plugins, unless they are disabled via an URL parameter. if (Request::int('disable_plugins') !== null && ($GLOBALS['user']->id === 'nobody' || $GLOBALS['perm']->have_perm('root'))) { @@ -113,8 +113,14 @@ if ($file_missing) { //if download not allowed throw exception to terminate script if ($no_access) { // redirect to login page if user is not logged in - $GLOBALS['auth']->login_if($GLOBALS['auth']->auth['uid'] === 'nobody'); - throw new AccessDeniedException(_("Sie haben keine Zugriffsberechtigung für diesen Download!")); + if ($GLOBALS['user']->id === 'nobody') { + $_SESSION['redirect_after_login'] = Request::url(); + $sess->save(); + header('Location: ' . URLHelper::getURL('dispatch.php/login')); + die(); + } else { + throw new AccessDeniedException(_("Sie haben keine Zugriffsberechtigung für diesen Download!")); + } } //replace bad charakters to avoid problems when saving the file @@ -171,7 +177,7 @@ if (isset($file)) { } // close session, download will mostly be a parallel action -page_close(); +$sess->save(); // output_buffering may be explicitly or implicitly enabled while (ob_get_level()) { @@ -209,7 +215,7 @@ if ($filesize && !parse_url($path_file, PHP_URL_SCHEME)) { if (isset($_SERVER['HTTP_RANGE'])) { $c_start = $start; $c_end = $end; - list(, $range) = explode('=', $_SERVER['HTTP_RANGE'], 2); + [, $range] = explode('=', $_SERVER['HTTP_RANGE'], 2); if (mb_strpos($range, ',') !== false) { header('HTTP/1.1 416 Requested Range Not Satisfiable'); header("Content-Range: bytes $start-$end/$filesize"); diff --git a/public/web_migrate.php b/public/web_migrate.php index 0ee4de554638e7dc40240a64ef450fcc407521f0..4f2102a8eb0f0e2707f4a30a385e89d2269c2ec2 100644 --- a/public/web_migrate.php +++ b/public/web_migrate.php @@ -16,12 +16,13 @@ require __DIR__ . '/../lib/bootstrap.php'; -page_open([ - 'sess' => 'Seminar_Session', - 'auth' => 'Seminar_Auth', - 'perm' => 'Seminar_Perm', - 'user' => 'Seminar_User', -]); +sess()->start(); +if (!auth()->start()) { + $_SESSION['redirect_after_login'] = Request::url(); + sess()->save(); + header('Location: ' . URLHelper::getURL('dispatch.php/login')); + die(); +} URLHelper::setBaseUrl($GLOBALS['ABSOLUTE_URI_STUDIP']); diff --git a/resources/assets/stylesheets/scss/index.scss b/resources/assets/stylesheets/scss/index.scss index b33d5f6f9b8cc5e17edacddcc670acc941766e77..f41d0d62ab82587fb368fbdb64f13cf144a74ae1 100644 --- a/resources/assets/stylesheets/scss/index.scss +++ b/resources/assets/stylesheets/scss/index.scss @@ -60,6 +60,7 @@ $gap-between-boxes: calc($login-page-margin / 2); min-height: 540px; display: flex; box-shadow: 0 0 8px rgba(0, 0, 0, 0.5); + margin-top: 100px; #login-infobox { max-width: 540px; diff --git a/resources/assets/stylesheets/scss/layouts.scss b/resources/assets/stylesheets/scss/layouts.scss index a101dac396cc8b42d4d6e7ce12c28e0135069b41..f9cb14334299e35e1706295b819b3117035cca4c 100644 --- a/resources/assets/stylesheets/scss/layouts.scss +++ b/resources/assets/stylesheets/scss/layouts.scss @@ -8,7 +8,7 @@ html { body { display: grid; background-color: var(--white); - width: 100%; + width: 100%; grid-column-gap: 5px; grid-row-gap: $grid-gap; grid-template-columns: ($sidebar-width + $sidebar-padding) minmax(auto, calc(100vw - $sidebar-width - $sidebar-padding)); @@ -35,6 +35,10 @@ body { grid-row: 2 / 3; } +body#login #content-wrapper { + background: unset; +} + #content-wrapper { background: linear-gradient(90deg, var(--white) 30%, hsla(0, 0%, 100%, 0)), diff --git a/templates/blubber/course_context.php b/templates/blubber/course_context.php index d13752eb5ab704675cccf9217fab8f27c227f7e1..0d6d2af62ca9d57f279ff0ea5f391b1890f2e881 100644 --- a/templates/blubber/course_context.php +++ b/templates/blubber/course_context.php @@ -1,14 +1,14 @@ <div class="blubber_course_info indented"> <div class="headline"> <div class="side"> - <a href="<?= URLHelper::getLink("seminar_main.php", ['auswahl' => $course->getId()]) ?>"> + <a href="<?= URLHelper::getLink("dispatch.php/course/go", ['to' => $course->getId()]) ?>"> <?= htmlReady($course->name) ?> </a> <div class="icons"> <ul class="my-courses-navigation"> <? foreach ($icons as $icon) : ?> <li class="my-courses-navigation-item <? if ($icon->getImage()->signalsAttention()) echo 'my-courses-navigation-important'; ?>"> - <a href="<?= URLHelper::getLink("seminar_main.php", ['auswahl' => $course->getId(), 'redirect_to' => $icon->getURL()]) ?>"<?= $icon->getTitle() ? ' title="'.htmlReady($icon->getTitle()).'"' : "" ?>> + <a href="<?= URLHelper::getLink("dispatch.php/course/go", ['to' => $course->getId(), 'redirect_to' => $icon->getURL()]) ?>"<?= $icon->getTitle() ? ' title="'.htmlReady($icon->getTitle()).'"' : "" ?>> <?= $icon->getImage() ?> </a> </li> diff --git a/templates/dates/seminar_html.php b/templates/dates/seminar_html.php index f227a57aab06a0db47767b2edd32e93e5e245706..4a95f4d35c19d04d5c931d154fe1527d691b072a 100644 --- a/templates/dates/seminar_html.php +++ b/templates/dates/seminar_html.php @@ -112,7 +112,7 @@ if (!$dates['regular']['turnus_data'] && empty($dates['irregular'])) { echo '<br>'; printf( _('Details zu allen Terminen im %sAblaufplan%s'), - '<a href="' . URLHelper::getLink('seminar_main.php', array('auswahl' => $seminar_id, 'redirect_to' => 'dispatch.php/course/dates')) . '">', + '<a href="' . URLHelper::getLink('dispatch.php/course/go', array('to' => $seminar_id, 'redirect_to' => 'dispatch.php/course/dates')) . '">', '</a>' ); } diff --git a/templates/login_emailactivation.php b/templates/login_emailactivation.php deleted file mode 100644 index cf8221ac47d7270165a7652a4d24035c73c5c74a..0000000000000000000000000000000000000000 --- a/templates/login_emailactivation.php +++ /dev/null @@ -1,36 +0,0 @@ -<? -# Lifter010: TODO -use Studip\Button, Studip\LinkButton; -?> -<div align="center"> -<table width="70%" border=0 cellpadding=0 cellspacing=0> -<tr><td class="table_header_bold" colspan=3 align="left"> - <?= Icon::create('mail', 'info_alt')->asImg(['class' => 'text-top']) ?> - <b><?= _('E-Mail Aktivierung') ?></b> -</td></tr> -<tr><td style="background-color: #fff; padding: 1.5em;"> -<?= _('Sie haben Ihre E-Mail-Adresse geändert. Um diese frei zu schalten müssen Sie den Ihnen an Ihre neue Adresse zugeschickten Aktivierungs Schlüssel im folgenden Eingabefeld eintragen.'); ?> -<br><form action="activate_email.php" method="post"> - <?= CSRFProtection::tokenTag() ?> - <input name="key"> - <input name="uid" type="hidden" value="<?= $uid ?>"> - <?= Button::createAccept(_('Abschicken')) ?></form><br><br> -</td></tr></table></div><br> - - -<div align="center"> -<table width="70%" border=0 cellpadding=0 cellspacing=0> -<tr><td class="table_header_bold" colspan=3 align="left"> - <?= Icon::create('mail', 'info_alt')->asImg(['class' => 'text-top']) ?> - <b><?= _('E-Mail Aktivierung neu senden') ?></b> -</td></tr> -<tr><td style="background-color: #fff; padding: 1.5em;"> -<?= _('Sollten Sie keine E-Mail erhalten haben, können Sie sich einen neuen Aktivierungsschlüssel zuschicken lassen. Geben Sie dazu Ihre gewünschte E-Mail-Adresse im folgenden Formular an:'); ?> -<form action="activate_email.php" method="post"> -<?= CSRFProtection::tokenTag() ?> -<input type="hidden" name="uid" value="<?= $uid ?>"> -<table><tr><td><?= _('E-Mail') ?>:</td><td><input name="email1"></td></tr> -<tr><td><?= _('Wiederholung') ?>:</td><td><input name="email2"></td></tr></table> -<?= Button::createAccept(_('Abschicken')) ?> -</form> -</td></tr></table></div><br> diff --git a/templates/mail/notification_html.php b/templates/mail/notification_html.php index 93bc1a81fbc9c8fdb6ac05f8a2f50d2567e01fb6..b1cbdee2c74dc07ab9b57a2506fe8f314cc760b6 100644 --- a/templates/mail/notification_html.php +++ b/templates/mail/notification_html.php @@ -104,7 +104,7 @@ <? foreach ($news as $sem_titel => $data) : ?> <tr class="table_header_bold"> <td style="font-weight: bold;"> - <a href="<?= URLHelper::getLink('seminar_main.php', ['again' => 'yes', 'sso' => $sso, 'auswahl' => $data[0]['seminar_id']]) ?>"> + <a href="<?= URLHelper::getLink('dispatch.php/course/go', ['again' => 'yes', 'sso' => $sso, 'to' => $data[0]['seminar_id']]) ?>"> <?= htmlReady($sem_titel) ?> <?= (($semester = Course::find($data[0]['range_id'])->semester_text) ? ' ('.$semester.')' : '') ?> </a> diff --git a/templates/mail/notification_text.php b/templates/mail/notification_text.php index 47b8a4aaf85eb1c4658ca2e6ffe035f5c7b3c509..3eb3b2e4e7fde695d775f4d104580e38f3652087 100644 --- a/templates/mail/notification_text.php +++ b/templates/mail/notification_text.php @@ -14,7 +14,7 @@ <? foreach ($news as $sem_titel => $data) : ?> <?= sprintf(_("In der Veranstaltung \"%s\" gibt es folgende Neuigkeiten:"), $sem_titel) ?> -<?= URLHelper::getURL('seminar_main.php', ['again' => 'yes', 'sso' => $sso, 'auswahl' => $data[0]['seminar_id']]) ?> +<?= URLHelper::getURL('dispatch.php/course/go', ['again' => 'yes', 'sso' => $sso, 'to' => $data[0]['seminar_id']]) ?> <? foreach ($data as $module) : ?> diff --git a/templates/shared/opengraphinfo_wide.php b/templates/shared/opengraphinfo_wide.php index 0637232808ee343e530532ee52bbc1169708aae6..1957bc44da5ace18bdda13d9a6e84d1dd164645b 100644 --- a/templates/shared/opengraphinfo_wide.php +++ b/templates/shared/opengraphinfo_wide.php @@ -7,7 +7,7 @@ $videofiles = $og->getVideoFiles(); $audiofiles = $og->getAudioFiles(); $og['image'] = filter_var($og['image'], FILTER_VALIDATE_URL) ? $og['image'] : ''; -if (Config::get()->LOAD_EXTERNAL_MEDIA === "proxy" && Seminar_Session::is_current_session_authenticated()) { +if (Config::get()->LOAD_EXTERNAL_MEDIA === "proxy" && sess()->isCurrentSessionAuthenticated()) { $media_url_func = function ($url) { return $GLOBALS['ABSOLUTE_URI_STUDIP'] . 'dispatch.php/media_proxy?url=' . urlencode($url); }; diff --git a/tests/_support/Helper/Jsonapi.php b/tests/_support/Helper/Jsonapi.php index cbb2216ed2344d37384725e8d164756de2d79d47..6a31d661ced0c2742edc9e14b91671c887980dba 100644 --- a/tests/_support/Helper/Jsonapi.php +++ b/tests/_support/Helper/Jsonapi.php @@ -129,12 +129,6 @@ class Jsonapi extends \Codeception\Module ->add(function ($request, $handler) { $user = $request->getAttribute(Authentication::USER_KEY, null); - $GLOBALS['auth'] = new \Seminar_Auth(); - $GLOBALS['auth']->auth = [ - 'uid' => $user->id, - 'uname' => $user->username, - 'perm' => $user->perms, - ]; $GLOBALS['user'] = new \Seminar_User($user->id); $GLOBALS['perm'] = new \Seminar_Perm(); $GLOBALS['MAIL_VALIDATE_BOX'] = false; diff --git a/tests/jsonapi/SeminarCycleDatesShowTest.php b/tests/jsonapi/SeminarCycleDatesShowTest.php index 46f8b9334d623e625b75c2a94d25786dc9503b50..0d2c559b8dc263e124cc38e591bbaac974784a98 100644 --- a/tests/jsonapi/SeminarCycleDatesShowTest.php +++ b/tests/jsonapi/SeminarCycleDatesShowTest.php @@ -51,8 +51,6 @@ class SeminarCycleDatesShowTest extends \Codeception\Test\Unit $GLOBALS['user'] = new \Seminar_User( \User::find($credentials['id']) ); - $GLOBALS['auth'] = new \Seminar_Auth(); - $GLOBALS['auth']->auth = ['uid' => $credentials['id']]; $cycle = \SeminarCycleDate::create( [ diff --git a/tests/jsonapi/_bootstrap.php b/tests/jsonapi/_bootstrap.php index 1fc5ba7ba0d71af6f124d8a675935a341f6fc6af..5a02ca2b60a92cdb96af0cd6b39851b3b693785e 100644 --- a/tests/jsonapi/_bootstrap.php +++ b/tests/jsonapi/_bootstrap.php @@ -2,13 +2,14 @@ // Here you can initialize variables that will be available to your tests -global $STUDIP_BASE_PATH, $ABSOLUTE_URI_STUDIP, $CACHING_ENABLE, $CACHING_FILECACHE_PATH, $SYMBOL_SHORT, $TMP_PATH, $UPLOAD_PATH, $DYNAMIC_CONTENT_PATH, $DYNAMIC_CONTENT_URL; +global $STUDIP_BASE_PATH, $ABSOLUTE_URI_STUDIP, $CACHING_ENABLE, $CACHING_FILECACHE_PATH, $SYMBOL_SHORT, $TMP_PATH, $UPLOAD_PATH, $DYNAMIC_CONTENT_PATH, $DYNAMIC_CONTENT_URL, $CANONICAL_RELATIVE_PATH_STUDIP; // common set-up, usually done by lib/bootstraph.php and // config/config_local.inc.php when run on web server if (!isset($STUDIP_BASE_PATH)) { $STUDIP_BASE_PATH = dirname(dirname(__DIR__)); $ABSOLUTE_PATH_STUDIP = $STUDIP_BASE_PATH.'/public/'; + $CANONICAL_RELATIVE_PATH_STUDIP = '/public/'; $UPLOAD_PATH = $STUDIP_BASE_PATH.'/data/upload_doc'; $TMP_PATH = $TMP_PATH ?: '/tmp'; $DYNAMIC_CONTENT_PATH = ''; @@ -50,17 +51,6 @@ $GLOBALS['_fullname_sql']['full_rev_username'] = "TRIM(CONCAT(Nachname,', ',Vorn SimpleORMap::expireTableScheme(); -/** - * @deprecated - */ -class DB_Seminar extends DB_Sql -{ - public function __construct($query = false) - { - parent::__construct($query); - } -} - -require_once __DIR__ . '/../../composer/autoload.php'; +require_once __DIR__.'/../../composer/autoload.php'; session_id("test-session"); diff --git a/tests/unit/_bootstrap.php b/tests/unit/_bootstrap.php index 0cf0f7ec526c3903ce023b89dbc0b501d98ab28a..9bc68f5ea2f60ef3cd7a6be05448706f832ddc1f 100644 --- a/tests/unit/_bootstrap.php +++ b/tests/unit/_bootstrap.php @@ -51,7 +51,6 @@ require __DIR__ . '/../../composer/autoload.php'; global $STUDIP_BASE_PATH; $STUDIP_BASE_PATH = realpath(dirname(__DIR__) . '/..'); -require 'lib/helpers.php'; require 'lib/functions.php'; require 'lib/visual.inc.php'; @@ -125,3 +124,48 @@ if (!class_exists('StudipTestHelper')) { } } } + +//fake DI +class StudipFakeDIContainer +{ + private $storage; + private static $instance; + + public static function getInstance() + { + if (is_null(self::$instance)) { + self::$instance = new self(); + } + return self::$instance; + } + + public function get($name) + { + return $this->storage[$name] ?? null; + } + + public function set($name, $object) + { + $this->storage[$name] = $object; + } + + public function make($name, $parameters) + { + return $this->get($name); + } +} + +function app($entryId = null, $parameters = []) +{ + $container = StudipFakeDIContainer::getInstance(); + if (is_null($entryId)) { + return $container; + } + + return $container->make($entryId, $parameters); +} + +function sess() +{ + return app()->get('Studip\Session\Manager'); +} diff --git a/tests/unit/lib/classes/AvatarClassTest.php b/tests/unit/lib/classes/AvatarClassTest.php index e09a3c260b571d9f3f94793f67165eb0c712cba8..51bfab8c5fd26910afef47751340ca78aa2fa038 100644 --- a/tests/unit/lib/classes/AvatarClassTest.php +++ b/tests/unit/lib/classes/AvatarClassTest.php @@ -9,7 +9,7 @@ * the License, or (at your option) any later version. */ -require_once 'lib/phplib/Seminar_Perm.php'; +require_once 'lib/classes/Seminar_Perm.php'; abstract class AvatarTest extends \Codeception\Test\Unit { diff --git a/tests/unit/lib/classes/MarkupClassTest.php b/tests/unit/lib/classes/MarkupClassTest.php index 8dad6e9954746c220a207cf96d34ba9f3c154c6c..7342a4a82097d29621eb1bc4e5d99e32742d0375 100644 --- a/tests/unit/lib/classes/MarkupClassTest.php +++ b/tests/unit/lib/classes/MarkupClassTest.php @@ -33,9 +33,9 @@ require_once 'lib/classes/Markup.php'; # completely unneeded for testing the Markup class. # Instead, create a fake class. # => But note, this will fail if another test case does the same thing! -class Seminar_Session +class StudipSessionManager { - public static function is_current_session_authenticated() + public static function isCurrentSessionAuthenticated() { return true; } @@ -77,7 +77,7 @@ class MarkupClassTest extends \Codeception\Test\Unit })); Config::set($configStub); - + app()->set('Studip\Session\Manager', new StudipSessionManager()); # exceptions $namespace = 'Studip\MarkupPrivate\MediaProxy\\'; $invalidInternalLink = $namespace . 'InvalidInternalLinkException'; diff --git a/tests/unit/lib/classes/MigrationTest.php b/tests/unit/lib/classes/MigrationTest.php index 12df1201c7ee64f52ef3f7406acf8434ddc31003..2e9db08a674550807721ed6213cbb1f2c71ceb4d 100644 --- a/tests/unit/lib/classes/MigrationTest.php +++ b/tests/unit/lib/classes/MigrationTest.php @@ -19,6 +19,11 @@ class MigrationTest extends \Codeception\Test\Unit require_once 'lib/migrations/Migration.php'; require_once 'lib/migrations/Migrator.php'; require_once 'lib/migrations/SchemaVersion.php'; + + $testconfig = new Config([ + 'LOG_ENABLE' => false, + ]); + Config::set($testconfig); } public function tearDown(): void diff --git a/vendor/email_message/debug_message.php b/vendor/email_message/debug_message.php index f8d4f02278f54dd82b50a015f037ca5d6a70c161..ea8bd6b4d5b6f80d16aa87d213790e89fa956d0e 100644 --- a/vendor/email_message/debug_message.php +++ b/vendor/email_message/debug_message.php @@ -15,15 +15,15 @@ class debug_message_class extends email_message_class function __construct() { $this->logfile = $GLOBALS['TMP_PATH'] . '/studip-mail-debug.log'; } - + function SendMail($to,$subject,$body,$headers,$return_path) { if ($log = fopen($this->logfile, "a")){ if(strlen($headers)) $headers.="\n"; - fwrite($log, "\n-- " . strftime("%x %X"). ' ' . $GLOBALS['auth']->auth['uname']); + fwrite($log, "\n-- " . strftime("%x %X"). ' ' . $GLOBALS['user']->username); fwrite($log, "\nTo: ".$to."\nSubject: ".$subject."\n".$headers."\n"); fwrite($log,$body."\n"); fclose($log); } } } -?> \ No newline at end of file +?>