MRBS 1.12.2 等保2.0二级整改完整提交
包含:登录失败锁定、90天密码有效期、30分钟会话超时、 强制改密、登录审计日志、屏幕水印、企业背景图、 备案信息固定底部、favicon、JS空集合保护、 会话过期体验优化(403 JSON)、display_errors 关闭、 固定 key 根治 Integrity check failed 等全部改动 注意:config.inc.php/.htaccess/.user.ini 含敏感信息, 通过 .gitignore 排除,勿推送到公开仓库。
This commit is contained in:
+371
@@ -0,0 +1,371 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace MRBS;
|
||||
|
||||
use MRBS\Form\ElementInputSubmit;
|
||||
use MRBS\Form\Form;
|
||||
|
||||
require "defaultincludes.inc";
|
||||
|
||||
function display_buttons(array $row, bool $is_series) : void
|
||||
{
|
||||
global $reminders_enabled, $reminder_interval;
|
||||
|
||||
$last_reminded = (empty($row['reminded'])) ? $row['last_updated'] : $row['reminded'];
|
||||
$returl = multisite(this_page());
|
||||
|
||||
$target_id = ($is_series) ? $row['repeat_id'] : $row['id'];
|
||||
|
||||
// When we're going to view_entry.php we need to pass the id and series in a
|
||||
// query string rather than as hidden inputs. That's because some pages called
|
||||
// by view_entry use $_SERVER['HTTP_REFERER'] to form a return URL, and view_entry
|
||||
// needs to have a valid id.
|
||||
$query_string = "id=$target_id";
|
||||
$query_string .= ($is_series) ? "&series=1" : "";
|
||||
|
||||
if (is_book_admin($row['room_id']))
|
||||
{
|
||||
// approve
|
||||
$form = new Form(Form::METHOD_POST);
|
||||
|
||||
$attributes = array('action' => multisite('approve_entry_handler.php'));
|
||||
$form->setAttributes($attributes);
|
||||
|
||||
$hidden_inputs = array('action' => 'approve',
|
||||
'id' => $target_id,
|
||||
'series' => ($is_series) ? 1 : 0,
|
||||
'returl' => $returl);
|
||||
$form->addHiddenInputs($hidden_inputs);
|
||||
|
||||
$element = new ElementInputSubmit();
|
||||
$element->setAttribute('value', get_vocab('approve'));
|
||||
$form->addElement($element);
|
||||
|
||||
$form->render();
|
||||
|
||||
// reject
|
||||
$form = new Form(Form::METHOD_POST);
|
||||
|
||||
$attributes = array('action' => multisite("view_entry.php?$query_string"));
|
||||
$form->setAttributes($attributes);
|
||||
|
||||
$hidden_inputs = array('action' => 'reject',
|
||||
'returl' => $returl);
|
||||
$form->addHiddenInputs($hidden_inputs);
|
||||
|
||||
$element = new ElementInputSubmit();
|
||||
$element->setAttribute('value', get_vocab('reject'));
|
||||
$form->addElement($element);
|
||||
|
||||
$form->render();
|
||||
|
||||
// more info
|
||||
$info_time = ($is_series) ? $row['repeat_info_time'] : $row['entry_info_time'];
|
||||
$info_user = ($is_series) ? $row['repeat_info_user'] : $row['entry_info_user'];
|
||||
if (empty($info_time))
|
||||
{
|
||||
$info_title = get_vocab("no_request_yet");
|
||||
}
|
||||
else
|
||||
{
|
||||
$info_title = get_vocab("last_request") . ' ' . time_date_string($info_time);
|
||||
if (!empty($info_user))
|
||||
{
|
||||
$info_title .= " " . get_vocab("by") . " $info_user";
|
||||
}
|
||||
}
|
||||
|
||||
$form = new Form(Form::METHOD_POST);
|
||||
|
||||
$attributes = array('action' => multisite("view_entry.php?$query_string"));
|
||||
$form->setAttributes($attributes);
|
||||
|
||||
$hidden_inputs = array('action' => 'more_info',
|
||||
'returl' => $returl);
|
||||
$form->addHiddenInputs($hidden_inputs);
|
||||
|
||||
$element = new ElementInputSubmit();
|
||||
$element->setAttributes(array('value' => get_vocab('more_info'),
|
||||
'title' => $info_title));
|
||||
$form->addElement($element);
|
||||
|
||||
$form->render();
|
||||
}
|
||||
else
|
||||
{
|
||||
// get the area settings for this room
|
||||
get_area_settings(get_area($row['room_id']));
|
||||
// if enough time has passed since the last reminder
|
||||
// output a "Remind Admin" button, otherwise nothing
|
||||
if ($reminders_enabled &&
|
||||
(working_time_diff(time(), $last_reminded) >= $reminder_interval))
|
||||
{
|
||||
$form = new Form(Form::METHOD_POST);
|
||||
|
||||
$attributes = array('action' => multisite('approve_entry_handler.php'));
|
||||
$form->setAttributes($attributes);
|
||||
|
||||
$hidden_inputs = array('action' => 'remind',
|
||||
'id' => $row['id'],
|
||||
'returl' => $returl);
|
||||
$form->addHiddenInputs($hidden_inputs);
|
||||
|
||||
$element = new ElementInputSubmit();
|
||||
$element->setAttribute('value', get_vocab('remind_admin'));
|
||||
$form->addElement($element);
|
||||
|
||||
$form->render();
|
||||
}
|
||||
else
|
||||
{
|
||||
echo " ";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function display_table_head() : void
|
||||
{
|
||||
echo "<thead>\n";
|
||||
echo "<tr>\n";
|
||||
// We give some columns a type data value so that the JavaScript knows how to sort them
|
||||
echo "<th class=\"control\"> </th>\n";
|
||||
echo "<th class=\"header_name\">" . get_vocab("entry") . "</th>\n";
|
||||
echo "<th class=\"header_create\">" . get_vocab("createdby") . "</th>\n";
|
||||
echo "<th class=\"header_area\">" . get_vocab("area") . "</th>\n";
|
||||
echo "<th class=\"header_room\">" . get_vocab("room") . "</th>\n";
|
||||
echo "<th class=\"header_start_time\"><span class=\"normal\" data-type=\"title-numeric\">" . get_vocab("start_date") . "</span></th>\n";
|
||||
echo "<th class=\"header_duration\"><span class=\"normal\" data-type=\"title-numeric\">" . get_vocab("duration") . "</span></th>\n";
|
||||
echo "<th class=\"header_end_time\"><span class=\"normal\" data-type=\"title-numeric\">" . get_vocab("end_date") . "</span></th>\n";
|
||||
echo "<th class=\"header_action\">" . get_vocab("action") . "</th>\n";
|
||||
echo "</tr>\n";
|
||||
echo "</thead>\n";
|
||||
}
|
||||
|
||||
// display the table head for a subtable
|
||||
function display_subtable_head(array $row) : void
|
||||
{
|
||||
echo "<thead>\n";
|
||||
echo "<tr>\n";
|
||||
// We give some columns a type data value so that the JavaScript knows how to sort them
|
||||
echo "<th class=\"control\"> </th>\n";
|
||||
// reservation name, with a link to the view_entry page
|
||||
echo '<th><a href="' . escape_html(multisite('view_entry.php?id=' . $row['repeat_id'] . '&series=1')) . '">' .
|
||||
escape_html($row['name']) ."</a></th>\n";
|
||||
|
||||
// create_by, area and room names
|
||||
echo "<th>" . escape_html($row['create_by']) . "</th>\n";
|
||||
echo "<th>" . escape_html($row['area_name']) . "</th>\n";
|
||||
echo "<th>" . escape_html($row['room_name']) . "</th>\n";
|
||||
|
||||
echo "<th><span class=\"normal\" data-type=\"title-numeric\">" . get_vocab("series") . "</span></th>\n";
|
||||
echo "<th> </th>\n";
|
||||
echo "<th> </th>\n";
|
||||
|
||||
echo "<th> </th>\n";
|
||||
echo "</tr>\n";
|
||||
echo "</thead>\n";
|
||||
}
|
||||
|
||||
|
||||
// display the title row for a series
|
||||
function display_series_title_row(array $row) : void
|
||||
{
|
||||
echo "<tr id=\"row_" . $row['repeat_id'] . "\">\n";
|
||||
echo "<td class=\"control\"> </td>\n";
|
||||
// reservation name, with a link to the view_entry page
|
||||
echo '<td><a href="' . escape_html(multisite('view_entry.php?id=' . $row['repeat_id'] . '&series=1')) . '">' .
|
||||
escape_html($row['name']) ."</a></td>\n";
|
||||
|
||||
// create_by, area and room names
|
||||
echo "<td>" . escape_html(auth()->getDisplayName($row['create_by'])) . "</td>\n";
|
||||
echo "<td>" . escape_html($row['area_name']) . "</td>\n";
|
||||
echo "<td>" . escape_html($row['room_name']) . "</td>\n";
|
||||
|
||||
echo "<td>";
|
||||
// <span> for sorting
|
||||
echo "<span title=\"" . $row['start_time'] . "\"></span>";
|
||||
echo get_vocab("series");
|
||||
echo "</td>\n";
|
||||
|
||||
echo "<th><span title=\"0\"></span> </th>\n";
|
||||
echo "<th><span title=\"0\"></span> </th>\n";
|
||||
|
||||
echo "<td>\n";
|
||||
display_buttons($row, true);
|
||||
echo "</td>\n";
|
||||
echo "</tr>\n";
|
||||
}
|
||||
|
||||
// display an entry in a row
|
||||
function display_entry_row(array $row) : void
|
||||
{
|
||||
global $view;
|
||||
|
||||
echo "<tr>\n";
|
||||
echo "<td> </td>\n";
|
||||
|
||||
// reservation name, with a link to the view_entry page
|
||||
echo "<td>";
|
||||
echo '<a href="' . escape_html(multisite('view_entry.php?id=' . $row['id'])) . '"' .
|
||||
' title="' . escape_html($row['description']) . '">' .
|
||||
escape_html($row['name']) ."</a></td>\n";
|
||||
|
||||
// create_by, area and room names
|
||||
echo "<td>" . escape_html(auth()->getDisplayName($row['create_by'])) . "</td>\n";
|
||||
echo "<td>" . escape_html($row['area_name']) . "</td>\n";
|
||||
echo "<td>" . escape_html($row['room_name']) . "</td>\n";
|
||||
|
||||
// start date, with a link to the calendar view
|
||||
$link = getdate($row['start_time']);
|
||||
echo "<td>";
|
||||
// <span> for sorting
|
||||
echo "<span title=\"" . $row['start_time'] . "\"></span>";
|
||||
|
||||
$vars = array('view' => $view,
|
||||
'year' => $link['year'],
|
||||
'month' => $link['mon'],
|
||||
'day' => $link['mday'],
|
||||
'area' => $row['area_id'],
|
||||
'room' => $row['room_id']);
|
||||
|
||||
$query = http_build_query($vars, '', '&');
|
||||
|
||||
echo '<a href="' . escape_html(multisite("index.php?$query")) . '">';
|
||||
$link_str = date_string(!empty($row['enable_periods']), $row['start_time'], $row['area_id']);
|
||||
echo escape_html($link_str) . "</a></td>";
|
||||
|
||||
$duration = get_duration($row['start_time'], $row['end_time'], !empty($row['enable_periods']), $row['area_id'], false);
|
||||
$duration_seconds = $row['end_time'] - $row['start_time'] - cross_dst($row['start_time'], $row['end_time']);
|
||||
echo "<td><span title=\"" . $duration_seconds . "\"></span>" . escape_html($duration['duration'] . " " . get_vocab($duration['dur_units'])) . "</td>\n";
|
||||
|
||||
// End date
|
||||
$end_date_str = date_string(!empty($row['enable_periods']), $row['end_time'], $row['area_id'], true);
|
||||
echo "<td><span title=\"" . $row['end_time'] . "\"></span>" . escape_html($end_date_str) . "</td>\n";
|
||||
|
||||
// action buttons
|
||||
echo "<td>\n";
|
||||
display_buttons($row, false);
|
||||
echo "</td>\n";
|
||||
echo "</tr>\n";
|
||||
}
|
||||
|
||||
|
||||
// Check the user is authorised for this page
|
||||
checkAuthorised(this_page());
|
||||
|
||||
$mrbs_user = session()->getCurrentUser();
|
||||
$mrbs_username = (isset($mrbs_user)) ? $mrbs_user->username : null;
|
||||
|
||||
$context = array(
|
||||
'view' => $view,
|
||||
'view_all' => $view_all,
|
||||
'year' => $year,
|
||||
'month' => $month,
|
||||
'day' => $day,
|
||||
'area' => $area,
|
||||
'room' => isset($room) ? $room : null
|
||||
);
|
||||
|
||||
print_header($context);
|
||||
|
||||
echo "<h1>" . get_vocab("pending") . "</h1>\n";
|
||||
|
||||
// Get a list of all bookings awaiting approval
|
||||
// We are only interested in areas where approval is required
|
||||
|
||||
$sql_approval_enabled = some_area_predicate('approval_enabled');
|
||||
|
||||
$sql = "SELECT E.id, E.name, E.description, E.room_id, E.start_time, E.end_time, E.create_by, " .
|
||||
db()->syntax_timestamp_to_unix("E.timestamp") . " AS last_updated,
|
||||
E.reminded, E.repeat_id,
|
||||
M.room_name, M.area_id, A.area_name, A.enable_periods,
|
||||
E.info_time AS entry_info_time, E.info_user AS entry_info_user,
|
||||
T.info_time AS repeat_info_time, T.info_user AS repeat_info_user
|
||||
FROM " . _tbl('room') . " AS M, " . _tbl('area') . " AS A, " . _tbl('entry') . " AS E
|
||||
LEFT JOIN " . _tbl('repeat') . " AS T ON E.repeat_id=T.id
|
||||
WHERE E.room_id = M.id
|
||||
AND M.area_id = A.id
|
||||
AND M.disabled = 0
|
||||
AND A.disabled = 0
|
||||
AND $sql_approval_enabled
|
||||
AND (E.status&" . STATUS_AWAITING_APPROVAL . " != 0)";
|
||||
|
||||
// We want entries for a series to appear together so that we can display
|
||||
// them as a separate table below the main entry for the series.
|
||||
$sql .= " ORDER BY repeat_id, start_time";
|
||||
|
||||
$res = db()->query($sql);
|
||||
|
||||
$rows = array();
|
||||
|
||||
while (false !== ($row = $res->next_row_keyed()))
|
||||
{
|
||||
row_cast_columns($row, 'entry');
|
||||
// Turn these columns into ints (some MySQL drivers will return a string,
|
||||
// and they won't have been caught by row_cast_columns() as they are derived results).
|
||||
$row['last_updated'] = intval($row['last_updated']);
|
||||
$row['entry_info_time'] = intval($row['entry_info_time']);
|
||||
$row['repeat_info_time'] = intval($row['repeat_info_time']);
|
||||
// And this comes from the area table
|
||||
$row['area_id'] = intval($row['area_id']);
|
||||
if ((compare_usernames($row['create_by'], $mrbs_username) === 0) || is_book_admin($row['room_id']))
|
||||
{
|
||||
$rows[] = $row;
|
||||
}
|
||||
}
|
||||
|
||||
if (count($rows) == 0)
|
||||
{
|
||||
echo "<p>" .get_vocab("none_outstanding") . "</p>\n";
|
||||
}
|
||||
else // display them in a table
|
||||
{
|
||||
echo "<div id=\"pending_list\" class=\"datatable_container\">\n";
|
||||
echo "<table id=\"pending_table\" class=\"admin_table display\">\n";
|
||||
display_table_head();
|
||||
|
||||
echo "<tbody>\n";
|
||||
$last_repeat_id = null;
|
||||
$is_series = false;
|
||||
foreach ($rows as $row)
|
||||
{
|
||||
if ($row['repeat_id'] != $last_repeat_id)
|
||||
// there's some kind of change
|
||||
{
|
||||
$last_repeat_id = $row['repeat_id'];
|
||||
if ($is_series)
|
||||
{
|
||||
// end the last series table if there was one
|
||||
$is_series = false;
|
||||
echo "</tbody></table></div></td></tr>\n";
|
||||
}
|
||||
|
||||
if (!empty($row['repeat_id']))
|
||||
{
|
||||
// we're starting a new series
|
||||
$is_series = true;
|
||||
// Put in the title row
|
||||
display_series_title_row($row);
|
||||
echo "<tr class=\"sub_table\">\n";
|
||||
echo "<td class=\"sub_table\" colspan=\"7\">";
|
||||
$table_id = "subtable_" . $row['repeat_id'];
|
||||
echo "<div class=\"details\">\n";
|
||||
echo "<table id=\"$table_id\" class=\"admin_table display sub\">\n";
|
||||
display_subtable_head($row);
|
||||
echo "<tbody>\n";
|
||||
}
|
||||
}
|
||||
display_entry_row($row);
|
||||
}
|
||||
if ($is_series)
|
||||
{
|
||||
// if we were in a series, then close the sub-table
|
||||
echo "</tbody></table></div></td></tr>\n";
|
||||
}
|
||||
echo "</tbody>\n";
|
||||
echo "</table>\n";
|
||||
echo "</div>\n";
|
||||
}
|
||||
|
||||
print_footer();
|
||||
Reference in New Issue
Block a user