summaryrefslogblamecommitdiffstats
path: root/modules-available/statistics/page.inc.php
blob: f07dca568930f7994c8fa07c2e6203b7e3fc522e (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11

     

                                  
                      
 




                                                                     

                                         
                             
                                          


                                                                
 
                                       
                                                      

                 


                                                            
                                                       

                  

                                                                                
                                                                              

                 







                                                                        
                                
                                                                       
                         





                                                                                                   


                                                                                                    
                         
                               

                 


                                       




















                                                                                                                                                        

                                                         
                                                      
                                                     




                                                               

                                              

                                                    



                                                                   



                                                                                




                                                                                                             

         




















                                                                                              
















                                                                                               


                                                              
                                                    








                                                                          















                                                                                                                                


















                                                                                        


                                                                                 



                                                                

                                                                                                            


                                        
                                        











                                                                                                          

         
                                              






                                                                          




                                                                                


                                                                                                                                        
                                        
                                                         
                                                                              
                                                                
                                
                                                                                                          
                         

                                      











                                                                                                                                        

                                   
                                                                                                

                 
 

                                     




                                            
                                                                             
         
 

                                   

                                  

                                                 

                                                                                

                               











                                                                                  
 





                                                                                  
                                                   
                 


                                                                     
                 

                                   
         
 
 
<?php

class Page_Statistics extends Page
{
	private $show;

	/**
	 * @var bool whether we have a SubPage from the pages/ subdir
	 */
	private $haveSubpage;

	protected function doPreprocess()
	{
		User::load();
		if (!User::isLoggedIn()) {
			Message::addError('main.no-permission');
			Util::redirect('?do=Main');
		}

		if (Request::isGet()) {
			$this->transformLegacyQuery();
		}

		/*
		Dictionary::translate('submenu_projectors');
		Dictionary::translate('submenu_replace');
		Dictionary::translate('submenu_hints');
		*/

		foreach (['projectors', 'replace', 'hints'] as $section) {
			Dashboard::addSubmenu('?do=statistics&show=' . $section,
				Dictionary::translate('submenu_' . $section));
		}

		$this->show = Request::any('show', false, 'string');
		if ($this->show === false && Request::isGet()) {
			if (Request::get('uuid') !== false) {
				$this->show = 'machine';
			} elseif (User::hasPermission('view.summary')) {
				$this->show = 'summary';
			} elseif (User::hasPermission('view.list')) {
				$this->show = 'list';
			} else {
				User::assertPermission('view.summary');
			}
		}
		if ($this->show !== false) {
			$this->show = preg_replace('/[^a-z0-9_\-]/', '', $this->show);
			if (!file_exists('modules/statistics/pages/' . $this->show . '.inc.php')) {
				Message::addError('main.invalid-action', $this->show);
			} else {
				require_once 'modules/statistics/pages/' . $this->show . '.inc.php';
				$this->haveSubpage = true;
				SubPage::doPreprocess();
			}
			return;
		}

		if (!Request::isPost())
			return;

		// POST
		$action = Request::post('action');
		if ($action === 'setnotes') {
			$uuid = Request::post('uuid', '', 'string');
			$res = Database::queryFirst('SELECT locationid FROM machine WHERE machineuuid = :uuid',
																array('uuid' => $uuid));
			if ($res === false) {
				Message::addError('unknown-machine', $uuid);
				Util::redirect('?do=statistics');
			}
			User::assertPermission("machine.note.edit", (int)$res['locationid']);
			$text = Request::post('content', null, 'string');
			if (empty($text)) {
				$text = null;
			}
			Database::exec('UPDATE machine SET notes = :text WHERE machineuuid = :uuid', array(
				'uuid' => $uuid,
				'text' => $text,
			));
			Message::addSuccess('notes-saved');
			Util::redirect('?do=statistics&uuid=' . $uuid);
		} elseif ($action === 'clear-machines') {
			$this->deleteMachines(true);
		} elseif ($action === 'delmachines') {
			$this->deleteMachines(false);
			Util::redirect('?do=statistics', true);
		} elseif ($action === 'rebootmachines') {
			$this->rebootControl(true);
		} elseif ($action === 'shutdownmachines') {
			$this->rebootControl(false);
		} elseif ($action === 'wol') {
			$this->wol();
		} elseif ($action === 'benchmark') {
			$this->vmstoreBenchmark();
		} elseif ($action === 'prepare-exec') {
			if (Module::isAvailable('rebootcontrol')) {
				RebootControl::prepareExec();
			}
		} elseif (substr($action, 0, 12) === 'exec-preset-') {
			if (Module::isAvailable('rebootcontrol')) {
				RebootControl::prepareExec(substr($action, 12));
			}
		}

		// Make sure we don't render any content for POST requests - should be handled above and then
		// redirected properly
		Util::redirect('?do=statistics');
	}

	private function transformLegacyQuery()
	{
		if (!Request::isGet())
			return;
		$query = Request::get('filters', false, 'string');
		if ($query === false)
			return;
		foreach (explode(StatisticsFilter::LEGACY_DELIMITER, $query) as $q) {
			if (!preg_match('/^\s*(\w+)\s*([<>=!~]{1,2})\s*(.*?)\s*$/', $q, $out))
				continue;
			$key = $out[1];
			$_GET['filter'][$key] = '1';
			$_GET['op'][$key] = $out[2];
			$_GET['arg'][$key] = $out[3];
		}
		unset($_GET['filters']);
		if (!empty($_GET['filter'])) {
			Util::redirect('?' . http_build_query($_GET));
		}
	}

	private function wol()
	{
		if (!Module::isAvailable('rebootcontrol'))
			return;
		$ids = Request::post('uuid', [], 'array');
		$ids = array_values($ids);
		if (empty($ids)) {
			Message::addError('main.parameter-empty', 'uuid');
			return;
		}
		$this->getAllowedMachines(".rebootcontrol.action.wol", $ids, $allowedMachines);
		if (empty($allowedMachines))
			return;
		$taskid = RebootControl::wakeMachines($allowedMachines);
		Util::redirect('?do=rebootcontrol&show=task&what=task&taskid=' . $taskid);
	}

	/**
	 * @param bool $reboot true = reboot, false = shutdown
	 */
	private function rebootControl(bool $reboot)
	{
		if (!Module::isAvailable('rebootcontrol'))
			return;
		$ids = Request::post('uuid', [], 'array');
		$ids = array_values($ids);
		if (empty($ids)) {
			Message::addError('main.parameter-empty', 'uuid');
			return;
		}
		$this->getAllowedMachines(".rebootcontrol.action." . ($reboot ? 'reboot' : 'shutdown'), $ids, $allowedMachines);
		if (empty($allowedMachines))
			return;
		if ($reboot && Request::post('kexec', false)) {
			$action = RebootControl::KEXEC_REBOOT;
		} elseif ($reboot) {
			$action = RebootControl::REBOOT;
		} else {
			$action = RebootControl::SHUTDOWN;
		}
		$task = RebootControl::execute($allowedMachines, $action, 0);
		if (Taskmanager::isTask($task)) {
			Util::redirect("?do=rebootcontrol&show=task&what=task&taskid=" . $task["id"]);
		}
	}

	/**
	 * @param bool $reboot true = reboot, false = shutdown
	 */
	private function vmstoreBenchmark()
	{
		if (!Module::isAvailable('vmstore'))
			return;
		$ids = Request::post('uuid', [], 'array');
		$ids = array_values($ids);
		if (empty($ids)) {
			Message::addError('main.parameter-empty', 'uuid');
			return;
		}
		$this->getAllowedMachines(".vmstore.benchmark", $ids, $allowedMachines);
		if (empty($allowedMachines))
			return;
		VmStoreBenchmark::prepareSelectDialog($allowedMachines);
	}

	private function getAllowedMachines($permission, $ids, &$allowedMachines)
	{
		$allowedLocations = User::getAllowedLocations($permission);
		if (empty($allowedLocations)) {
			Message::addError('main.no-permission');
			Util::redirect('?do=statistics');
		}
		$res = Database::simpleQuery('SELECT machineuuid, clientip, macaddr, locationid FROM machine
				WHERE machineuuid IN (:ids)', compact('ids'));
		$ids = array_flip($ids);
		$allowedMachines = [];
		$seenLocations = [];
		foreach ($res as $row) {
			unset($ids[$row['machineuuid']]);
			settype($row['locationid'], 'int');
			if (in_array($row['locationid'], $allowedLocations)) {
				$allowedMachines[] = $row;
			} elseif (!isset($seenLocations[$row['locationid']])) {
				Message::addError('locations.no-permission-location', $row['locationid']);
			}
			$seenLocations[$row['locationid']] = true;
		}
		if (!empty($ids)) {
			Message::addWarning('unknown-machine', implode(', ', array_keys($ids)));
		}
	}

	private function deleteMachines($soft)
	{
		$ids = Request::post('uuid', [], 'array');
		$ids = array_values($ids);
		if (empty($ids)) {
			Message::addError('main.parameter-empty', 'uuid');
			return;
		}
		$allowedLocations = User::getAllowedLocations("machine.delete");
		if (empty($allowedLocations)) {
			Message::addError('main.no-permission');
			Util::redirect('?do=statistics');
		}
		$res = Database::simpleQuery('SELECT machineuuid, locationid FROM machine WHERE machineuuid IN (:ids)', compact('ids'));
		$ids = array_flip($ids);
		$delete = [];
		foreach ($res as $row) {
			unset($ids[$row['machineuuid']]);
			if (in_array($row['locationid'], $allowedLocations)) {
				$delete[] = $row['machineuuid'];
			} else {
				Message::addError('locations.no-permission-location', $row['locationid']);
			}
		}
		if (!empty($delete)) {
			if ($soft) {
				// "Soft delete" -- keep all data, but set IP address to 0.0.0.0, so it will not be assigned to its
				// old location anymore. Upon next boot some time in the future, the machine is hopefully relocated
				// to somewhere else and will appear in a new location
				Database::exec("UPDATE machine SET clientip = '0.0.0.0', fixedlocationid = NULL, subnetlocationid = NULL
					WHERE machineuuid IN (:delete)", compact('delete'));
				Message::addSuccess('cleared-n-machines', count($delete));
			} else {
				// Actually purge from DB
				Database::exec('DELETE FROM machine WHERE machineuuid IN (:delete)', compact('delete'));
				Message::addSuccess('deleted-n-machines', count($delete));
			}
		}
		if (!empty($ids)) {
			Message::addWarning('unknown-machine', implode(', ', array_keys($ids)));
		}
	}

	protected function doRender()
	{
		if ($this->haveSubpage) {
			SubPage::doRender();
			return;
		}

		Message::addError('main.value-invalid', 'show', $this->show);
	}

	protected function doAjax()
	{
		if (!User::load())
			return;
		$action = Request::any('action');
		if ($action === 'bios') {
			require_once 'modules/statistics/pages/machine.inc.php';
			SubPage::ajaxCheckBios();
			return;
		}
		if ($action === 'json-lookup') {
			$reply = [];
			foreach (Request::post('list', [], 'array') as $item) {
				$name = PciId::getPciId(PciId::AUTO, $item, true);
				if ($name === false) {
					$name = '?????';
				}
				$reply[$item] = $name;
			}
			header('Content-Type: application/json');
			die(json_encode($reply));
		}

		$param = Request::any('lookup', false, 'string');
		if ($param === false) {
			die('No lookup given');
		}
		$add = '';
		if (preg_match('/^([a-f0-9]{4}):([a-f0-9]{4})$/', $param, $out)) {
			$add = ' (' . $param . ')';
		}
		$cached = PciId::getPciId(PciId::AUTO, $param, true);
		if ($cached === false) {
			$cached = 'Unknown';
		}
		echo $cached, $add;
		exit;
	}

}