1<?php 2/* Icinga Web 2 | (c) 2013 Icinga Development Team | GPLv2+ */ 3 4namespace Icinga\Module\Monitoring; 5 6use Icinga\Exception\ConfigurationError; 7use Icinga\Exception\QueryException; 8use Icinga\Data\Filter\Filter; 9use Icinga\Data\Filterable; 10use Icinga\File\Csv; 11use Icinga\Util\Json; 12use Icinga\Web\Controller as IcingaWebController; 13use Icinga\Web\Url; 14 15/** 16 * Base class for all monitoring action controller 17 */ 18class Controller extends IcingaWebController 19{ 20 /** 21 * The backend used for this controller 22 * 23 * @var Backend 24 */ 25 protected $backend; 26 27 protected function moduleInit() 28 { 29 $this->backend = Backend::createBackend($this->_getParam('backend')); 30 $this->view->url = Url::fromRequest(); 31 } 32 33 protected function handleFormatRequest($query) 34 { 35 $desiredContentType = $this->getRequest()->getHeader('Accept'); 36 if ($desiredContentType === 'application/json') { 37 $desiredFormat = 'json'; 38 } elseif ($desiredContentType === 'text/csv') { 39 $desiredFormat = 'csv'; 40 } else { 41 $desiredFormat = strtolower($this->params->get('format', 'html')); 42 } 43 44 if ($desiredFormat !== 'html' && ! $this->params->has('limit')) { 45 $query->limit(); // Resets any default limit and offset 46 } 47 48 switch ($desiredFormat) { 49 case 'sql': 50 echo '<pre>' 51 . htmlspecialchars(wordwrap($query->dump())) 52 . '</pre>'; 53 exit; 54 case 'json': 55 $response = $this->getResponse(); 56 $response 57 ->setHeader('Content-Type', 'application/json') 58 ->setHeader('Cache-Control', 'no-store') 59 ->setHeader( 60 'Content-Disposition', 61 'inline; filename=' . $this->getRequest()->getActionName() . '.json' 62 ) 63 ->appendBody(Json::sanitize($query->fetchAll())) 64 ->sendResponse(); 65 exit; 66 case 'csv': 67 $response = $this->getResponse(); 68 $response 69 ->setHeader('Content-Type', 'text/csv') 70 ->setHeader('Cache-Control', 'no-store') 71 ->setHeader( 72 'Content-Disposition', 73 'attachment; filename=' . $this->getRequest()->getActionName() . '.csv' 74 ) 75 ->appendBody((string) Csv::fromQuery($query)) 76 ->sendResponse(); 77 exit; 78 } 79 } 80 81 /** 82 * Apply a restriction of the authenticated on the given filterable 83 * 84 * @param string $name Name of the restriction 85 * @param Filterable $filterable Filterable to restrict 86 * 87 * @return Filterable The filterable having the restriction applied 88 */ 89 protected function applyRestriction($name, Filterable $filterable) 90 { 91 $filterable->applyFilter($this->getRestriction($name)); 92 return $filterable; 93 } 94 95 /** 96 * Get a restriction of the authenticated 97 * 98 * @param string $name Name of the restriction 99 * 100 * @return Filter Filter object 101 * @throws ConfigurationError If the restriction contains invalid filter columns 102 */ 103 protected function getRestriction($name) 104 { 105 $restriction = Filter::matchAny(); 106 $restriction->setAllowedFilterColumns(array( 107 'host_name', 108 'hostgroup_name', 109 'instance_name', 110 'service_description', 111 'servicegroup_name', 112 function ($c) { 113 return preg_match('/^_(?:host|service)_/i', $c); 114 } 115 )); 116 foreach ($this->getRestrictions($name) as $filter) { 117 if ($filter === '*') { 118 return Filter::matchAll(); 119 } 120 try { 121 $restriction->addFilter(Filter::fromQueryString($filter)); 122 } catch (QueryException $e) { 123 throw new ConfigurationError( 124 $this->translate( 125 'Cannot apply restriction %s using the filter %s. You can only use the following columns: %s' 126 ), 127 $name, 128 $filter, 129 implode(', ', array( 130 'instance_name', 131 'host_name', 132 'hostgroup_name', 133 'service_description', 134 'servicegroup_name', 135 '_(host|service)_<customvar-name>' 136 )), 137 $e 138 ); 139 } 140 } 141 142 if ($restriction->isEmpty()) { 143 return Filter::matchAll(); 144 } 145 146 return $restriction; 147 } 148} 149