From 27962a475916255dcb65d7090b64503e1da10925 Mon Sep 17 00:00:00 2001 From: Jonathan Champ Date: Mon, 6 Jul 2026 18:04:56 +0200 Subject: [PATCH 1/6] lib: bound parameters are better than interpolation --- lib.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib.php b/lib.php index 9bba84be..4018d9b5 100755 --- a/lib.php +++ b/lib.php @@ -1108,7 +1108,12 @@ function zoom_update_instance_breakout_rooms($zoomid, $breakoutrooms) { function zoom_delete_instance_breakout_rooms($zoomid) { global $DB; - $zoomcurrentbreakoutroomsids = $DB->get_fieldset_select('zoom_meeting_breakout_rooms', 'id', "zoomid = {$zoomid}"); + $zoomcurrentbreakoutroomsids = $DB->get_fieldset_select( + 'zoom_meeting_breakout_rooms', + 'id', + 'zoomid = ?', + [$zoomid] + ); foreach ($zoomcurrentbreakoutroomsids as $id) { $DB->delete_records('zoom_breakout_participants', ['breakoutroomid' => $id]); From 5cecbc5bc34ff0841ae64c10ee3ecce6e6497514 Mon Sep 17 00:00:00 2001 From: Jonathan Champ Date: Mon, 6 Jul 2026 18:14:30 +0200 Subject: [PATCH 2/6] get_meeting_report: use task directly; reduce dependencies --- console/get_meeting_report.php | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/console/get_meeting_report.php b/console/get_meeting_report.php index 826220d0..cb856abd 100644 --- a/console/get_meeting_report.php +++ b/console/get_meeting_report.php @@ -45,16 +45,8 @@ $PAGE->set_url('/mod/zoom/console/'); echo html_writer::tag('h1', get_string('getmeetingreports', 'mod_zoom')); -$output = null; -$arguments = implode( - ' ', - [ - '--start=' . escapeshellarg($startdate), - '--end=' . escapeshellarg($enddate), - '--courseid=' . escapeshellarg($courseid), - ] -); -exec("php $CFG->dirroot/mod/zoom/cli/get_meeting_report.php $arguments", $output); echo '
';
-echo implode("\n", $output);
+$hostuuids = $DB->get_fieldset_select('zoom', 'DISTINCT host_id', 'course = ?', [$courseid]);
+$meetingtask = new \mod_zoom\task\get_meeting_reports();
+$meetingtask->execute($startdate, $enddate, $hostuuids);
 echo '
'; From 5e673e9aa9835f189cf24017833d3c52b70964ee Mon Sep 17 00:00:00 2001 From: Jonathan Champ Date: Tue, 7 Jul 2026 12:28:26 +0200 Subject: [PATCH 3/6] output: format_string all dynamic strings (multilang and more) --- classes/task/get_meeting_reports.php | 7 ++++-- index.php | 4 ++-- locallib.php | 2 +- participants.php | 34 +++++++++++++++++----------- recordings.php | 8 +++---- report.php | 10 ++++---- view.php | 8 +++---- 7 files changed, 42 insertions(+), 31 deletions(-) diff --git a/classes/task/get_meeting_reports.php b/classes/task/get_meeting_reports.php index 991260ad..b0ed1562 100644 --- a/classes/task/get_meeting_reports.php +++ b/classes/task/get_meeting_reports.php @@ -866,8 +866,11 @@ public function notify_teachers($data) { // Number of users need to be graded. $needgradenumber = count($data['needgrade']); // List of users need grading. - $needstring = get_string('grading_needgrade', 'mod_zoom'); - $needgrade = (!empty($data['needgrade'])) ? $needstring . implode('
', $data['needgrade']) . "\n" : ''; + $needgrade = ''; + if (!empty($data['needgrade'])) { + $safeneedgrade = array_map('s', $data['needgrade']); + $needgrade = get_string('grading_needgrade', 'mod_zoom') . implode('
', $safeneedgrade) . "\n"; + } $zoomid = $data['zoomid']; $itemid = $data['itemid']; diff --git a/index.php b/index.php index 6c714ece..30eff0b4 100755 --- a/index.php +++ b/index.php @@ -60,8 +60,8 @@ $PAGE->set_url('/mod/zoom/index.php', ['id' => $id]); $PAGE->navbar->add($strname); -$PAGE->set_title("$course->shortname: $strname"); -$PAGE->set_heading($course->fullname); +$PAGE->set_title(format_string("$course->shortname: $strname", true, ['context' => $context])); +$PAGE->set_heading(format_string($course->fullname, true, ['context' => $context])); $PAGE->set_pagelayout('incourse'); echo $OUTPUT->header(); diff --git a/locallib.php b/locallib.php index 0e2d879e..7a809e77 100755 --- a/locallib.php +++ b/locallib.php @@ -143,7 +143,7 @@ function zoom_fatal_error($errorcode, $module = '', $continuelink = '', $a = nul throw new moodle_exception($errorcode, $module, $continuelink, $a); } - $PAGE->set_heading($COURSE->fullname); + $PAGE->set_heading(format_string($COURSE->fullname)); $output .= $OUTPUT->header(); // Output message without messing with HTML content of error. diff --git a/participants.php b/participants.php index 40c5a724..5a1a64c6 100644 --- a/participants.php +++ b/participants.php @@ -43,11 +43,11 @@ $PAGE->set_url('/mod/zoom/participants.php', ['id' => $cm->id, 'uuid' => $uuid, 'export' => $export]); -$strname = $zoom->name; +$activityname = $zoom->name; $strtitle = get_string('participants', 'mod_zoom'); $PAGE->navbar->add($strtitle); -$PAGE->set_title("$course->shortname: $strname"); -$PAGE->set_heading($course->fullname); +$PAGE->set_title(format_string("$course->shortname: $activityname", true, ['context' => $context])); +$PAGE->set_heading(format_string($course->fullname, true, ['context' => $context])); $PAGE->set_pagelayout('incourse'); $maskparticipantdata = get_config('zoom', 'maskparticipantdata'); @@ -66,7 +66,7 @@ // Display the headers/etc if we're not exporting, or if there is no data. if (empty($export) || empty($participants)) { echo $OUTPUT->header(); - echo $OUTPUT->heading($strname); + echo $OUTPUT->heading(format_string($activityname, true, ['context' => $context])); echo $OUTPUT->heading($strtitle, 4); // Stop if there is no data. @@ -116,12 +116,11 @@ } // ID number. + $idnumber = ''; if (array_key_exists($p->userid, $moodleidtouids)) { - $row[] = $moodleidtouids[$p->userid]; + $idnumber = $moodleidtouids[$p->userid]; } else if (isset($moodleuser->idnumber)) { - $row[] = $moodleuser->idnumber; - } else { - $row[] = ''; + $idnumber = $moodleuser->idnumber; } // Name/email. @@ -135,12 +134,21 @@ // Put email in separate column if we are exporting to Excel. if (!empty($export)) { - $row[] = $name; - $row[] = $email; - } else if (!empty($email)) { - $row[] = html_writer::link("mailto:$email", $name); + $row = [ + $idnumber, + $name, + $email, + ]; } else { - $row[] = $name; + $safename = format_string($name, true, ['context' => $context]); + if (!empty($email)) { + $safename = html_writer::link("mailto:$email", $safename); + } + + $row = [ + s($idnumber), + $safename, + ]; } // Join/leave times. diff --git a/recordings.php b/recordings.php index c358e9ac..81c2f73c 100644 --- a/recordings.php +++ b/recordings.php @@ -41,13 +41,13 @@ $url = new moodle_url('/mod/zoom/recordings.php', $params); $PAGE->set_url($url); -$strname = $zoom->name; -$PAGE->set_title("$course->shortname: $strname"); -$PAGE->set_heading($course->fullname); +$activityname = $zoom->name; +$PAGE->set_title(format_string("$course->shortname: $activityname", true, ['context' => $context])); +$PAGE->set_heading(format_string($course->fullname, true, ['context' => $context])); $PAGE->set_pagelayout('incourse'); echo $OUTPUT->header(); -echo $OUTPUT->heading($strname); +echo $OUTPUT->heading(format_string($activityname, true, ['context' => $context])); $iszoommanager = has_capability('mod/zoom:addinstance', $context); diff --git a/report.php b/report.php index 7ee5b46e..384c84fa 100755 --- a/report.php +++ b/report.php @@ -38,15 +38,15 @@ $PAGE->set_url('/mod/zoom/report.php', ['id' => $cm->id]); -$strname = $zoom->name; +$activityname = $zoom->name; $strtitle = get_string('sessions', 'mod_zoom'); $PAGE->navbar->add($strtitle); -$PAGE->set_title("$course->shortname: $strname"); -$PAGE->set_heading($course->fullname); +$PAGE->set_title(format_string("$course->shortname: $activityname", true, ['context' => $context])); +$PAGE->set_heading(format_string($course->fullname, true, ['context' => $context])); $PAGE->set_pagelayout('incourse'); echo $OUTPUT->header(); -echo $OUTPUT->heading($strname); +echo $OUTPUT->heading(format_string($activityname, true, ['context' => $context])); echo $OUTPUT->heading($strtitle, 4); $sessions = zoom_get_sessions_for_display($zoom->id); @@ -65,7 +65,7 @@ foreach ($sessions as $uuid => $meet) { $row = []; - $row[] = $meet['topic']; + $row[] = format_string($meet['topic'], true, ['context' => $context]); $row[] = $meet['starttime']; $row[] = $meet['endtime']; $row[] = format_time($meet['duration']); diff --git a/view.php b/view.php index 1f31fc5e..a071f274 100755 --- a/view.php +++ b/view.php @@ -50,8 +50,8 @@ // Print the page header. $PAGE->set_url('/mod/zoom/view.php', ['id' => $cm->id]); -$PAGE->set_title(format_string($zoom->name)); -$PAGE->set_heading(format_string($course->fullname)); +$PAGE->set_title(format_string($zoom->name, true, ['context' => $context])); +$PAGE->set_heading(format_string($course->fullname, true, ['context' => $context])); $PAGE->requires->js_call_amd("mod_zoom/toggle_text", 'init'); // Get Zoom user ID of current Moodle user. @@ -127,7 +127,7 @@ echo $OUTPUT->header(); if ($CFG->branch < '400') { - echo $OUTPUT->heading(format_string($zoom->name), 2); + echo $OUTPUT->heading(format_string($zoom->name, true, ['context' => $context]), 2); } // Show notification if the meeting does not exist on Zoom. @@ -591,7 +591,7 @@ $meetinginvite = zoom_webservice()->get_meeting_invitation($zoom)->get_display_string($cm->id); // Show meeting invitation if there is any. if (!empty($meetinginvite)) { - $meetinginvitetext = str_replace("\r\n", '
', $meetinginvite); + $meetinginvitetext = str_replace("\r\n", '
', s($meetinginvite)); $showbutton = html_writer::tag( 'button', $strmeetinginviteshow, From 69208ad6b3efb4b80cfd257a958a03a9cd4cf2e1 Mon Sep 17 00:00:00 2001 From: Jonathan Champ Date: Tue, 7 Jul 2026 12:29:55 +0200 Subject: [PATCH 4/6] random: use better system randomness for passcodes --- locallib.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/locallib.php b/locallib.php index 7a809e77..fda49e87 100755 --- a/locallib.php +++ b/locallib.php @@ -504,7 +504,7 @@ function zoom_get_participants_report($detailsid) { */ function zoom_create_default_passcode($meetingpasswordrequirement) { $length = max($meetingpasswordrequirement->length, 6); - $random = rand(0, pow(10, $length) - 1); + $random = random_int(0, (int) pow(10, $length) - 1); $passcode = str_pad(strval($random), $length, '0', STR_PAD_LEFT); // Get a random set of indexes to replace with non-numberic values. @@ -513,14 +513,14 @@ function zoom_create_default_passcode($meetingpasswordrequirement) { if ($meetingpasswordrequirement->have_letter || $meetingpasswordrequirement->have_upper_and_lower_characters) { // Random letter from A-Z. - $passcode[$indexes[0]] = chr(rand(65, 90)); + $passcode[$indexes[0]] = chr(random_int(65, 90)); // Random letter from a-z. - $passcode[$indexes[1]] = chr(rand(97, 122)); + $passcode[$indexes[1]] = chr(random_int(97, 122)); } if ($meetingpasswordrequirement->have_special_character) { $specialchar = '@_*-'; - $passcode[$indexes[2]] = substr(str_shuffle($specialchar), 0, 1); + $passcode[$indexes[2]] = $specialchar[random_int(0, strlen($specialchar) - 1)]; } return $passcode; From 0c38cc91df6febd5cfed87eeb4265b47938937d8 Mon Sep 17 00:00:00 2001 From: Jonathan Champ Date: Tue, 7 Jul 2026 12:30:23 +0200 Subject: [PATCH 5/6] sessions: correctly report endtimes --- locallib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/locallib.php b/locallib.php index fda49e87..6f7b574e 100755 --- a/locallib.php +++ b/locallib.php @@ -270,7 +270,7 @@ function zoom_get_sessions_for_display($zoomid) { $sessions[$uuid]['topic'] = $instance->topic; $sessions[$uuid]['duration'] = $instance->duration; $sessions[$uuid]['starttime'] = userdate($instance->start_time, $format); - $sessions[$uuid]['endtime'] = userdate($instance->start_time + $instance->duration * 60, $format); + $sessions[$uuid]['endtime'] = userdate($instance->start_time + $instance->duration, $format); } return $sessions; From 21d30e7cbcc00a820e9c810b1b0f52812e1aeaba Mon Sep 17 00:00:00 2001 From: Jonathan Champ Date: Tue, 7 Jul 2026 12:57:45 +0200 Subject: [PATCH 6/6] db: fix legacy SQL example --- db/upgrade.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/db/upgrade.php b/db/upgrade.php index 064cc0d9..15beb609 100755 --- a/db/upgrade.php +++ b/db/upgrade.php @@ -61,7 +61,7 @@ function xmldb_zoom_upgrade($oldversion) { // Rename option_no_video_host to option_host_video; change default to 1; invert values. $field = new xmldb_field('option_no_video_host', XMLDB_TYPE_INTEGER, '1', null, null, null, '1', 'option_start_type'); // Invert option_no_video_host. - $DB->set_field('UPDATE {zoom} SET option_no_video_host = 1 - option_no_video_host'); + $DB->execute('UPDATE {zoom} SET option_no_video_host = 1 - option_no_video_host'); $dbman->change_field_default($table, $field); $dbman->rename_field($table, $field, 'option_host_video'); @@ -77,7 +77,7 @@ function xmldb_zoom_upgrade($oldversion) { 'option_host_video' ); // Invert option_no_video_participants. - $DB->set_field('UPDATE {zoom} SET option_no_video_participants = 1 - option_no_video_participants'); + $DB->execute('UPDATE {zoom} SET option_no_video_participants = 1 - option_no_video_participants'); $dbman->change_field_default($table, $field); $dbman->rename_field($table, $field, 'option_participants_video'); @@ -95,7 +95,7 @@ function xmldb_zoom_upgrade($oldversion) { // Change precision/length of duration to 6 digits. $field = new xmldb_field('duration', XMLDB_TYPE_INTEGER, '6', null, null, null, null, 'type'); $dbman->change_field_precision($table, $field); - $DB->set_field('UPDATE {zoom} SET duration = duration*60'); + $DB->execute('UPDATE {zoom} SET duration = duration*60'); upgrade_mod_savepoint(true, 2015071500, 'zoom'); }