From ce679651ccf784da2e4bf57d53b57d895a4fbea3 Mon Sep 17 00:00:00 2001 From: Elmar Ludwig Date: Fri, 27 Feb 2026 14:50:39 +0100 Subject: fix XSS issues with date formatting, fixes #6277 Closes #6277 Merge request studip/studip!4751 --- app/controllers/admin/courses.php | 7 ++---- app/controllers/course/block_appointments.php | 4 ++-- app/controllers/course/overview.php | 2 +- app/controllers/course/timesrooms.php | 24 +++++++++---------- app/controllers/tree.php | 2 +- app/views/course/overview/index.php | 4 ++-- .../course/room_requests/_new_request_header.php | 2 +- app/views/resources/_common/_request_info.php | 2 +- app/views/resources/_common/_request_tr.php | 2 +- app/views/resources/admin/global_locks.php | 2 +- app/views/resources/booking/add_from_request.php | 2 +- app/views/resources/room_request/planning.php | 2 +- app/views/resources/room_request/resolve.php | 2 +- lib/models/CourseDate.php | 6 +---- lib/models/SeminarCycleDate.php | 28 +++++++++++++++------- lib/models/resources/ResourceRequest.php | 2 +- templates/dates/course_date_list.php | 24 ++++++++++++++++--- templates/filesystem/topic_folder/description.php | 2 +- 18 files changed, 71 insertions(+), 48 deletions(-) diff --git a/app/controllers/admin/courses.php b/app/controllers/admin/courses.php index fb65f70..38ce72b 100644 --- a/app/controllers/admin/courses.php +++ b/app/controllers/admin/courses.php @@ -658,8 +658,7 @@ class Admin_CoursesController extends AuthenticatedController $d['type'] = htmlReady($semtype['name']); } if (in_array('room_time', $activated_fields)) { - $strings = $course->getAllDatesInSemester($this->semester)->toStringArray(); - $d['room_time'] = implode('
', $strings) ?: _('nicht angegeben'); + $d['room_time'] = $course->getAllDatesInSemester($this->semester)->toHtml(); } if (in_array('semester', $activated_fields)) { $d['semester'] = htmlReady($course->semester_text); @@ -1005,9 +1004,7 @@ class Admin_CoursesController extends AuthenticatedController } if (in_array('room_time', $filter_config)) { - $dates = $course->getAllDatesInSemester($this->semester); - $date_strings = $dates->toStringArray(true); - $row['room_time'] = implode("\n", $date_strings) ?: _('nicht angegeben'); + $row['room_time'] = (string) $course->getAllDatesInSemester($this->semester); } if (in_array('requests', $filter_config)) { diff --git a/app/controllers/course/block_appointments.php b/app/controllers/course/block_appointments.php index 9e6b9c2..c735244 100644 --- a/app/controllers/course/block_appointments.php +++ b/app/controllers/course/block_appointments.php @@ -272,11 +272,11 @@ class Course_BlockAppointmentsController extends AuthenticatedController } if ($result && $booking_failures) { //Not all selected rooms for the date could be booked: - $partially_booked_dates[] = $d->getFullName(); + $partially_booked_dates[] = htmlReady($d->getFullName()); } } - return $result ? $d->getFullName() : null; + return $result ? htmlReady($d->getFullName()) : null; }, $dates)); if ($date_count > 1) { diff --git a/app/controllers/course/overview.php b/app/controllers/course/overview.php index fc0f441..4325de8 100644 --- a/app/controllers/course/overview.php +++ b/app/controllers/course/overview.php @@ -67,7 +67,7 @@ class Course_OverviewController extends AuthenticatedController $this->next_date = $this->course->getNextDate(); $this->first_date = $this->course->getFirstDate(); $show_link = $GLOBALS["perm"]->have_studip_perm('autor', $this->course_id) && $this->course->isToolActive('schedule'); - $this->times_rooms = implode('
', $this->course->getAllDatesInSemester()->toStringArray()); + $this->times_rooms = $this->course->getAllDatesInSemester()->toHtml(); //Load lecturers: $lecturers = $this->course->getMembersWithStatus('dozent'); diff --git a/app/controllers/course/timesrooms.php b/app/controllers/course/timesrooms.php index ae2c567..8349445 100644 --- a/app/controllers/course/timesrooms.php +++ b/app/controllers/course/timesrooms.php @@ -371,7 +371,7 @@ class Course_TimesroomsController extends AuthenticatedController PageLayout::postWarning( studip_interpolate( _('Die Buchung des Raumes %{room_name} zu diesem Termin wird bei der Verlängerung des Zeitbereiches gelöscht, da sie keine Buchungsrechte an dem Raum haben!'), - ['room_name' => $room->name] + ['room_name' => htmlReady($room->name)] ) ); } @@ -759,9 +759,9 @@ class Course_TimesroomsController extends AuthenticatedController studip_interpolate( _('Der Raum %{room_name} wird an dem Termin %{date} bereits durch die Veranstaltung %{course_name} belegt.'), [ - 'room_name' => $room->name, - 'date' => $termin->getFullName(), - 'course_name' => $course->name + 'room_name' => htmlReady($room->name), + 'date' => htmlReady($termin->getFullName()), + 'course_name' => htmlReady($course->name) ] ), $message_links @@ -771,8 +771,8 @@ class Course_TimesroomsController extends AuthenticatedController studip_interpolate( _('Der Raum %{room_name} wird an dem Termin %{date} bereits anderweitig belegt.'), [ - 'room_name' => $room->name, - 'date' => $termin->getFullName() + 'room_name' => htmlReady($room->name), + 'date' => htmlReady($termin->getFullName()) ] ), $message_links @@ -1309,7 +1309,7 @@ class Course_TimesroomsController extends AuthenticatedController $error_messages[] = sprintf( studip_interpolate( _('%{date}: Die eingegebene Rüstzeit überschreitet das erlaubte Maximum von %d Minuten!'), - ['date' => $singledate->getFullName()] + ['date' => htmlReady($singledate->getFullName())] ), $max_preparation_time ); @@ -1334,17 +1334,17 @@ class Course_TimesroomsController extends AuthenticatedController $error_messages[] = studip_interpolate( _('Der Raum %{room_name} wird an dem Termin %{date} bereits durch die Veranstaltung %{course_name} belegt.'), [ - 'room_name' => $room->name, - 'date' => $singledate->getFullName(), - 'course_name' => $course->name + 'room_name' => htmlReady($room->name), + 'date' => htmlReady($singledate->getFullName()), + 'course_name' => htmlReady($course->name) ] ); } else { $error_messages[] = studip_interpolate( _('Der Raum %{room_name} wird an dem Termin %{date} bereits anderweitig belegt.'), [ - 'room_name' => $room->name, - 'date' => $singledate->getFullName() + 'room_name' => htmlReady($room->name), + 'date' => htmlReady($singledate->getFullName()) ] ); } diff --git a/app/controllers/tree.php b/app/controllers/tree.php index 22135a5..9bde648 100644 --- a/app/controllers/tree.php +++ b/app/controllers/tree.php @@ -39,7 +39,7 @@ class TreeController extends AuthenticatedController $course->veranstaltungsnummer, $course->getFullName('type-number-name'), $course->getTextualSemester(), - strip_tags(implode("\n", $course->getAllDatesInSemester()->toStringArray())), + implode("\n", $course->getAllDatesInSemester()->toStringArray()), implode(', ', $lecturers), implode("\n", $studyAreaPaths) ]; diff --git a/app/views/course/overview/index.php b/app/views/course/overview/index.php index 03fc848..fa14efd 100644 --- a/app/views/course/overview/index.php +++ b/app/views/course/overview/index.php @@ -17,12 +17,12 @@
-
getFullName('long') ?>
+
getFullName('long')) ?>
- getFullName('long') ?> + getFullName('long')) ?> diff --git a/app/views/course/room_requests/_new_request_header.php b/app/views/course/room_requests/_new_request_header.php index cd0d381..c63d8a8 100644 --- a/app/views/course/room_requests/_new_request_header.php +++ b/app/views/course/room_requests/_new_request_header.php @@ -7,7 +7,7 @@ getDateString(true); ?> - ', $dates)) ?> + ', array_map('htmlReady', $dates))) ?> diff --git a/app/views/resources/_common/_request_info.php b/app/views/resources/_common/_request_info.php index 8a0c7b4..c698fad 100644 --- a/app/views/resources/_common/_request_info.php +++ b/app/views/resources/_common/_request_info.php @@ -5,7 +5,7 @@ ?>
:
-
getDateString() ?>
+
getDateString()) ?>
:
preparation_time / 60) ?> diff --git a/app/views/resources/_common/_request_tr.php b/app/views/resources/_common/_request_tr.php index 8f0510e..7c18ed1 100644 --- a/app/views/resources/_common/_request_tr.php +++ b/app/views/resources/_common/_request_tr.php @@ -49,7 +49,7 @@ getTimeIntervals() ?> - getTypeString() ?> + getTypeString()) ?> isSimpleRequest()): ?> getStartDate(); diff --git a/app/views/resources/admin/global_locks.php b/app/views/resources/admin/global_locks.php index ef6bccd..6f44630 100644 --- a/app/views/resources/admin/global_locks.php +++ b/app/views/resources/admin/global_locks.php @@ -13,7 +13,7 @@ begin) ?> end) ?> - getTypeString() ?> + getTypeString()) ?> setContext( sprintf( diff --git a/app/views/resources/booking/add_from_request.php b/app/views/resources/booking/add_from_request.php index e7c3d37..f5b5573 100644 --- a/app/views/resources/booking/add_from_request.php +++ b/app/views/resources/booking/add_from_request.php @@ -12,7 +12,7 @@

    - getDateString()) ?> + getDateString(true) ?>
  • diff --git a/app/views/resources/room_request/planning.php b/app/views/resources/room_request/planning.php index 8011dee..1b6c6a3 100644 --- a/app/views/resources/room_request/planning.php +++ b/app/views/resources/room_request/planning.php @@ -285,7 +285,7 @@ - getTypeString() ?> + getTypeString()) ?> diff --git a/app/views/resources/room_request/resolve.php b/app/views/resources/room_request/resolve.php index 8156dc2..9d4aab8 100644 --- a/app/views/resources/room_request/resolve.php +++ b/app/views/resources/room_request/resolve.php @@ -125,7 +125,7 @@
    getDateString(true, false) ?> - ', $dates) ?> + ', array_map('htmlReady', $dates)) ?> diff --git a/lib/models/CourseDate.php b/lib/models/CourseDate.php index 87a56e8..91182c6 100644 --- a/lib/models/CourseDate.php +++ b/lib/models/CourseDate.php @@ -370,11 +370,7 @@ class CourseDate extends SimpleORMap implements PrivacyObject, Event $rooms = $this->getRooms(); if ($rooms) { foreach ($rooms as $room) { - $string = sprintf('%s %s', - $string, - $room->getActionURL('booking_plan'), - htmlReady($room->name) - ); + $string .= ' ' . $room->name; } } elseif ($this->raum) { //Use the freetext room name: diff --git a/lib/models/SeminarCycleDate.php b/lib/models/SeminarCycleDate.php index e400665..799cd4a 100644 --- a/lib/models/SeminarCycleDate.php +++ b/lib/models/SeminarCycleDate.php @@ -214,7 +214,7 @@ class SeminarCycleDate extends SimpleORMap * * @returns string The formatted string. */ - public function toString(string $format = 'short') : string + public function toString(string $format = 'short', bool $as_html = false) : string { if (!in_array($format, ['short', 'long', 'long-start', 'full'])) { //Invalid format: @@ -246,16 +246,24 @@ class SeminarCycleDate extends SimpleORMap $room = $this->getMostBookedRoom(); if ($room) { - $parameters['room_name'] = sprintf( - '%2$s', - $room->getActionLink(), - htmlReady($room->name) - ); + if ($as_html) { + $parameters['room_name'] = sprintf( + '%2$s', + $room->getActionLink(), + htmlReady($room->name) + ); + } else { + $parameters['room_name'] = $room->name; + } } else { //Use the freetext room name: $room = $this->getMostUsedFreetextRoomName(); if ($room) { - $parameters['room_name'] = $room; + if ($as_html) { + $parameters['room_name'] = htmlReady($room); + } else { + $parameters['room_name'] = $room; + } } } $first_date = $this->getFirstDate(); @@ -273,7 +281,11 @@ class SeminarCycleDate extends SimpleORMap } elseif ($format === 'full') { $parameters['start_week'] = $this->week_offset + 1; if ($this->description) { - $parameters['description'] = $this->description; + if ($as_html) { + $parameters['description'] = htmlReady($this->description); + } else { + $parameters['description'] = $this->description; + } } if ($this->end_offset) { $parameters['end_week'] = $this->end_offset; diff --git a/lib/models/resources/ResourceRequest.php b/lib/models/resources/ResourceRequest.php index 0fe0342..79969b3 100644 --- a/lib/models/resources/ResourceRequest.php +++ b/lib/models/resources/ResourceRequest.php @@ -1577,7 +1577,7 @@ class ResourceRequest extends SimpleORMap implements PrivacyObject, Studip\Calen $begin_date = date('Ymd', $this->begin); $end_date = date('Ymd', $this->end); if($this->resource) { - $resource_name = htmlReady($this->resource->getFullName()); + $resource_name = $this->resource->getFullName(); } if ($begin_date == $end_date) { $strings[] = strftime('%a., %x, %R', $this->begin) . ' - ' diff --git a/templates/dates/course_date_list.php b/templates/dates/course_date_list.php index 8fdcd69..0a7bf41 100644 --- a/templates/dates/course_date_list.php +++ b/templates/dates/course_date_list.php @@ -12,14 +12,32 @@ isEmpty()) : ?>
      getRegularDates() as $regular_date) : ?> -
    • toString('long-start') ?>
    • +
    • + toString('long-start', true) ?> +
    • getSingleDates() as $single_date) : ?> -
    • getFullName($with_room_names ? 'long-include-room' : 'long') ?>
    • +
    • + getFullName('long')) ?> + + getRooms() ?> + + + + name) ?> + + + + raum) ?> + + +
    • getCancelledDates() as $cancelled_date) : ?> -
    • getFullName() ?>
    • +
    • + getFullName()) ?> +
    diff --git a/templates/filesystem/topic_folder/description.php b/templates/filesystem/topic_folder/description.php index b80740f..9028773 100644 --- a/templates/filesystem/topic_folder/description.php +++ b/templates/filesystem/topic_folder/description.php @@ -12,7 +12,7 @@
    - +
    -- cgit v1.0