Skip to content
Commits on Source (3)
1.9.17
* FIX: Fix PHP 5.3 incompatibility introduced with 1.9.16
* FIX: Fix IE 11 incompatibility on worldmaps in relation to lines
which was introduced with 1.9.13
* FIX: Fix incompatibility with Check 1.6 auth cookies of users with special
characters in the user ID
1.9.16
Core:
* Add support for Encrypted livestatus. You can now configure "tcp-tls:[address]:[port]"
as socket address and control the TLS verification using the new backend specific
settings "verify_tls_peer" and "verify_tls_ca_path".
1.9.15
Core:
* FIX: "You are not permitted to access this page (ChangePassword/view/)" for users (issue #215)
Frontend:
* FIX: Fix IE 11 incompatibility regression introduced with 1.9.13
1.9.14
Core:
* MKBI backend: Use "htmlcgi" URL/path for building links to the Checkmk GUI
(Aggregations used the base_url, which should not be used for user URLs)
Worldmap:
* Consistent page reloads: center + zoom of the map kept in URL
* Memory and performance optimization: line rendering - clip long lines protruding out of viewport
* Memory and performance optimization: fix getMapObject SQL query (lng/lat rectangle)
Frontend
* FIX: Fix creating users when mbstring extension is not available
1.9.13
Worldmap:
* Configurable OpenStreetMap tile server URL (worldmap_tiles_{url,attribution})
* OpenStreetMap tile colors can now be dimmed using the
worldmap_tiles_saturate configuration option so that larger colorful
backgrounds do not interfere with the map objects.
* Optional 2nd map layer (satellite imagery)
* FIX: Worldmap textbox visibility per zoom level
* FIX: The "clone object" functionality did sometimes break with an error
message like "Invalid argument supplied for foreach()"
(Thanks to Vojtech Pithart for taking the time to improve the NagVis worldmap!)
1.9.12
Core:
* FIX: Allow "*" character to be part of backend dbpass values
* Multisite Snapin: Reworked data export API to snapin. The new API is
compatible with Checkmk 1.6b2 and newer.
Frontend
* FIX: Fixed incompatibility with PHP 7.2 (count(STRING)) when creating roles
Geomap:
* Improved error handling of CSV lines with less than 4 fields
1.9.11
Frontend
* FIX: Weathermap lines now respect the configured error colors
......@@ -66,7 +124,7 @@ Core:
(Configure this per object by adding the attribute hover_childs_sort=k).
Frontend:
* On demand automaps: Hostgroup filter in header menu is now a searchable dropdown field
* On demand automaps: Hostgroup filter in header menu is now a searchable dropdown field
* FIX: Fixed moving textbox objects in IE
1.9.3
......@@ -89,7 +147,7 @@ Core:
1.9.1
Core:
* FIX: Fixed incompatibility with pecl-http (Cannot redeclare http_redirect())
* FIX: Fixed incompatibility with pecl-http (Cannot redeclare http_redirect())
* FIX: Fixed duplicate global section in sample automaps after editing
Frontend:
......@@ -627,9 +685,9 @@ Automap:
1.8b3
Frontend:
* Added option "zoom_scale_objects" to default section of global config to
allow users to control the scaling behaviour of zoomed objects. By
default the whole maps is zoomed like in previous versions. But when
zoom_scale_objects is set to 0, the map objects and labels are not
allow users to control the scaling behaviour of zoomed objects. By
default the whole maps is zoomed like in previous versions. But when
zoom_scale_objects is set to 0, the map objects and labels are not
resized, but only repositioned according to the given zoom factor.
* FIX: Fixed broken NagVis Multisite sidebar dashlet
* FIX: Fixed showing URLs as hover menus (hover_url option)
......@@ -641,7 +699,7 @@ Frontend:
Core:
* Allowing ~ chars in URLs now (Thanks to Daniel Albers for the patch)
* FIX: Fixed rare occuring encoding problems of vars in several places
* FIX: Fixed rare occuring encoding problems of vars in several places
* FIX: Fixed PHP error with map objects linking to not existing maps
* FIX: Trying to workaround broken processing of non UTF-8 pages in hover_urls
......@@ -662,7 +720,7 @@ Core:
* FIX: Fixed host alias attribute in livestatus backend
* Dropped the merlinmy backend for the moment as it was not working for a
time. Please provide a fixed one if you like to see this working again
* FIX: Fixed PHP errors when acknowleding host/service problems
* FIX: Fixed PHP errors when acknowleding host/service problems
* FIX: Fixed missing values alias, display_name, address values in hover templates
Installer:
......@@ -690,7 +748,7 @@ Core:
filter on the map. In first instance it automatically gathers the list of
objects to add on this map and positions them in a grid on the map. The
user can then modify all the objects, for example change their options
like, positions and visualisation.
like, positions and visualisation.
* Changed default http_timeout from 10 to 2 seconds
* Added new iconset std_area, which can be used to create maps which are
visible from a greater distance
......@@ -763,13 +821,13 @@ Geomap:
Frontend:
* FIX: Fixed "Undefined index" error when changing backend_id of maps
* FIX: Fixed hiding of shapes during refresh (enable_refresh=1)
* Reverted change from 1.7.5 (Weathermap lines with byte/bit values in
* Reverted change from 1.7.5 (Weathermap lines with byte/bit values in
labels should print human) which broke the handling for some plugins
1.7.7
Core:
* Implemented "on demand" maps. Maps which only need a basic configuration
of global parameters like automaps and geomaps can now be configured and
of global parameters like automaps and geomaps can now be configured and
created on demand by URL parameters. This mode is reached by simply
calling the map URL without "show=" parameter and a bunch of parameters
for the global section of the map instead.
......@@ -920,7 +978,7 @@ Core
Frontend
* Added new map config option (global section) event_on_load to raise frontend events
also on page loading
* Added new options event_repeat_interval and event_repeat_duration to
* Added new options event_repeat_interval and event_repeat_duration to
configured repeated frontend events
* Added rotations to sidebar
* Info page shows json_encode/json_decode capability of used PHP
......@@ -1095,7 +1153,7 @@ Core
* NagVis creates now "omdadmin" user in OMD environments when creating new auth.db files
* Bugfix: Added missing default permissions for guest role (viewing demo maps)
* Bugfix: Fixed version number format for stable versions like (1.6)
Frontend
* Ajax call for redrawing map objects is not cacheable anymore (prevent strange
hopping of icons after unlock -> edit -> lock in some cases.
......@@ -1192,7 +1250,7 @@ Frontend
* Bugfix: Don't hide dependent fiels where the master attribute is not available
* Bugfix: Fixed map global section editing
* Bugfix: IE8 fixing event registration (javascript errors on page loading)
* Updating map object information while having the hover menu open does not close
* Updating map object information while having the hover menu open does not close
open hover menus anymore
1.6rc1
......
nagvis (1:1.9.11-2) UNRELEASED; urgency=medium
nagvis (1:1.9.17-1) unstable; urgency=medium
[ Debian Janitor ]
* Trim trailing whitespace.
......@@ -12,7 +12,10 @@ nagvis (1:1.9.11-2) UNRELEASED; urgency=medium
[ Bas Couwenberg ]
* Add Bug-* fields to upstream metadata.
-- Debian Janitor <janitor@jelmer.uk> Wed, 11 Dec 2019 00:49:40 +0000
[ Adam Cecile ]
* New upstream release (Closes: #949387).
-- Adam Cecile <acecile@le-vert.net> Mon, 20 Jan 2020 16:02:56 +0100
nagvis (1:1.9.11-1) unstable; urgency=medium
......
......@@ -26,7 +26,21 @@
<tr>
<td>socket</td>
<td>unix:/usr/local/nagios/var/rw/live</td>
<td><p>The socket to connect to can be a local unix socket or a tcp socket. You have to define the type at the beginning of the string. Set &quot;unix:&quot; for unix sockets or &quot;tcp:&quot; for tcp sockets.</p> <p>In case of the unix socket you need to specify the path of the livestatus unix socket to connect to.</p> <p>When using a tcp socket you have to enter a host address and a tcp port using the following scheme: &lt;host>:&lt;port>. The host address can be an IP address or an FQDN.</p></td>
<td><p>The socket to connect to can be a local unix socket or a tcp
socket. You have to define the type at the beginning of the string.
Set &quot;unix:&quot; for unix sockets or &quot;tcp:&quot; for tcp
sockets.</p>
<p><font color="#f00">New in 1.9.16</font>:Since Checkmk 1.6.0 it is possible to encrypt the Livestatus
channel using TLS. To connnect to such a channel use &quot;tcp-tls:&quot;.</p>
<p>In case of the unix socket you need to specify the
path of the livestatus unix socket to connect to.</p>
<p>When using a tcp socket you have to enter a host address and a
tcp port using the following scheme: &lt;host>:&lt;port>. The host address can
be an IP address or an FQDN.</p>
</td>
</tr><tr>
<td>timeout</td>
<td>5</td>
......@@ -35,6 +49,25 @@
This is just a fallback. To prevent timeouts when accessing remote sites you really should configure a statushost for the backend.
For details take a look at the general backend parameters documented in the <a href="nagvis_config_format_description.html#backend">backend section</a>
of the main configuration format description.</a></td>
</tr><tr>
<td>verify_tls_peer</td>
<td>1</td>
<td>
<font color="#f00">New in 1.9.16</font>: Only relevant when you connect to a Livestatus TLS encrypted socket.
This can be used to turn off the peer certificate verification. In case it is enabled, you will have to
set the <tt>verify_tls_ca_path</tt> option.
</td>
</tr><tr>
<td>verify_tls_ca_path</td>
<td></td>
<td>
<font color="#f00">New in 1.9.16</font>: Configure an absolute
path that points to a CA chain file which is then used to verify the
certificate of the Livestatus TLS server. You can, for example in Checkmk
sites, point it to the, "Trusted certificate authorities file of Checkmk
(/omd/sites/[site-id]/var/ssl/ca-certificates.crt) to use the same trust
configuration in NagVis and Checkmk.
</td>
</tr>
</table>
<p>There are also some general parameters. You can read about them in <a href="nagvis_config_format_description.html#backend">main configuration format description</a>.</p>
......
......@@ -101,6 +101,28 @@
<td>http://geomap.nagvis.org/</td>
<td>The server to use as source for the NagVis geomaps. Must implement the API which can be found <a href="http://pafciu17.dev.openstreetmap.org/">here</a></td>
</tr>
<tr>
<td>worldmap_tiles_url <font color="#ff0000">(new in 1.9.13)</font></td>
<td>https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png</td>
<td>Worldmap uses OpenStreetMap tiles as default map background. The URL specifies where to GET the PNG tile images from.</td>
</tr>
<tr>
<td>worldmap_tiles_attribution <font color="#ff0000">(new in 1.9.13)</font></td>
<td>&copy; &lt;a href="http://www.openstreetmap.org/copyright"&gt;OpenStreetMap&lt;/a&gt;</td>
<td>Map tiles attribution text (shown in bottom right corner)</td>
</tr>
<tr>
<td>worldmap_satellite_tiles_url<br>
worldmap_satellite_tiles_attribution<br>
<font color="#ff0000">(new in 1.9.13)</font>
</td>
<td></td>
<td>Secondary map background tiles (satellite images) URL and attribution.
When used, the <a href="https://leafletjs.com/reference-1.5.0.html#control-layers">layers control</a>
appears on top right corner of the map.
</td>
</tr>
<tr>
<td>http_proxy <font color="#ff0000">(new in 1.6)</font></td>
......
......@@ -22,12 +22,13 @@
<h2>Prerequisites</h2>
<p>There is no special software needed on the NagVis server, but there is one special requirement. To
be able to use this feature, the browser opening NagVis worldmaps needs to be able to fetch the background
images (map tiles) from the internet. In most corporate environments this means that your client needs
images (map tiles) from the internet, or a local mirror, see below. In most corporate environments this means that your client needs
to have a proxy server configured.</p>
<p>The worldmaps currently use the official tile servers of Open Street Map
(<code>https://{s}.tile.openstreetmap.org/</code>). This is currently hardcoded, but might be made configurable
in the future.</p>
<p>The worldmaps use the official tile servers of Open Street Map (<code>https://{s}.tile.openstreetmap.org/</code>) as a default.
Alternative tile server (local mirror) may be set in configuration, for example: <code>worldmap_tiles_url="http://my-tiles.local/{z}/{x}/{y}.png"</code> </p>
<p>The <a href="https://switch2osm.org/serving-tiles/">switch2osm guides</a> might help you to spin up your local OpenStreetMap mirror.</p>
<h2>The first call</h2>
<p>NagVis comes with a demo worldmap called "demo-worldmap". If your NagVis is configured correctly
and your browser is able to fetch the background images from the tile server, you should see a map
......@@ -37,7 +38,7 @@
<p>This worldmap is defined using the map configuration file "demo-worldmap.cfg". The contents
look like this:</p>
<pre>define global {
alias=Demo: 4 Worldmap
parent_map=demo-overview
......@@ -48,6 +49,7 @@
sources=worldmap
worldmap_center=50.86837814203458,10.21728515625
worldmap_zoom=6
worldmap_tiles_saturate=33
}</pre>
<p>Only the last three attributes are worldmap specific definitions, all of them are mandatory for
......@@ -62,6 +64,8 @@
<p>The <code>worldmap_zoom=6</code> specifies the initial zoom level to be used when rendering the worldmap.
NagVis allows zoom levels from 2 to 18.</p>
<p>The <code>worldmap_tiles_saturate=33</code> dims the colors of default OpenStreetMap so that red motorways or
large green forests don't interfere with actual map objects. Possible values are 0 (no colors, grayscale) through 100 (full colors).</p>
<h2>Create your own worldmap</h2>
......
......@@ -6,6 +6,7 @@ define global {
backend_id=demo
worldmap_center=50.86837814203458,10.21728515625
worldmap_zoom=6
worldmap_tiles_saturate=33
iconset=std_geo
icon_size=32
}
......@@ -71,6 +71,14 @@
; can be found on http://pafciu17.dev.openstreetmap.org/
;geomap_server="http://geomap.nagvis.org/"
;
; Public or private mirror of OpenStreetMap tiles server
;worldmap_tiles_url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
;worldmap_tiles_attribution="&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>"
;
; Secondary "satellite" tiles server
;worldmap_satellite_tiles_url=""
;worldmap_satellite_tiles_attribution=""
;
; In some cases NagVis needs to open connections to the internet. The cases are:
; - The new geomap needs access to openstreetmap webservices to be able to fetch
; mapping information
......
......@@ -716,7 +716,7 @@ var ElementHover = Element.extend({
var regex = getRegEx('loopChild', "<!--\\sBEGIN\\sloop_child\\s-->(.+?)<!--\\sEND\\sloop_child\\s-->");
if(this.template_html.search(regex) !== -1)
this.template_html = this.template_html.replace(regex, '<!-- BEGIN loop_child -->'
+ g_hover_template_childs[this.obj.hover_template]
+ g_hover_template_childs[this.obj.conf.hover_template]
+ '<!-- END loop_child -->');
// Search for images and append current timestamp to src (prevent caching of
......
......@@ -340,6 +340,16 @@ var ElementLine = Element.extend({
var xEnd = x[x.length - 1];
var yEnd = y[y.length - 1];
let adjustedPoints = this.cutLineBeyondViewport(xStart, yStart, xEnd, yEnd);
if (adjustedPoints === null) {
return; // Line won't be visible -> this.parts left empty -> no rendering
}
xStart = adjustedPoints[0];
yStart = adjustedPoints[1];
xEnd = adjustedPoints[2];
yEnd = adjustedPoints[3];
var width = addZoomFactor(this.obj.conf.line_width);
if (width <= 0)
width = 1; // minimal width for lines
......@@ -422,6 +432,10 @@ var ElementLine = Element.extend({
},
renderLine: function() {
if (this.parts.length === 0) {
return;
}
var allX = [], allY = [];
for (var i = 0, len = this.parts.length; i < len; i++) {
allX = allX.concat(this.parts[i][2]);
......@@ -948,6 +962,147 @@ var ElementLine = Element.extend({
]);
}
return parsed;
}
},
/*
* There is a rectangle: viewport (current Leaflet map shown) + 10% on each side.
* This function cuts the lines protruding beyond the rectangle.
* Shortened lines prevent renderLine() from generating many vast <canvas> (10000-ish pixels) which eventually lead
* to memory exhaustion or crash the browser
*
* Returns:
* either: [xA, yA, xB, yB] - original or adjusted line A/B coordinates,
* or: null - line out of a rectangle, don't render
*/
cutLineBeyondViewport: function(xA, yA, xB, yB) {
if (!g_map)
return([xA, yA, xB, yB]); // no viewport - no clipping
let viewport_size = g_map.getSize();
const xMax = viewport_size.x; // 1920
const yMax = viewport_size.y; // 1080
const xTolerance = xMax * 0.1; // 192 (10%)
const yTolerance = yMax * 0.1; // 108 (10%)
// Cohen-Sutherland algorithm
// region codes
const INSIDE = 0; // 0000
const LEFT = 1; // 0001
const RIGHT = 2; // 0010
const BOTTOM = 4; // 0100
const TOP = 8; // 1000
// boundaries
const x_min = -xTolerance;
const x_max = xMax + xTolerance;
const y_min = -yTolerance;
const y_max = yMax + yTolerance;
// Function to compute region code
let regionCode = function (x, y)
{
let code = INSIDE;
if (x < x_min) // to the left of rectangle
code |= LEFT;
else if (x > x_max) // to the right of rectangle
code |= RIGHT;
if (y < y_min) // below the rectangle
code |= BOTTOM;
else if (y > y_max) // above the rectangle
code |= TOP;
return code;
}
let cohenSutherlandClip = function (x1, y1, x2, y2) {
let code1 = regionCode(x1, y1);
let code2 = regionCode(x2, y2);
let accept = false;
while (true)
{
if ((code1 == 0) && (code2 == 0))
{
// If both endpoints lie within rectangle
accept = true;
break;
}
else if (code1 & code2)
{
// If both endpoints are outside rectangle,
// in same region
break;
}
else
{
// Some segment of line lies within the
// rectangle
let code_out;
let x, y;
// At least one endpoint is outside the
// rectangle, pick it.
if (code1 != 0)
code_out = code1;
else
code_out = code2;
// Find intersection point;
// using formulas y = y1 + slope * (x - x1),
// x = x1 + (1 / slope) * (y - y1)
if (code_out & TOP)
{
// point is above the clip rectangle
x = x1 + (x2 - x1) * (y_max - y1) / (y2 - y1);
y = y_max;
}
else if (code_out & BOTTOM)
{
// point is below the rectangle
x = x1 + (x2 - x1) * (y_min - y1) / (y2 - y1);
y = y_min;
}
else if (code_out & RIGHT)
{
// point is to the right of rectangle
y = y1 + (y2 - y1) * (x_max - x1) / (x2 - x1);
x = x_max;
}
else if (code_out & LEFT)
{
// point is to the left of rectangle
y = y1 + (y2 - y1) * (x_min - x1) / (x2 - x1);
x = x_min;
}
// Now intersection point x,y is found
// We replace point outside rectangle
// by intersection point
if (code_out == code1)
{
x1 = x;
y1 = y;
code1 = regionCode(x1, y1);
}
else
{
x2 = x;
y2 = y;
code2 = regionCode(x2, y2);
}
}
}
if (accept)
return([x1, y1, x2, y2]);
else
return null;
}
return cohenSutherlandClip(xA, yA, xB, yB);
},
});
......@@ -436,20 +436,33 @@ var NagVisStatefulObject = NagVisObject.extend({
var sColor = oStates[this.conf.summary_state].color;
// Use these classes (icon-flashing-<state>) in your custom css to customise flashing icons
// e.g. icon-flashing-critical, icondiv-flashing-critical
// Note you may need to use '!important' to override the inline default
//
var sFlashingClass = 'icon-flashing-' + this.conf.summary_state.toLowerCase();
var sFlashingDivClass = 'icondiv-flashing-' + this.conf.summary_state.toLowerCase();
this.bIsFlashing = show;
if(show) {
oObjIcon.style.border = "5px solid " + sColor;
oObjIcon.classList.add(sFlashingClass);
oObjIconDiv.style.top = (this.parseCoord(this.conf.y, 'y') - 5) + 'px';
oObjIconDiv.style.left = (this.parseCoord(this.conf.x, 'x') - 5) + 'px';
oObjIconDiv.classList.add(sFlashingDivClass);
} else {
oObjIcon.style.border = "none";
oObjIcon.classList.remove(sFlashingClass);
oObjIconDiv.style.top = this.parseCoord(this.conf.y, 'y') + 'px';
oObjIconDiv.style.left = this.parseCoord(this.conf.x, 'x') + 'px';
oObjIconDiv.classList.remove(sFlashingDivClass);
}
sColor = null;
oObjIconDiv = null;
oObjIcon = null;
},
sColor = null;
sFlashingClass = null;
sFlashingDivClass = null;
oObjIconDiv = null;
oObjIcon = null;
}
});
......@@ -55,16 +55,41 @@ var ViewWorldmap = ViewMap.extend({
initWorldmap: function() {
L.Icon.Default.imagePath = oGeneralProperties.path_base+'/frontend/nagvis-js/images/leaflet';
var layers = {
"map": L.tileLayer(oGeneralProperties.worldmap_tiles_url, {
attribution: oGeneralProperties.worldmap_tiles_attribution,
noWrap: true, // don't repeat the world on horizontal axis
detectRetina: true, // look nice on high resolution screens
maxZoom: 20,
}),
}
if(oGeneralProperties.worldmap_satellite_tiles_url) {
layers.satellite = L.tileLayer(oGeneralProperties.worldmap_satellite_tiles_url, {
attribution: oGeneralProperties.worldmap_satellite_tiles_attribution,
noWrap: true, // don't repeat the world on horizontal axis
detectRetina: true, // look nice on high resolution screens
maxZoom: 20,
})
}
g_map = L.map('map', {
markerZoomAnimation: false,
maxBounds: [ [-85,-180.0], [85,180.0] ],
minZoom: 2
}).setView(getViewParam('worldmap_center').split(','), parseInt(getViewParam('worldmap_zoom')));
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>',
noWrap: true, // don't repeat the world on horizontal axe
detectRetina: true, // look nice on high resolution screens
}).addTo(g_map);
minZoom: 2,
layers: [layers.map]
})
let restored_coordinates = window.location.hash.substr(1).split('/');
if (restored_coordinates.length === 3) {
// place the map view according to location hash (#lat/lon/zoom) - consistent page reloads
g_map.setView([restored_coordinates[1], restored_coordinates[0]], restored_coordinates[2]);
} else {
// or default (map-defined) view
g_map.setView(getViewParam('worldmap_center').split(','), parseInt(getViewParam('worldmap_zoom')));
}
if (layers.satellite)
L.control.layers(layers).addTo(g_map);
g_map_objects = L.layerGroup().addTo(g_map);
......@@ -80,6 +105,12 @@ var ViewWorldmap = ViewMap.extend({
if (typeof checkHideMenu !== "undefined")
g_map.on('mousedown', checkHideMenu);
g_map.on('mousedown', context_handle_global_mousedown);
// dim the colors of map background so that red motorways don't distract
let saturate_percentage = getViewParam('worldmap_tiles_saturate');
let ltp = document.getElementsByClassName('leaflet-tile-pane');
if (ltp && saturate_percentage !== '')
ltp[0].style.filter = "saturate("+saturate_percentage+"%)";
},
handleMoveStart: function(lEvent) {
......@@ -94,6 +125,10 @@ var ViewWorldmap = ViewMap.extend({
setViewParam('worldmap_zoom', g_map.getZoom());
this.render(); // re-render the whole map
// Put the new map view coords into URL (location) - consistent reloads
new_center = g_map.getCenter();
window.location.hash = new_center.lng + "/" + new_center.lat + "/" + g_map.getZoom();
},
saveView: function() {
......
......@@ -79,7 +79,11 @@ class CoreLogonMultisite extends CoreLogonModule {
throw new Exception();
}
list($username, $issueTime, $cookieHash) = explode(':', $_COOKIE[$cookieName], 3);
// Checkmk 1.6+ may add double quotes round the value in some cases
// (e.g. when @ signs are found in the value)
$cookieValue = trim($_COOKIE[$cookieName], '"');
list($username, $issueTime, $cookieHash) = explode(':', $cookieValue, 3);
if($this->authFile == 'htpasswd')
$users = $this->loadAuthFile($this->htpasswdPath);
......
......@@ -39,15 +39,25 @@ class CoreModMultisite extends CoreModule {
if(!$this->offersAction($this->sAction))
return '';
$maps = array();
switch($this->sAction) {
case 'getMaps':
if (cfg('global', 'multisite_snapin_layout') == 'tree') {
return $this->renderTree();
$maps = array(
"type" => "tree",
"maps" => $this->renderTree(),
);
} else {
return $this->renderTable();
$maps = array(
"type" => "table",
"maps" => $this->renderTable(),
);
}
break;
}
return json_encode($maps);
}
private function renderTree() {
......@@ -55,102 +65,38 @@ class CoreModMultisite extends CoreModule {
$childs = array();
foreach ($this->getMapsCached() as $map) {
if($map['parent_map'] === '')
$maps[$map['name']] = $map;
$maps[$map['name']] = $this->getMapForMultisite($map);
else {
if(!isset($childs[$map['parent_map']]))
$childs[$map['parent_map']] = Array();
$childs[$map['parent_map']][$map['name']] = $map;
}
}
$s = '<ul>'.$this->renderTreeNodes($maps, $childs).'</ul>';
// FIXME: check_mk/tree_state.py?tree=nagvis holen
// evaluieren
// alles was auf off steht per toggle_foldable_container schließen
return $s.$this->renderFootnotelinks();
}
private function renderTreeNodes($maps, $childs) {
$s = '';
foreach($maps AS $map) {
// this copies the foldable_container code provided in Check_MK htmllib
// assume always open by default
$s .= '<li>';
$map_url = cfg('paths', 'htmlbase').'/index.php?mod=Map&act=view&show='.$map['name'];
if(isset($childs[$map['name']])) {
$act = 'onclick="toggle_foldable_container(\'nagvis\', \''.$map['name'].'\')" '
. 'onmouseover="this.style.cursor=\'pointer\';" '
. 'onmouseout="this.style.cursor=\'auto\';"';
$s .= '<img align=absbottom class="treeangle" id="treeimg.nagvis.'.$map['name'].'" '
. 'src="images/tree_90.png" '.$act.' />';
$s .= '<a href="'.$map_url.'" target="main"><b class="treeangle title" class=treeangle>';
$s .= $map['alias'];
$s .= '</b></a><br>';
$s .= '<ul class="treeangle open" style="padding-left:0;" id="tree.nagvis.'.$map['name'].'">';
$s .= $this->renderTreeNodes($childs[$map['name']], $childs);
$s .= '</ul>';
} else {
$s .= '<a target="main" href="'.$map_url.'">'.$map['alias'].'</a>';
$childs[$map['parent_map']][$map['name']] = $this->getMapForMultisite($map);
}
$s .= '</li>';
}
return $s;
return array(
"maps" => $maps,
"childs" => $childs,
);
}
private function renderTable() {
$code = '<table class="allhosts"><tbody>';
$maps = array();
foreach ($this->getMapsCached() as $map) {
switch($map['summary_state']) {
case 'OK':
case 'UP':
$state = '0';
break;
case 'WARNING':
$state = '1';
break;
case 'CRITICAL':
case 'DOWN':
case 'UNREACHABLE':
$state = '2';
break;
default:
$state = '3';
break;
}
$title = $map['summary_state'];
if ($map['summary_in_downtime']) {
$state .= ' stated';
$title .= ' (Downtime)';
}
elseif ($map['summary_problem_has_been_acknowledged']) {
$state .= ' statea';
$title .= ' (Acknowledged)';
}
if ($map['summary_stale']) {
$state .= ' stale';
$title .= ' (Stale)';
}
$code .= '<tr><td>';
$code .= '<div class="statebullet state'.$state.'" title="'.$title.'">&nbsp;</div>';
$code .= '<a href="'.cfg('paths', 'htmlbase').'/index.php?mod=Map&act=view&show='.$map['name'].'" ';
$code .= 'class="link" target="main">'.$map['alias'].'</a>';
$code .= '</td></tr>';
$maps[] = $this->getMapForMultisite($map);
}
$code .= '</tbody></table>';
return $code.$this->renderFootnotelinks();
return $maps;
}
private function renderFootnoteLinks() {
$url = cfg('paths', 'htmlbase');
return "<div class=footnotelink>"
."<a onfocus=\"if (this.blur) this.blur();\" target=\"main\" class=\"link\" href=\"".$url."/\">EDIT</a>"
."</div>";
private function getMapForMultisite($map) {
return array(
"name" => $map["name"],
"title" => $map['summary_state'],
"alias" => $map['alias'],
"url" => cfg('paths', 'htmlbase').'/index.php?mod=Map&act=view&show='.$map['name'],
"summary_state" => $map["summary_state"],
"summary_in_downtime" => $map['summary_in_downtime'],
"summary_problem_has_been_acknowledged" => $map['summary_problem_has_been_acknowledged'],
"summary_stale" => $map['summary_stale'],
);
}
// Wraps the getMaps() function by applying a short livetime cache based
......
......@@ -63,6 +63,7 @@ class CorePDOHandler {
.'WHERE users2roles."userId" = :id',
'-perm-rename-map' => 'UPDATE perms SET obj=:new_name '.
' WHERE "mod"=\'Map\' AND obj=:old_name',
'-perm-change-act' => 'UPDATE perms SET act=:new_act WHERE mod=:mod and act=:old_act',
'-role-add' => 'INSERT INTO roles (name) VALUES (:name)',
'-role-add-with-id' => 'INSERT INTO roles ("roleId", name) VALUES (:roleId, :name)',
......@@ -128,6 +129,10 @@ class CorePDOHandler {
),
'updates' => array(
'1091500' => array(
array('-perm-change-act', array('mod' => 'ChangePassword', 'old_act' => 'change', 'new_act' => '*'))
),
'1080600' => array(
array('-perm-add', array('mod' => 'Url', 'act' => 'view', 'obj' => '*')),
array('-create-pop-roles-perms-3', array(
......@@ -261,6 +266,7 @@ class CorePDOHandler {
}
$drv_data = self::$DRIVERS[$driver];
$dsn = "$driver:".$drv_data['build_dsn']($params);
$this->dsn = $dsn;
try {
$this->DB = new PDO($dsn, $username, $password, array(
......@@ -270,12 +276,12 @@ class CorePDOHandler {
));
} catch(PDOException $e) {
error_log('Could not initialize a database connection: '.$e->getMessage());
$this->lastErrorInfo = $e->getMessage();
return false;
}
}
if($this->DB === false || $this->DB === null)
return false;
$this->dsn = $dsn;
$this->driver = $driver;
$this->data = $drv_data;
$this->updating = false;
......@@ -286,6 +292,7 @@ class CorePDOHandler {
$res = $this->DB->exec($q);
if($res === false) {
$this->DB = null;
$this->lastErrorInfo = "Initial DB query ($q) failed";
return false;
}
}
......@@ -356,7 +363,7 @@ class CorePDOHandler {
if (isset($this->lastErrorInfo))
return $this->lastErrorInfo;
else
return $this->DB->errorInfo();
return $this->DB ? $this->DB->errorInfo() : '';
}
public function errorString() {
......@@ -460,7 +467,7 @@ class CorePDOHandler {
try {
ksort(self::$DRIVERS['_common']['updates']);
foreach (self::$DRIVERS['_common']['updates'] as $ver => $queries) {
if (intval($ver) <= $dbVersion)
if (intval($ver) < $dbVersion)
continue;
if (!$this->inTrans) {
......@@ -583,7 +590,7 @@ class CorePDOHandler {
$this->queryFatal('-perm-add', array('mod' => 'User', 'act' => 'setOption', 'obj' => '*'));
// Access controll: Change own password
$this->queryFatal('-perm-add', array('mod' => 'ChangePassword', 'act' => 'change', 'obj' => '*'));
$this->queryFatal('-perm-add', array('mod' => 'ChangePassword', 'act' => '*', 'obj' => '*'));
// Access controll: View maps via multisite
$this->queryFatal('-perm-add', array('mod' => 'Multisite', 'act' => 'getMaps', 'obj' => '*'));
......@@ -618,7 +625,7 @@ class CorePDOHandler {
// Access control: View URLs e.g. in rotation pools
$this->queryFatal('-perm-add', array('mod' => 'Url', 'act' => 'view', 'obj' => '*'));
// Assign the new permission to the managers, users, guests
$this->queryFatal('-create-pop-roles-perms-3', array(
'r1' => 'Managers', 'r2' => 'Users (read-only)', 'r3' => 'Guests',
......
......@@ -127,7 +127,8 @@ class GlobalBackendmkbi implements GlobalBackendInterface {
}
private function aggrUrl($name) {
return $this->baseUrl.'view.py?view_name=aggr_single&aggr_name='.$name.'&po_aggr_expand=1';
$html_cgi = cfg('backend_'.$this->backendId, 'htmlcgi');
return $html_cgi.'/view.py?view_name=aggr_single&aggr_name='.$name.'&po_aggr_expand=1';
}
/**
......
......@@ -37,6 +37,7 @@
class GlobalBackendmklivestatus implements GlobalBackendInterface {
private $backendId = '';
private $CONNECT_ERR = "";
private $CONNECT_EXC = null;
private $SOCKET = null;
private $socketType = '';
......@@ -52,6 +53,19 @@ class GlobalBackendmklivestatus implements GlobalBackendInterface {
'default' => 'unix:/usr/local/nagios/var/rw/live',
'match' => MATCH_SOCKET,
),
'verify_tls_peer' => Array(
'must' => 0,
'editable' => 1,
'default' => 1,
'match' => MATCH_BOOLEAN,
'field_type' => 'boolean',
),
'verify_tls_ca_path' => Array(
'must' => 0,
'editable' => 1,
'default' => '',
'match' => MATCH_STRING_PATH,
),
'timeout' => Array(
'must' => 1,
'editable' => 1,
......@@ -118,7 +132,7 @@ class GlobalBackendmklivestatus implements GlobalBackendInterface {
if($type === 'unix') {
$this->socketType = $type;
$this->socketPath = $address;
} elseif($type === 'tcp') {
} elseif($type === 'tcp' || $type === 'tcp-tls') {
$this->socketType = $type;
// Extract address and port
......@@ -126,6 +140,7 @@ class GlobalBackendmklivestatus implements GlobalBackendInterface {
$this->socketAddress = $address;
$this->socketPort = $port;
} else {
throw new BackendConnectionProblem(
l('Unknown socket type given in backend [BACKENDID]',
......@@ -170,31 +185,77 @@ class GlobalBackendmklivestatus implements GlobalBackendInterface {
if($this->CONNECT_EXC != null)
throw $this->CONNECT_EXC;
set_error_handler(array($this, 'connectErrorHandler'), E_WARNING | E_NOTICE);
// Connect to the socket
// don't want to see the connection error messages - want to handle the
// errors later with an own error message
// FIXME: Maybe use pfsockopen in the future to use persistent connections
if($this->socketType === 'unix') {
$oldLevel = error_reporting(0);
$this->SOCKET = fsockopen('unix://'.$this->socketPath, NULL, $errno, $errstr, (float) cfg('backend_'.$this->backendId, 'timeout'));
error_reporting($oldLevel);
} elseif($this->socketType === 'tcp-tls') {
if (cfg('backend_'.$this->backendId, 'verify_tls_peer') == true) {
$ssl_options = Array(
'verify_peer' => true,
'verify_peer_name' => false,
'verify_depth' => 1,
);
$ca_path = cfg('backend_'.$this->backendId, 'verify_tls_ca_path');
if ($ca_path)
$ssl_options['cafile'] = $ca_path;
$context = stream_context_create(Array(
'ssl' => $ssl_options
));
} else {
$context = stream_context_create(Array(
'ssl' => Array(
'verify_peer' => false,
'verify_peer_name' => false
)
));
}
$this->SOCKET= stream_socket_client(
"tls://" . $this->socketAddress . ":" . $this->socketPort, $errno, $errstr,
(float) cfg('backend_'.$this->backendId, 'timeout'), STREAM_CLIENT_CONNECT,
$context);
} elseif($this->socketType === 'tcp') {
$oldLevel = error_reporting(0);
$this->SOCKET = fsockopen($this->socketAddress, $this->socketPort, $errno, $errstr, (float) cfg('backend_'.$this->backendId, 'timeout'));
error_reporting($oldLevel);
$this->SOCKET = fsockopen($this->socketAddress, $this->socketPort, $errno, $errstr,
(float) cfg('backend_'.$this->backendId, 'timeout'));
}
restore_error_handler();
if(!$this->SOCKET) {
if ($errno === 0)
$error_msg = $this->CONNECT_ERR;
else
$error_msg = $errstr;
$this->SOCKET = null;
$this->CONNECT_EXC = new BackendConnectionProblem(
l('Unable to connect to the [SOCKET] in backend [BACKENDID]: [MSG]',
Array('BACKENDID' => $this->backendId,
'SOCKET' => $this->socketPath,
'MSG' => $errstr)));
'MSG' => $error_msg)));
throw $this->CONNECT_EXC;
}
}
/**
* Catch PHP errors occured during connect
*/
public function connectErrorHandler($errno, $errstr) {
if (($errno & E_WARNING) === 0 && ($errno & E_NOTICE) === 0) {
return false; // use default error handler
}
$this->CONNECT_ERR .= $errstr . "\n";
return true;
}
/*private function verifyLivestatusVersion() {
$result = $this->queryLivestatusSingleColumn("GET status\nColumns: livestatus_version\n");
$result[0] = '1.1.7rc1';
......
......@@ -154,6 +154,27 @@ class GlobalMainCfg {
'match' => MATCH_STRING_URL,
),
'worldmap_tiles_url' => array(
'must' => 0,
'default' => 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
'match' => MATCH_STRING_URL,
),
'worldmap_tiles_attribution' => array(
'must' => 0,
'default' => '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>',
'match' => MATCH_ALL
),
'worldmap_satellite_tiles_url' => array(
'must' => 0,
'default' => '',
'match' => MATCH_STRING_URL,
),
'worldmap_satellite_tiles_attribution' => array(
'must' => 0,
'default' => '',
'match' => MATCH_ALL
),
'http_proxy' => array(
'must' => 0,
'default' => null,
......@@ -655,7 +676,7 @@ class GlobalMainCfg {
'must' => 0,
'editable' => 1,
'default' => '0',
'match' => MATCH_BOOLEAN,
'match' => MATCH_BOOLEAN,
'field_type' => 'boolean',
),
'line_weather_colors' => Array(
......@@ -2184,6 +2205,11 @@ class GlobalMainCfg {
'internal_title' => $this->getValue('internal', 'title'),
'header_show_states' => intval($this->getValue('defaults', 'header_show_states')),
'zoom_scale_objects' => intval($this->getValue('defaults', 'zoom_scale_objects')),
'worldmap_tiles_url' => $this->getValue('global', 'worldmap_tiles_url'),
'worldmap_tiles_attribution' => $this->getValue('global', 'worldmap_tiles_attribution'),
'worldmap_satellite_tiles_url' => $this->getValue('global', 'worldmap_satellite_tiles_url'),
'worldmap_satellite_tiles_attribution' => $this->getValue('global', 'worldmap_satellite_tiles_attribution'),
// Add custom action configuration
);
// Add custom action configuration
......
......@@ -35,7 +35,7 @@ class ViewManageRoles {
if (!$name)
throw new FieldInputError('name', l('Please specify a name'));
if (count($name) > AUTH_MAX_ROLENAME_LENGTH)
if (strlen($name) > AUTH_MAX_ROLENAME_LENGTH)
throw new FieldInputError('name', l('This name is too long'));
if (!preg_match(MATCH_ROLE_NAME, $name))
......
......@@ -35,7 +35,7 @@ class ViewManageUsers {
if (!$name)
throw new FieldInputError('name', l('Please specify a name.'));
if (mb_strlen($name) > AUTH_MAX_USERNAME_LENGTH)
if (strlen($name) > AUTH_MAX_USERNAME_LENGTH)
throw new FieldInputError('name', l('This name is too long.'));
if (!preg_match(MATCH_USER_NAME, $name))
......@@ -49,7 +49,7 @@ class ViewManageUsers {
if (!$password1)
throw new FieldInputError('password1', l('Please specify a password.'));
if (mb_strlen($password1) > AUTH_MAX_PASSWORD_LENGTH)
if (strlen($password1) > AUTH_MAX_PASSWORD_LENGTH)
throw new FieldInputError('password1', l('This password is too long.'));
$password2 = post('password2');
......@@ -254,7 +254,7 @@ class ViewManageUsers {
if (!$password1)
throw new FieldInputError('password1', l('Please specify a password.'));
if (mb_strlen($password1) > AUTH_MAX_PASSWORD_LENGTH)
if (strlen($password1) > AUTH_MAX_PASSWORD_LENGTH)
throw new FieldInputError('password1', l('This password is too long.'));
$password2 = post('password2');
......