zoneminder/web/includes/actions/options.php

284 lines
10 KiB
PHP

<?php
//
// ZoneMinder web action file
// Copyright (C) 2019 ZoneMinder LLC
//
// 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// System edit actions
if ( !canEdit('System') ) {
ZM\Warning('Must have System permissions to perform options actions');
return;
}
global $error_message;
if ( $action == 'delete' ) {
if ( isset($_REQUEST['object']) ) {
if ( $_REQUEST['object'] == 'server' ) {
if ( !empty($_REQUEST['markIds']) ) {
foreach ( $_REQUEST['markIds'] as $Id ) {
dbQuery('DELETE FROM Servers WHERE Id=?', array($Id));
ZM\AuditAction('delete', 'server', $Id, '');
}
}
$refreshParent = true;
} else if ( $_REQUEST['object'] == 'storage' ) {
if ( !empty($_REQUEST['markIds']) ) {
foreach ( $_REQUEST['markIds'] as $Id ) {
dbQuery('DELETE FROM Storage WHERE Id=?', array($Id));
ZM\AuditAction('delete', 'storage', $Id, '');
}
}
$refreshParent = true;
} else if ( $_REQUEST['object'] == 'role' ) {
if ( !empty($_REQUEST['markRids']) ) {
foreach ( $_REQUEST['markRids'] as $Id ) {
dbQuery('DELETE FROM User_Roles WHERE Id=?', array($Id));
ZM\AuditAction('delete', 'role', $Id, '');
}
}
$redirect = '?view=options&tab=roles';
} # end if isset($_REQUEST['object'] )
} else if ( isset($_REQUEST['markUids']) ) {
// deletes users
foreach ($_REQUEST['markUids'] as $markUid) {
dbQuery('DELETE FROM Users WHERE Id = ?', array($markUid));
ZM\AuditAction('delete', 'user', $markUid, '');
}
if ($markUid == $user->Id()) {
userLogout();
$redirect = '?view=login';
} else {
$redirect = '?view=options&tab=users';
}
}
} else if ( $action == 'options' && isset($_REQUEST['tab']) ) {
$result = dbQuery('SELECT Name,Value,Type,`System` FROM Config WHERE Category=? ORDER BY Id ASC', array($_REQUEST['tab']));
if (!$result) {
echo mysql_error();
return;
}
$changed = false;
while ($config = dbFetchNext($result)) {
unset($newValue);
if ( ($config['Type'] == 'boolean') and empty($_REQUEST['newConfig'][$config['Name']]) ) {
$newValue = 0;
} else if (isset($_REQUEST['newConfig'][$config['Name']])) {
$newValue = preg_replace("/\r\n/", "\n", $_REQUEST['newConfig'][$config['Name']]);
}
if (isset($newValue) && ($newValue != $config['Value'])) {
# Handle special cases first
if ($config['Name'] == 'ZM_LANG_DEFAULT') {
# Verify that the language file exists in the lang directory.
if (!file_exists(ZM_PATH_WEB.'/lang/'.$newValue.'.php')) {
$error_message .= 'Error setting ' . $config['Name'].'. New value ' .$newValue.' not saved because '.ZM_PATH_WEB.'/lang/'.$newValue.'.php doesn\'t exist.<br/>';
ZM\Error($error_message);
continue;
}
}
dbQuery('UPDATE Config SET Value=? WHERE Name=?', array($newValue, $config['Name']));
$changed = true;
} # end if value changed
} # end foreach config entry
if ( $changed ) {
ZM\AuditAction('update', 'config', 0, 'Tab: '.$_REQUEST['tab']);
switch ( $_REQUEST['tab'] ) {
case 'system' :
case 'config' :
$restartWarning = true;
break;
case 'API':
case 'web' :
case 'tools' :
break;
case 'logging' :
case 'network' :
case 'mail' :
case 'upload' :
$restartWarning = true;
break;
case 'highband' :
case 'medband' :
case 'lowband' :
break;
}
$redirect = '?view=options&tab='.$_REQUEST['tab'];
loadConfig(false);
# Might need to update auth hash
# This doesn't work because the config are constants and won't really be loaded until the next refresh.
#generateAuthHash(ZM_AUTH_HASH_IPS, true);
}
return;
} else if ($action == 'save') {
if (isset($_REQUEST['object'])) {
if ($_REQUEST['object'] == 'dnsmasq') {
$config = isset($_REQUEST['config']) ? $_REQUEST['config'] : [];
$conf = '';
foreach ($config as $name=>$value) {
if ($name == 'dhcp-host') {
foreach ($value as $mac=>$ip) {
$conf .= $name.'='.$mac.','.$ip.PHP_EOL;
}
} else if ($name == 'dhcp-option') {
foreach ($value as $option_name=>$option_value) {
$conf .= $name.'='.$option_name.','.$option_value.PHP_EOL;
}
} else if (
($name == 'bind-interfaces')
or
($name == 'dhcp-authoritative')
) {
if ($value=='yes') {
$conf .= $name.PHP_EOL;
}
} else if ($name == 'dhcp-range') {
$conf .= $name.'='.$value['min'].','.$value['max'].','.$value['expires'].PHP_EOL;
} else {
if (is_array($value)) {
foreach ($value as $v) {
}
} else {
$conf .= $name.'='.$value.PHP_EOL;
}
}
}
if (false===file_put_contents(ZM_PATH_DNSMASQ_CONF, $conf)) {
ZM\Warning("Failed to writh to ".ZM_PATH_DNSMASQ_CONF);
} else {
exec('sudo -n /bin/systemctl restart dnsmasq.service');
}
exec('sudo -n /bin/systemctl restart dnsmasq.service');
}
}
} else if ($action == 'start') {
if (isset($_REQUEST['object'])) {
if ($_REQUEST['object'] == 'dnsmasq') {
exec('sudo -n /bin/systemctl start dnsmasq.service', $output, $result);
if ($result) {
ZM\Warning("Error execing sudo -n /bin/systemctl start dnsmasq.service. Output: ".implode(PHP_EOL, $output));
} else {
ZM\Debug("Error execing sudo -n /bin/systemctl start dnsmasq.service. Output: ".implode(PHP_EOL, $output));
}
}
}
} else if ($action == 'stop') {
if (isset($_REQUEST['object'])) {
if ($_REQUEST['object'] == 'dnsmasq') {
exec('sudo -n /bin/systemctl stop dnsmasq.service', $output, $result);
if ($result) {
ZM\Warning("Error execing sudo -n /bin/systemctl start dnsmasq.service. Output: ".implode(PHP_EOL, $output));
} else {
ZM\Debug("Error execing sudo -n /bin/systemctl start dnsmasq.service. Output: ".implode(PHP_EOL, $output));
}
}
}
} else if ($action == 'menuitems') {
if (!canEdit('System')) {
ZM\Warning('Need System permission to edit menu items');
} else if (isset($_REQUEST['items'])) {
require_once('includes/MenuItem.php');
$allItems = ZM\MenuItem::find();
foreach ($allItems as $item) {
$id = $item->Id();
$enabled = isset($_REQUEST['items'][$id]['Enabled']) ? 1 : 0;
$label = isset($_REQUEST['items'][$id]['Label']) ? trim($_REQUEST['items'][$id]['Label']) : null;
$sortOrder = isset($_REQUEST['items'][$id]['SortOrder']) ? intval($_REQUEST['items'][$id]['SortOrder']) : $item->SortOrder();
if ($label === '') $label = null;
$iconType = isset($_REQUEST['items'][$id]['IconType']) ? $_REQUEST['items'][$id]['IconType'] : $item->IconType();
if (!in_array($iconType, ['material', 'fontawesome', 'image', 'none'])) $iconType = 'material';
$icon = isset($_REQUEST['items'][$id]['Icon']) ? trim($_REQUEST['items'][$id]['Icon']) : $item->Icon();
if ($icon === '') $icon = null;
// Handle image upload
if (isset($_FILES['items']['name'][$id]['IconFile'])
&& $_FILES['items']['error'][$id]['IconFile'] == UPLOAD_ERR_OK) {
$uploadDir = ZM_PATH_WEB.'/graphics/menu/';
if (!is_dir($uploadDir)) mkdir($uploadDir, 0755, true);
$tmpName = $_FILES['items']['tmp_name'][$id]['IconFile'];
$origName = basename($_FILES['items']['name'][$id]['IconFile']);
$ext = strtolower(pathinfo($origName, PATHINFO_EXTENSION));
$allowedExts = ['png', 'jpg', 'jpeg', 'gif', 'svg', 'webp', 'ico'];
if (in_array($ext, $allowedExts)) {
// Validate it's actually an image (except SVG/ICO)
if ($ext == 'svg' || $ext == 'ico' || getimagesize($tmpName) !== false) {
$safeName = 'menu_'.$id.'_'.time().'.'.$ext;
$destPath = $uploadDir.$safeName;
if (move_uploaded_file($tmpName, $destPath)) {
// Remove old uploaded icon if it exists
if ($item->IconType() == 'image' && $item->Icon() && file_exists(ZM_PATH_WEB.'/'.$item->Icon())) {
unlink(ZM_PATH_WEB.'/'.$item->Icon());
}
$icon = 'graphics/menu/'.$safeName;
$iconType = 'image';
}
}
}
}
// If user cleared icon, reset to default
if ($iconType != 'image' && ($icon === null || $icon === '')) {
$icon = null;
}
$item->save([
'Enabled' => $enabled,
'Label' => $label,
'SortOrder' => $sortOrder,
'Icon' => $icon,
'IconType' => $iconType,
]);
}
}
$redirect = '?view=options&tab=menu';
} else if ($action == 'resetmenu') {
if (!canEdit('System')) {
ZM\Warning('Need System permission to reset menu items');
} else {
// Clean up any uploaded icon files
require_once('includes/MenuItem.php');
$oldItems = ZM\MenuItem::find();
foreach ($oldItems as $item) {
if ($item->IconType() == 'image' && $item->Icon() && file_exists(ZM_PATH_WEB.'/'.$item->Icon())) {
unlink(ZM_PATH_WEB.'/'.$item->Icon());
}
}
dbQuery('DELETE FROM Menu_Items');
dbQuery("INSERT INTO `Menu_Items` (`MenuKey`, `Enabled`, `SortOrder`) VALUES
('Console', 1, 10),
('Montage', 1, 20),
('MontageReview', 1, 30),
('Events', 1, 40),
('Options', 1, 50),
('Log', 1, 60),
('Devices', 1, 70),
('IntelGpu', 1, 80),
('Groups', 1, 90),
('Filters', 1, 100),
('Snapshots', 1, 110),
('Reports', 1, 120),
('ReportEventAudit', 1, 130),
('Map', 1, 140)");
}
$redirect = '?view=options&tab=menu';
} // end if object vs action
?>