[-]
[+]
|
Changed |
icingaweb2.spec
|
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/.travis.yml
^
|
@@ -7,9 +7,28 @@
- '7.0'
- '7.1'
- '7.2'
+ - '7.3'
- nightly
+env:
+ - CHECK=phpunit
+
matrix:
+ include:
+ - env: CHECK=phpcs
+ php: '7.3'
+ - env: CHECK=phpcs
+ php: '7.0'
+ - env: CHECK=phpcs
+ php: '5.6'
+ - env: CHECK=syntax
+ php: 'nightly'
+ - env: CHECK=syntax
+ php: '7.3'
+ - env: CHECK=syntax
+ php: '7.0'
+ - env: CHECK=syntax
+ php: '5.6'
allow_failures:
- php: nightly
@@ -32,12 +51,13 @@
# also see: test/setup_vendor.sh
before_script:
- php -m
- - sh -c '[ -z $LOCALE_GEN ] || sudo locale-gen en_US.UTF-8 de_DE.UTF-8 fr_FR.UTF-8'
- - sh -c '[ -z $ENABLE_LDAP ] || phpenv config-add test/travis-ldap.ini'
- - test/travis_database.sh
+ - '[ -z $LOCALE_GEN ] || sudo locale-gen en_US.UTF-8 de_DE.UTF-8 fr_FR.UTF-8'
+ - '[ -z $ENABLE_LDAP ] || phpenv config-add test/travis-ldap.ini'
- test/setup_vendor.sh
+ - 'if [ "$CHECK" = phpunit ]; then test/travis_database.sh; fi'
script:
# also see: modules/test/application/clicommands/PhpCommand.php
- - php phpcs.phar
- - php phpunit.phar -c modules/test/phpunit.xml --verbose
+ - 'if [ "$CHECK" = phpcs ]; then php vendor/phpcs.phar; fi'
+ - 'if [ "$CHECK" = phpunit ]; then php vendor/phpunit.phar -c modules/test/phpunit.xml --verbose; fi'
+ - 'if [ "$CHECK" = syntax ]; then php test/check-syntax.php -e "^(\./)?vendor/" -e Icinga/Util/String.php; fi'
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/CHANGELOG.md
^
|
@@ -4,6 +4,68 @@
## What's New
+### What's New in Version 2.6.3
+
+You can find issues related to this release on our [Roadmap](https://github.com/Icinga/icingaweb2/milestone/54?closed=1).
+
+#### PHP 7.3
+
+Now supported. :tada:
+
+#### LDAP - Community contributions, that's the spirit
+
+With the help of our users we've finally fixed the issue that defining multiple hostnames and enabling STARTTLS has
+never properly worked. Also, they've identified that defining multiple hostnames caused a customized port not being
+utilized and fixed it themselves.
+
+There has also a rare case been fixed that caused no group members being found in case object classes had a different
+casing than what we expected. (Good news for all the non-OpenLdap and non-MSActiveDirectory users)
+
+* LDAP connection fails with multiple servers using STARTTLS [#3639](https://github.com/Icinga/icingaweb2/issues/3639)
+* LDAPS authentication ignores custom port setting [#3713](https://github.com/Icinga/icingaweb2/issues/3713)
+* LDAP group members not found [#3650](https://github.com/Icinga/icingaweb2/issues/3650)
+
+#### We take care about your data even better now
+
+With this are newlines and HTML entities (such as ` `) in plugin output and custom variables meant.
+Sorry if I've teased some data security folks now. :innocent:
+
+* Newlines in plugin output disappear [#3662](https://github.com/Icinga/icingaweb2/issues/3662)
+* Windows path separators are converted to newlines in custom variables [#3636](https://github.com/Icinga/icingaweb2/issues/3636)
+* HTML entities in plugin output are not resolved if no other HTML is there [#3707](https://github.com/Icinga/icingaweb2/issues/3707)
+
+#### You've wondered how you got into a famous blue police box?
+
+Don't worry, not only you and the european union are sometimes unsure what's the correct time.
+
+* Set client timezone on DB connection [#3525](https://github.com/Icinga/icingaweb2/issues/3525)
+* Ensure a valid default timezone is set in any case [#3747](https://github.com/Icinga/icingaweb2/pull/3747)
+* Fix that the event detail view is not showing times in correct timezone [#3660](https://github.com/Icinga/icingaweb2/pull/3660)
+
+#### UI - The portal to your monitoring environment, improved
+
+The collapsible sidebar introduced with v2.5 has been plagued by some issues since then. They're now fixed. Also,
+the UI should now flicker less and properly preserve the scroll position when interacting with action links. (This
+also allows the business process module to behave more stable when using drag and drop in large configurations.)
+
+* Collapsible Sidebar Issues [#3187](https://github.com/Icinga/icingaweb2/issues/3187)
+* Fix title when closing right column [#3654](https://github.com/Icinga/icingaweb2/issues/3654)
+* Preserve scroll position upon form submits [#3661](https://github.com/Icinga/icingaweb2/pull/3661)
+
+#### Corrected things we've broke recently
+
+That's due to preemptive changes to protect you from bad individuals. Unfortunately this meant that some unforeseen
+side-effects appeared after the release of v2.6.2. These are now fixed.
+
+* Multiline values in ini files broken [#3705](https://github.com/Icinga/icingaweb2/issues/3705)
+* PHP ini parser doesn't strip trailing whitespace [#3733](https://github.com/Icinga/icingaweb2/issues/3733)
+* Escaped characters in INI values are not unescaped [#3648](https://github.com/Icinga/icingaweb2/issues/3648)
+
+Though, if you've faced issue [#3705](https://github.com/Icinga/icingaweb2/issues/3705) you still need to take manual
+action (if not already done) as the provided fix does only prevent further occurrences of the resulting error. The
+required changes involve the transformation of all real newlines in Icinga Web 2's INI files to literal `\n` or `\r\n`
+sequences. (Files likely having such are the `roles.ini` and `announcements.ini`)
+
### What's New in Version 2.6.2
You can find issues and features related to this release on our [Roadmap](https://github.com/Icinga/icingaweb2/milestone/53?closed=1).
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/VERSION
^
|
@@ -1 +1 @@
-v2.6.2
+v2.6.3
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/application/VERSION
^
|
@@ -1 +1 @@
-63cb9d728338225833884fda2c312a5a9f431fd6 2018-11-21 09:19:00 +0100
+0d119242ba1728f4b617000a1bd14a230f96f2ee 2019-04-25 10:40:53 +0200
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/application/controllers/StaticController.php
^
|
@@ -52,7 +52,11 @@
return;
}
- $img = file_get_contents('http://www.gravatar.com/avatar/' . $filename . '?s=120&d=mm');
+ $img = @file_get_contents('http://www.gravatar.com/avatar/' . $filename . '?s=120&d=mm');
+ if ($img === false) {
+ $this->httpNotFound('Unable to connect to gravatar.com');
+ }
+
$cache->store($cacheFile, $img);
$response->setHeader('ETag', sprintf('"%s"', $cache->etagForCachedFile($cacheFile)));
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/application/forms/Config/Resource/LdapResourceForm.php
^
|
@@ -48,38 +48,7 @@
'The hostname or address of the LDAP server to use for authentication.'
. ' You can also provide multiple hosts separated by a space'
),
- 'value' => 'localhost',
- 'validators' => array(
- array(
- 'Callback',
- false,
- array(
- 'callback' => function ($v) {
- $withoutScheme = $withScheme = false;
- foreach (explode(' ', $v) as $uri) {
- if (preg_match('~^(?<!://)[^:]+:\d+$~', $uri)) {
- return false;
- }
-
- $url = Url::fromPath($uri);
- if ($url->getScheme()) {
- $withScheme = true;
- } else {
- $withoutScheme = true;
- }
- }
-
- return $withScheme ^ $withoutScheme;
- },
- 'messages' => array(
- 'callbackValue' => $this->translate(
- 'A protocol scheme such as ldap:// or ldaps:// is mandatory for URIs with a given'
- . ' port and for all other URIs as well once a scheme is given for a single one.'
- )
- )
- )
- )
- )
+ 'value' => 'localhost'
)
);
$this->addElement(
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/application/forms/ConfigForm.php
^
|
@@ -4,6 +4,7 @@
namespace Icinga\Forms;
use Exception;
+use Icinga\Exception\ConfigurationError;
use Zend_Form_Decorator_Abstract;
use Icinga\Application\Config;
use Icinga\Web\Form;
@@ -99,6 +100,10 @@
{
try {
$this->writeConfig($this->config);
+ } catch (ConfigurationError $e) {
+ $this->addError($e->getMessage());
+
+ return false;
} catch (Exception $e) {
$this->addDecorator('ViewScript', array(
'viewModule' => 'default',
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/application/forms/Dashboard/DashletForm.php
^
|
@@ -46,6 +46,17 @@
$panes = $this->dashboard->getPaneKeyTitleArray();
}
+ $sectionNameValidator = ['Callback', true, [
+ 'callback' => function ($value) {
+ if (strpos($value, '[') === false && strpos($value, ']') === false) {
+ return true;
+ }
+ },
+ 'messages' => [
+ 'callbackValue' => $this->translate('Brackets ([, ]) cannot be used here')
+ ]
+ ]];
+
$this->addElement(
'hidden',
'org_pane',
@@ -80,7 +91,8 @@
array(
'required' => true,
'label' => $this->translate('Dashlet Title'),
- 'description' => $this->translate('Enter a title for the dashlet.')
+ 'description' => $this->translate('Enter a title for the dashlet.'),
+ 'validators' => [$sectionNameValidator]
)
);
$this->addElement(
@@ -109,7 +121,8 @@
array(
'required' => true,
'label' => $this->translate('New Dashboard Title'),
- 'description' => $this->translate('Enter a title for the new dashboard')
+ 'description' => $this->translate('Enter a title for the new dashboard'),
+ 'validators' => [$sectionNameValidator]
)
);
} else {
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/application/layouts/scripts/layout.phtml
^
|
@@ -85,6 +85,7 @@
<script type="text/javascript" src="<?= $this->href($jsfile) ?>"></script>
<!--<![endif]-->
<script type="text/javascript">
+window.name = '<?= $this->protectId('Icinga') ?>';
var icinga = new Icinga({
baseUrl: '<?= $this->baseUrl(); ?>'
});
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/doc/05-Authentication.md
^
|
@@ -171,9 +171,13 @@
-------------------------|-----------------------------------------------
backend | **Required.** Specifies the backend type. Can be set to `ldap`, `msldap`.
resource | **Required.** The name of the LDAP resource defined in [resources.ini](04-Resources.md#resources).
-user\_class | **Optional.** LDAP user class. Defaults to `user`.
+domain | **Optional.** The domain the LDAP server is responsible for. See [Domain-aware Authentication](05-Authentication.md#domain-aware-authentication).
+user\_class | **Optional.** LDAP user class. Defaults to `inetOrgPerson` with `msldap` and `user` with `ldap`.
user\_name\_attribute | **Optional.** LDAP attribute which contains the username. Defaults to `sAMAccountName` with `msldap` and `uid` with `ldap`.
+user\_base\_dn | **Optional.** The path where users can be found on the LDAP server.
+base_dn | **Optional.** LDAP base dn for groups. Leave empty to select all groups available using the specified resource.
group\_class | **Optional.** LDAP group class. Defaults to `group`.
+group\_member\_attribute | **Optional.** LDAP attribute where a group's members are stored. Defaults to `member`.
group\_name\_attribute | **Optional.** LDAP attribute which contains the groupname. Defaults to `sAMAccountName` with `msldap` and `gid` with `ldap`.
group\_filter | **Optional.** LDAP group search filter. Requires `group_class` and `group_name_attribute`.
nested\_group\_search | **Optional.** Enable nested group search in Active Directory based on the user. Defaults to `0`. Only available with `backend` type `msldap`.
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/library/Icinga/Application/ApplicationBootstrap.php
^
|
@@ -618,11 +618,7 @@
{
$timezone = $this->detectTimeZone();
if ($timezone === null || @date_default_timezone_set($timezone) === false) {
- $timezone = @date_default_timezone_get();
- if ($timezone === false) {
- $timezone = 'UTC';
- date_default_timezone_set($timezone);
- }
+ date_default_timezone_set(@date_default_timezone_get());
}
return $this;
}
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/library/Icinga/Application/Modules/Module.php
^
|
@@ -686,7 +686,7 @@
case 'depends':
if (strpos($val, ' ') === false) {
$metadata->depends[$val] = true;
- continue;
+ continue 2;
}
$parts = preg_split('/,\s+/', $val);
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/library/Icinga/Application/Version.php
^
|
@@ -8,7 +8,7 @@
*/
class Version
{
- const VERSION = '2.6.2';
+ const VERSION = '2.6.3';
/**
* Get the version of this instance of Icinga Web 2
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/library/Icinga/Authentication/Auth.php
^
|
@@ -139,7 +139,20 @@
$this->getResponse()->setReloadCss(true);
$user->setPreferences($preferences);
$groups = $user->getGroups();
+ $userBackendName = $user->getAdditional('backend_name');
foreach (Config::app('groups') as $name => $config) {
+ $groupsUserBackend = $config->user_backend;
+ if ($groupsUserBackend
+ && $groupsUserBackend !== 'none'
+ && $userBackendName !== null
+ && $groupsUserBackend !== $userBackendName
+ ) {
+ // Do not ask for Group membership if a specific User Backend
+ // has been assigned to that Group Backend, and the user has
+ // been authenticated by another User Backend
+ continue;
+ }
+
try {
$groupBackend = UserGroupBackend::create($name, $config);
$groupsFromBackend = $groupBackend->getMemberships($user);
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/library/Icinga/Chart/GridChart.php
^
|
@@ -409,7 +409,7 @@
);
break;
default:
- continue;
+ continue 2;
}
$el = $this->setupGraph($graphObj, $graph);
if ($el) {
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/library/Icinga/Data/DataArray/ArrayDatasource.php
^
|
@@ -201,7 +201,7 @@
$result = array();
$skipped = 0;
foreach ($this->data as $key => $row) {
- if (is_string($key) && $this->keyColumn !== null && !isset($row->{$this->keyColumn})) {
+ if ($this->keyColumn !== null && !isset($row->{$this->keyColumn})) {
$row = clone $row; // Make sure that this won't affect the actual data
$row->{$this->keyColumn} = $key;
}
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/library/Icinga/Data/Db/DbConnection.php
^
|
@@ -3,6 +3,8 @@
namespace Icinga\Data\Db;
+use DateTime;
+use DateTimeZone;
use Exception;
use Icinga\Data\Inspectable;
use Icinga\Data\Inspection;
@@ -200,6 +202,7 @@
$driverOptions[PDO::MYSQL_ATTR_INIT_COMMAND] .= ', NAMES ' . $adapterParamaters['charset'];
unset($adapterParamaters['charset']);
}
+ $driverOptions[PDO::MYSQL_ATTR_INIT_COMMAND] .= ", time_zone='" . $this->defaultTimezoneOffset() . "'";
$driverOptions[PDO::MYSQL_ATTR_INIT_COMMAND] .=';';
$defaultPort = 3306;
break;
@@ -278,6 +281,22 @@
}
/**
+ * Get offset from the current default timezone to GMT
+ *
+ * @return string
+ */
+ protected function defaultTimezoneOffset()
+ {
+ $tz = new DateTimeZone(date_default_timezone_get());
+ $offset = $tz->getOffset(new DateTime());
+ $prefix = $offset >= 0 ? '+' : '-';
+ $offset = abs($offset);
+ $hours = (int) floor($offset / 3600);
+ $minutes = (int) floor(($offset % 3600) / 60);
+ return sprintf('%s%d:%02d', $prefix, $hours, $minutes);
+ }
+
+ /**
* Count all rows of the result set
*
* @param DbQuery $query
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/library/Icinga/File/Ini/Dom/Directive.php
^
|
@@ -157,11 +157,10 @@
{
$str = trim($str);
$str = str_replace('\\', '\\\\', $str);
- $str = str_replace('"', '\\"', $str);
+ $str = str_replace('"', '\"', $str);
+ $str = str_replace("\r", '\r', $str);
+ $str = str_replace("\n", '\n', $str);
- // line breaks in the value should always match the current system EOL sequence
- // to assure editable configuration files
- $str = preg_replace("/(\r\n)|(\n)/", PHP_EOL, $str);
return $str;
}
}
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/library/Icinga/File/Ini/Dom/Section.php
^
|
@@ -41,13 +41,18 @@
/**
* @param string $name The immutable name of this section
*
- * @throws ConfigurationError When the section name is empty
+ * @throws ConfigurationError When the section name is empty or contains brackets
*/
public function __construct($name)
{
$this->name = trim($name);
if (strlen($this->name) < 1) {
- throw new ConfigurationError(sprintf('Ini file error: empty section identifier'));
+ throw new ConfigurationError('Ini file error: empty section identifier');
+ } elseif (strpos($name, '[') !== false || strpos($name, ']') !== false) {
+ throw new ConfigurationError(
+ 'Ini file error: Section name "%s" must not contain any brackets ([, ])',
+ $name
+ );
}
}
@@ -165,7 +170,6 @@
$str = trim($str);
$str = str_replace('\\', '\\\\', $str);
$str = str_replace('"', '\\"', $str);
- $str = str_replace(']', '\\]', $str);
$str = str_replace(';', '\\;', $str);
return str_replace(PHP_EOL, ' ', $str);
}
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/library/Icinga/File/Ini/IniParser.php
^
|
@@ -64,7 +64,7 @@
switch ($state) {
case self::LINE_START:
if (ctype_space($s)) {
- continue;
+ continue 2;
}
switch ($s) {
case '[':
@@ -130,7 +130,7 @@
case self::DIRECTIVE_VALUE_START:
if (ctype_space($s)) {
- continue;
+ continue 2;
} elseif ($s === '"') {
$state = self::DIRECTIVE_VALUE_QUOTED;
} else {
@@ -269,9 +269,42 @@
$unescaped = array();
foreach ($configArray as $section => $options) {
- $unescaped[preg_replace('/\\\\(.)/', '\1', $section)] = $options;
+ $unescaped[self::unescapeSectionName($section)] = array_map([__CLASS__, 'unescapeOptionValue'], $options);
}
return Config::fromArray($unescaped)->setConfigFile($file);
}
+
+ /**
+ * Unescape significant characters in the given section name
+ *
+ * @param string $str
+ *
+ * @return string
+ */
+ protected static function unescapeSectionName($str)
+ {
+ $str = str_replace('\"', '"', $str);
+ $str = str_replace('\;', ';', $str);
+
+ return str_replace('\\\\', '\\', $str);
+ }
+
+ /**
+ * Unescape significant characters in the given option value
+ *
+ * @param string $str
+ *
+ * @return string
+ */
+ protected static function unescapeOptionValue($str)
+ {
+ $str = str_replace('\n', "\n", $str);
+ $str = str_replace('\r', "\r", $str);
+ $str = str_replace('\"', '"', $str);
+ $str = str_replace('\\\\', '\\', $str);
+
+ // This replacement is a work-around for PHP bug #76965. Fixed with versions 7.1.24, 7.2.12 and 7.3.0.
+ return preg_replace('~^([\'"])(.*?)\1\s+$~', '$2', $str);
+ }
}
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/library/Icinga/File/Pdf.php
^
|
@@ -8,6 +8,7 @@
use Dompdf\Options;
use Icinga\Application\Icinga;
use Icinga\Exception\ProgrammingError;
+use Icinga\Util\Environment;
use Icinga\Web\Hook;
use Icinga\Web\Url;
@@ -45,8 +46,10 @@
public function renderControllerAction($controller)
{
$this->assertNoHeadersSent();
- ini_set('memory_limit', '384M');
- ini_set('max_execution_time', 300);
+
+ Environment::raiseMemoryLimit('512M');
+ Environment::raiseExecutionTime(300);
+
$viewRenderer = $controller->getHelper('viewRenderer');
$controller->render(
$viewRenderer->getScriptAction(),
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/library/Icinga/Protocol/Ldap/LdapConnection.php
^
|
@@ -344,11 +344,10 @@
$success = @ldap_bind($ds, $this->bindDn, $this->bindPw);
if (! $success) {
throw new LdapException(
- 'LDAP bind (%s / %s) to %s with default port %s failed: %s',
+ 'LDAP bind (%s / %s) to %s failed: %s',
$this->bindDn,
'***' /* $this->bindPw */,
- $this->hostname,
- $this->port,
+ $this->normalizeHostname($this->hostname),
ldap_error($ds)
);
}
@@ -1179,22 +1178,7 @@
$info = new Inspection('');
}
- $hostname = $this->hostname;
- if ($this->encryption === static::LDAPS) {
- $info->write('Connect using LDAPS');
- $ldapUrls = explode(' ', $hostname);
- if (count($ldapUrls) > 1) {
- foreach ($ldapUrls as & $uri) {
- if (strpos($uri, '://') === false) {
- $uri = 'ldaps://' . $uri;
- }
- }
-
- $hostname = implode(' ', $ldapUrls);
- } else {
- $hostname = 'ldaps://' . $hostname;
- }
- }
+ $hostname = $this->normalizeHostname($this->hostname);
$ds = ldap_connect($hostname, $this->port);
@@ -1209,7 +1193,9 @@
// Not setting this results in "Operations error" on AD when using the whole domain as search base
ldap_set_option($ds, LDAP_OPT_REFERRALS, 0);
- if ($this->encryption === static::STARTTLS) {
+ if ($this->encryption === static::LDAPS) {
+ $info->write('Connect using LDAPS');
+ } elseif ($this->encryption === static::STARTTLS) {
$this->encrypted = true;
$info->write('Connect using STARTTLS');
if (! ldap_start_tls($ds)) {
@@ -1253,23 +1239,6 @@
// We're checking the level by ourselves to avoid rendering the ldapsearch commandline for nothing
$starttlsParam = $this->encryption === static::STARTTLS ? ' -ZZ' : '';
- $ldapUrls = array();
- $defaultScheme = $this->encryption === static::LDAPS ? 'ldaps://' : 'ldap://';
- foreach (explode(' ', $this->hostname) as $uri) {
- $url = Url::fromPath($uri);
- if (! $url->getScheme()) {
- $uri = $defaultScheme . $uri . ($this->port ? ':' . $this->port : '');
- } else {
- if ($url->getPort() === null) {
- $url->setPort($this->port);
- }
-
- $uri = $url->getAbsoluteUrl();
- }
-
- $ldapUrls[] = $uri;
- }
-
$bindParams = '';
if ($this->bound) {
$bindParams = ' -D "' . $this->bindDn . '"' . ($this->bindPw ? ' -W' : '');
@@ -1288,7 +1257,7 @@
Logger::debug("Issueing LDAP search. Use '%s' to reproduce.", sprintf(
'ldapsearch -P 3%s -H "%s"%s -b "%s" -s "%s" -z %u -l %u -a "%s"%s%s%s',
$starttlsParam,
- implode(' ', $ldapUrls),
+ $this->normalizeHostname($this->hostname),
$bindParams,
$baseDn,
$scope,
@@ -1508,11 +1477,10 @@
// Try a bind-command with the given user credentials, this must not fail
$success = @ldap_bind($ds, $this->bindDn, $this->bindPw);
$msg = sprintf(
- 'LDAP bind (%s / %s) to %s with default port %s',
+ 'LDAP bind (%s / %s) to %s',
$this->bindDn,
'***' /* $this->bindPw */,
- $this->hostname,
- $this->port
+ $this->normalizeHostname($this->hostname)
);
if (! $success) {
// ldap_error does not return any proper error messages in case of certificate errors. Connecting
@@ -1543,4 +1511,33 @@
}
return $insp;
}
+
+ protected function normalizeHostname($hostname)
+ {
+ $scheme = $this->encryption === static::LDAPS ? 'ldaps://' : 'ldap://';
+ $normalizeHostname = function ($hostname) use ($scheme) {
+ if (strpos($hostname, $scheme) === false) {
+ $hostname = $scheme . $hostname;
+ }
+
+ if (! preg_match('/:\d+$/', $hostname)) {
+ $hostname .= ':' . $this->port;
+ }
+
+ return $hostname;
+ };
+
+ $ldapUrls = explode(' ', $hostname);
+ if (count($ldapUrls) > 1) {
+ foreach ($ldapUrls as & $uri) {
+ $uri = $normalizeHostname($uri);
+ }
+
+ $hostname = implode(' ', $ldapUrls);
+ } else {
+ $hostname = $normalizeHostname($hostname);
+ }
+
+ return $hostname;
+ }
}
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/library/Icinga/Protocol/Ldap/LdapQuery.php
^
|
@@ -3,6 +3,7 @@
namespace Icinga\Protocol\Ldap;
+use Icinga\Data\Filter\Filter;
use LogicException;
use Icinga\Data\SimpleQuery;
@@ -183,6 +184,37 @@
return parent::from($target, $fields);
}
+ public function where($condition, $value = null)
+ {
+ $this->addFilter(Filter::expression($condition, '=', $value));
+ return $this;
+ }
+
+ public function addFilter(Filter $filter)
+ {
+ $this->makeCaseInsensitive($filter);
+ return parent::addFilter($filter);
+ }
+
+ public function setFilter(Filter $filter)
+ {
+ $this->makeCaseInsensitive($filter);
+ return parent::setFilter($filter);
+ }
+
+ protected function makeCaseInsensitive(Filter $filter)
+ {
+ if ($filter->isExpression()) {
+ /** @var \Icinga\Data\Filter\FilterExpression $filter */
+ $filter->setCaseSensitive(false);
+ } else {
+ /** @var \Icinga\Data\Filter\FilterChain $filter */
+ foreach ($filter->filters() as $subFilter) {
+ $this->makeCaseInsensitive($subFilter);
+ }
+ }
+ }
+
/**
* Fetch result as tree
*
|
[-]
[+]
|
Added |
v2.6.3.tar.gz/library/Icinga/Util/Environment.php
^
|
@@ -0,0 +1,42 @@
+<?php
+/* Icinga Web 2 | (c) 2018 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Util;
+
+/**
+ * Helper for configuring the PHP environment
+ */
+class Environment
+{
+ /**
+ * Raise the PHP memory_limit
+ *
+ * Unless it is not already set to a higher limit
+ *
+ * @param string|int $minimum
+ */
+ public static function raiseMemoryLimit($minimum = '512M')
+ {
+ if (is_string($minimum)) {
+ $minimum = Format::unpackShorthandBytes($minimum);
+ }
+
+ if (Format::unpackShorthandBytes(ini_get('memory_limit')) < $minimum) {
+ ini_set('memory_limit', $minimum);
+ }
+ }
+
+ /**
+ * Raise the PHP max_execution_time
+ *
+ * Unless it is not already configured to a higher value.
+ *
+ * @param int $minimum
+ */
+ public static function raiseExecutionTime($minimum = 300)
+ {
+ if ((int) ini_get('max_execution_time') < $minimum) {
+ ini_set('max_execution_time', $minimum);
+ }
+ }
+}
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/library/Icinga/Util/Format.php
^
|
@@ -4,8 +4,6 @@
namespace Icinga\Util;
use DateTime;
-use Icinga\Date\DateFormatter;
-use Icinga\Exception\ProgrammingError;
class Format
{
@@ -56,11 +54,13 @@
public static function seconds($value)
{
- if ($value < 60) {
+ $absValue = abs($value);
+
+ if ($absValue < 60) {
return self::formatForUnits($value, self::$secondPrefix, self::$secondBase);
- } elseif ($value < 3600) {
+ } elseif ($absValue < 3600) {
return sprintf('%0.2f m', $value / 60);
- } elseif ($value < 86400) {
+ } elseif ($absValue < 86400) {
return sprintf('%0.2f h', $value / 3600);
}
@@ -141,4 +141,37 @@
return $dt->format('L') == 1;
}
+
+ /**
+ * Unpack shorthand bytes PHP directives to bytes
+ *
+ * @param string $subject
+ *
+ * @return int
+ */
+ public static function unpackShorthandBytes($subject)
+ {
+ $base = (int) $subject;
+
+ if ($base <= -1) {
+ return INF;
+ }
+
+ switch (strtoupper($subject[strlen($subject) - 1])) {
+ case 'K':
+ $multiplier = 1024;
+ break;
+ case 'M':
+ $multiplier = 1024 ** 2;
+ break;
+ case 'G':
+ $multiplier = 1024 ** 3;
+ break;
+ default:
+ $multiplier = 1;
+ break;
+ }
+
+ return $base * $multiplier;
+ }
}
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/library/Icinga/Web/Form.php
^
|
@@ -3,6 +3,7 @@
namespace Icinga\Web;
+use Icinga\Web\Form\Element\DateTimePicker;
use Zend_Config;
use Zend_Form;
use Zend_Form_Element;
@@ -983,7 +984,9 @@
'tag' => 'input',
'type' => 'hidden',
'name' => $name . static::DEFAULT_SUFFIX,
- 'value' => $el->getValue()
+ 'value' => $el instanceof DateTimePicker
+ ? $el->getValue()->format($el->getFormat())
+ : $el->getValue()
)
);
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/library/Icinga/Web/Navigation/NavigationItem.php
^
|
@@ -38,6 +38,13 @@
protected $active;
/**
+ * Whether this item is selected
+ *
+ * @var bool
+ */
+ protected $selected;
+
+ /**
* The CSS class used for the outer li element
*
* @var string
@@ -212,6 +219,39 @@
return $this;
}
+
+ /**
+ * Return whether this item is selected
+ *
+ * @return bool
+ */
+ public function getSelected()
+ {
+ if ($this->selected === null) {
+ $this->active = false;
+ if ($this->getUrl() !== null && Icinga::app()->getRequest()->getUrl()->matches($this->getUrl())) {
+ $this->setSelected();
+ }
+ }
+
+ return $this->selected;
+ }
+
+ /**
+ * Set whether this item is active
+ *
+ * If it's active and has a parent, the parent gets activated as well.
+ *
+ * @param bool $selected
+ *
+ * @return $this
+ */
+ public function setSelected($selected = true)
+ {
+ $this->selected = (bool) $selected;
+
+ return $this;
+ }
/**
* Get the CSS class used for the outer li element
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/library/Icinga/Web/Navigation/Renderer/BadgeNavigationItemRenderer.php
^
|
@@ -100,15 +100,8 @@
$item->setCssClass('badge-nav-item');
$this->setEscapeLabel(false);
$label = $this->view()->escape($item->getLabel());
- if (($icon = $item->getIcon()) !== null) {
- $label = $this->view()->icon($icon) . $label;
- $item->setIcon(null);
- }
$item->setLabel($this->renderBadge() . $label);
$html = parent::render($item);
- if ($icon) {
- $item->setIcon(true);
- }
return $html;
}
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/library/Icinga/Web/Navigation/Renderer/NavigationItemRenderer.php
^
|
@@ -178,6 +178,9 @@
: $item->getLabel();
if (($icon = $item->getIcon()) !== null) {
$label = $this->view()->icon($icon) . $label;
+ } else {
+ $firstLetter = $item->getName()[0];
+ $label = $this->view()->icon('letter', null, ['data-letter' => strtolower($firstLetter)]) . $label;
}
if (($url = $item->getUrl()) !== null) {
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/library/Icinga/Web/Navigation/Renderer/NavigationRenderer.php
^
|
@@ -322,9 +322,8 @@
$cssClasses[] = static::CSS_CLASS_ACTIVE;
}
- if ($item->getIcon() === null) {
- // @TODO(el): Add constant
- $cssClasses[] = 'no-icon';
+ if ($item->getSelected()) {
+ $cssClasses[] = static::CSS_CLASS_SELECTED;
}
if ($cssClass = $item->getCssClass()) {
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/library/Icinga/Web/Navigation/Renderer/NavigationRendererInterface.php
^
|
@@ -23,6 +23,13 @@
const CSS_CLASS_ACTIVE = 'active';
/**
+ * CSS class for selected items
+ *
+ * @var string
+ */
+ const CSS_CLASS_SELECTED = 'selected';
+
+ /**
* CSS class for dropdown items
*
* @var string
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/library/vendor/JShrink/Minifier.php
^
|
@@ -183,7 +183,7 @@
// new lines
case "\n":
// if the next line is something that can't stand alone preserve the newline
- if (strpos('(-+[@', $this->b) !== false) {
+ if ($this->b !== false && strpos('(-+[@', $this->b) !== false) {
echo $this->a;
$this->saveString();
break;
@@ -231,7 +231,7 @@
// check for some regex that breaks stuff
if ($this->a === '/' && ($this->b === '\'' || $this->b === '"')) {
$this->saveRegex();
- continue;
+ continue 3;
}
echo $this->a;
@@ -274,9 +274,8 @@
if (isset($this->c)) {
$char = $this->c;
unset($this->c);
-
- // Otherwise we start pulling from the input.
} else {
+ // Otherwise we start pulling from the input.
$char = substr($this->input, $this->index, 1);
// If the next character doesn't exist return false.
@@ -459,11 +458,8 @@
echo $this->a;
// Loop until the string is done
- while (true) {
-
- // Grab the very next character and load it into a
- $this->a = $this->getChar();
-
+ // Grab the very next character and load it into a
+ while (($this->a = $this->getChar()) !== false) {
switch ($this->a) {
// If the string opener (single or double quote) is used
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/library/vendor/JShrink/SOURCE
^
|
@@ -1,4 +1,7 @@
-curl https://codeload.github.com/tedious/JShrink/tar.gz/v1.3.0 -o JShrink-1.3.0.tar.gz
-tar xzf JShrink-1.3.0.tar.gz --strip-components 1 JShrink-1.3.0/LICENSE
-tar xzf JShrink-1.3.0.tar.gz --strip-components 3 JShrink-1.3.0/src/JShrink/Minifier.php
-rm JShrink-1.3.0.tar.gz
+#!/bin/bash
+set -eux
+VERSION=1.3.1
+curl -LsS https://github.com/tedious/JShrink/archive/v"$VERSION".tar.gz -o /tmp/JShrink.tar.gz
+tar xzf /tmp/JShrink.tar.gz --strip-components 1 JShrink-"$VERSION"/LICENSE
+tar xzf /tmp/JShrink.tar.gz --strip-components 3 JShrink-"$VERSION"/src/JShrink/Minifier.php
+rm /tmp/JShrink.tar.gz
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/library/vendor/Zend/Form.php
^
|
@@ -1159,7 +1159,7 @@
} else {
switch ($argc) {
case 0:
- continue;
+ continue 2;
case (1 <= $argc):
$type = array_shift($spec);
case (2 <= $argc):
@@ -1664,7 +1664,7 @@
*/
public function addSubForms(array $subForms)
{
- foreach ($subForms as $key => $spec) {
+ foreach ($subForms as $key => $spec) {
$name = (string) $key;
if ($spec instanceof Zend_Form) {
$this->addSubForm($spec, $name);
@@ -1676,7 +1676,7 @@
$order = null;
switch ($argc) {
case 0:
- continue;
+ continue 2;
case (1 <= $argc):
$subForm = array_shift($spec);
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/library/vendor/Zend/README.md
^
|
@@ -1,6 +1,6 @@
# icingaweb2-vendor-zf1
-icingaweb2-vendor-zf1 is [Icinga Web 2](https://icinga.com/products/icinga-web-2/)'s fork of
+icingaweb2-vendor-zf1 is [Icinga Web 2](https://www.icinga.org/products/icinga-web-2/)'s fork of
[Zend Framework](https://framework.zend.com/) 1 which is
[end-of-life](https://framework.zend.com/blog/2016-06-28-zf1-eol.html) since Sep 28, 2016.
We've reduced the library to the minimum required by Icinga Web 2 and its modules.
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/library/vendor/Zend/VERSION
^
|
@@ -1 +1 @@
-v1.12.20
+v1.12.20-23-gc1f645550
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/library/vendor/dompdf/SOURCE
^
|
@@ -1,16 +1,26 @@
-GLOBIGNORE=$0; rm -rf *
+#!/bin/bash
+set -eux
+#GLOBIGNORE=$0; rm -rf *
-curl https://codeload.github.com/dompdf/dompdf/tar.gz/v0.8.2 -o dompdf-0.8.2.tar.gz
-tar xzf dompdf-0.8.2.tar.gz --strip-components 1 dompdf-0.8.2/{lib,src,LICENSE.LGPL}
-rm dompdf-0.8.2.tar.gz
+#DOMPDF_VERSION=0.8.2
+DOMPDF_VERSION=6a77a427984f97743018ace3e095fbf0edaaee29 # https://github.com/dompdf/dompdf/pull/1854
+
+PHP_FONTLIB_VERSION=0.5.1
+PHP_SVGLIB_VERSION=0.3.2
+
+rm -rf lib/ src/
+
+curl -LsS https://github.com/dompdf/dompdf/archive/"$DOMPDF_VERSION".tar.gz -o /tmp/dompdf.tar.gz
+tar xf /tmp/dompdf.tar.gz --strip-components 1 dompdf-"$DOMPDF_VERSION"/{lib,src,LICENSE.LGPL}
+rm /tmp/dompdf.tar.gz
mv LICENSE.LGPL LICENSE
-curl https://codeload.github.com/PhenX/php-font-lib/tar.gz/0.5.1 -o php-font-lib-0.5.1.tar.gz
-mkdir -p lib/php-font-lib
-tar xzf php-font-lib-0.5.1.tar.gz --strip-components 1 -C lib/php-font-lib php-font-lib-0.5.1/{src,LICENSE}
-rm php-font-lib-0.5.1.tar.gz
-
-curl https://codeload.github.com/PhenX/php-svg-lib/tar.gz/v0.3.2 -o php-svg-lib-0.3.2.tar.gz
-mkdir -p lib/php-svg-lib
-tar xzf php-svg-lib-0.3.2.tar.gz --strip-components 1 -C lib/php-svg-lib php-svg-lib-0.3.2/src
-rm php-svg-lib-0.3.2.tar.gz
+curl -LsS https://github.com/PhenX/php-font-lib/archive/"$PHP_FONTLIB_VERSION".tar.gz -o /tmp/php-font-lib.tar.gz
+[ -d lib/php-font-lib ] || mkdir -p lib/php-font-lib
+tar xf /tmp/php-font-lib.tar.gz --strip-components 1 -C lib/php-font-lib php-font-lib-"$PHP_FONTLIB_VERSION"/{src,LICENSE}
+rm /tmp/php-font-lib.tar.gz
+
+curl -LsS https://github.com/PhenX/php-svg-lib/archive/v"$PHP_SVGLIB_VERSION".tar.gz -o /tmp/php-svg-lib.tar.gz
+[ -d lib/php-svg-lib ] || mkdir -p lib/php-svg-lib
+tar xf /tmp/php-svg-lib.tar.gz --strip-components 1 -C lib/php-svg-lib php-svg-lib-"$PHP_SVGLIB_VERSION"/src
+rm /tmp/php-svg-lib.tar.gz
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/library/vendor/dompdf/lib/Cpdf.php
^
|
@@ -464,28 +464,28 @@
// Named with limited valid values
case 'NonFullScreenPageMode':
if (!in_array($v, array('UseNone', 'UseOutlines', 'UseThumbs', 'UseOC'))) {
- continue;
+ continue 2;
}
$o['info'][$k] = $v;
break;
case 'Direction':
if (!in_array($v, array('L2R', 'R2L'))) {
- continue;
+ continue 2;
}
$o['info'][$k] = $v;
break;
case 'PrintScaling':
if (!in_array($v, array('None', 'AppDefault'))) {
- continue;
+ continue 2;
}
$o['info'][$k] = $v;
break;
case 'Duplex':
if (!in_array($v, array('None', 'AppDefault'))) {
- continue;
+ continue 2;
}
$o['info'][$k] = $v;
break;
@@ -4801,12 +4801,12 @@
imagesavealpha($img, false);
// create temp alpha file
- $tempfile_alpha = tempnam($this->tmp, "cpdf_img_");
+ $tempfile_alpha = @tempnam($this->tmp, "cpdf_img_");
@unlink($tempfile_alpha);
$tempfile_alpha = "$tempfile_alpha.png";
// create temp plain file
- $tempfile_plain = tempnam($this->tmp, "cpdf_img_");
+ $tempfile_plain = @tempnam($this->tmp, "cpdf_img_");
@unlink($tempfile_plain);
$tempfile_plain = "$tempfile_plain.png";
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/library/vendor/dompdf/src/Adapter/CPDF.php
^
|
@@ -562,6 +562,25 @@
}
/**
+ * Draw line at the specified coordinates on every page.
+ *
+ * See {@link Style::munge_color()} for the format of the colour array.
+ *
+ * @param float $x1
+ * @param float $y1
+ * @param float $x2
+ * @param float $y2
+ * @param array $color
+ * @param float $width
+ * @param array $style optional
+ */
+ public function page_line($x1, $y1, $x2, $y2, $color, $width, $style = array())
+ {
+ $_t = 'line';
+ $this->_page_text[] = compact('_t', 'x1', 'y1', 'x2', 'y2', 'color', 'width', 'style');
+ }
+
+ /**
* @param float $x
* @param float $y
* @param float $r1
@@ -608,7 +627,7 @@
imageinterlace($im, false);
$tmp_dir = $this->_dompdf->getOptions()->getTempDir();
- $tmp_name = tempnam($tmp_dir, "{$type}dompdf_img_");
+ $tmp_name = @tempnam($tmp_dir, "{$type}dompdf_img_");
@unlink($tmp_name);
$filename = "$tmp_name.png";
$this->_image_cache[] = $filename;
@@ -1092,6 +1111,10 @@
}
$eval->evaluate($code, array('PAGE_NUM' => $page_number, 'PAGE_COUNT' => $this->_page_count));
break;
+
+ case 'line':
+ $this->line( $x1, $y1, $x2, $y2, $color, $width, $style );
+ break;
}
}
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/library/vendor/dompdf/src/Adapter/GD.php
^
|
@@ -729,7 +729,7 @@
$func_name = "imagecreatefrom$img_type";
if (!function_exists($func_name)) {
if (!method_exists("Dompdf\Helpers", $func_name)) {
- throw new \Exception("Function $func_name() not found. Cannot convert $type image: $img_url. Please install the image PHP extension.");
+ throw new \Exception("Function $func_name() not found. Cannot convert $img_type image: $img_url. Please install the image PHP extension.");
}
$func_name = "\\Dompdf\\Helpers::" . $func_name;
}
@@ -977,6 +977,11 @@
{
// N/A
}
+
+ public function page_line()
+ {
+ // N/A
+ }
/**
* Streams the image to the client.
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/library/vendor/dompdf/src/Adapter/PDFLib.php
^
|
@@ -208,7 +208,7 @@
$this->_pdf->begin_document("", "");
} else {
$tmp_dir = $this->_dompdf->getOptions()->getTempDir();
- $tmp_name = tempnam($tmp_dir, "libdompdf_pdf_");
+ $tmp_name = @tempnam($tmp_dir, "libdompdf_pdf_");
@unlink($tmp_name);
$this->_file = "$tmp_name.pdf";
$this->_pdf->begin_document($this->_file, "");
@@ -763,6 +763,25 @@
}
/**
+ * Draw line at the specified coordinates on every page.
+ *
+ * See {@link Style::munge_color()} for the format of the colour array.
+ *
+ * @param float $x1
+ * @param float $y1
+ * @param float $x2
+ * @param float $y2
+ * @param array $color
+ * @param float $width
+ * @param array $style optional
+ */
+ public function page_line($x1, $y1, $x2, $y2, $color, $width, $style = array())
+ {
+ $_t = 'line';
+ $this->_page_text[] = compact('_t', 'x1', 'y1', 'x2', 'y2', 'color', 'width', 'style');
+ }
+
+ /**
* @param float $x1
* @param float $y1
* @param float $r1
@@ -1259,6 +1278,11 @@
}
$eval->evaluate($code, array('PAGE_NUM' => $p, 'PAGE_COUNT' => $this->_page_count));
break;
+
+ case 'line':
+ $this->line( $x1, $y1, $x2, $y2, $color, $width, $style );
+ break;
+
}
}
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/library/vendor/dompdf/src/Css/Stylesheet.php
^
|
@@ -1357,7 +1357,7 @@
$key = $page_selector;
default:
- continue;
+ continue 3;
}
// Store the style for later...
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/library/vendor/dompdf/src/Dompdf.php
^
|
@@ -368,7 +368,7 @@
$ext = strtolower(pathinfo($realfile, PATHINFO_EXTENSION));
if (!in_array($ext, $this->allowedLocalFileExtensions)) {
- throw new Exception("Permission denied on $file.");
+ throw new Exception("Permission denied on $file. This file extension is forbidden");
}
if (!$realfile) {
@@ -607,7 +607,7 @@
if (!$accept) {
//found at least one mediatype, but none of the accepted ones
//Skip this css file.
- continue;
+ continue 2;
}
}
@@ -628,7 +628,7 @@
($media = $tag->getAttribute("media")) &&
!in_array($media, $acceptedmedia)
) {
- continue;
+ continue 2;
}
$css = "";
@@ -945,7 +945,7 @@
*
* @param array $options options (see above)
*
- * @return string
+ * @return string|null
*/
public function output($options = array())
{
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/library/vendor/dompdf/src/FontMetrics.php
^
|
@@ -186,7 +186,7 @@
$fontDir = $this->getOptions()->getFontDir();
$remoteHash = md5($remoteFile);
$localFile = $fontDir . DIRECTORY_SEPARATOR . $remoteHash;
- $localTempFile = tempnam($this->options->get("tempDir"), "dompdf-font-");
+ $localTempFile = @tempnam($this->options->get("tempDir"), "dompdf-font-");
$cacheEntry = $localFile;
$localFile .= ".".strtolower(pathinfo(parse_url($remoteFile, PHP_URL_PATH),PATHINFO_EXTENSION));
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/library/vendor/dompdf/src/FrameDecorator/Page.php
^
|
@@ -515,7 +515,7 @@
// parents of $frame must fit on the page as well:
$p = $frame->get_parent();
while ($p) {
- $max_y += $p->get_style()->computed_bottom_spacing();
+ $max_y += (float) $p->get_style()->computed_bottom_spacing();
$p = $p->get_parent();
}
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/library/vendor/dompdf/src/Image/Cache.php
^
|
@@ -88,7 +88,7 @@
} // From remote
else {
$tmp_dir = $dompdf->getOptions()->getTempDir();
- $resolved_url = tempnam($tmp_dir, "ca_dompdf_img_");
+ $resolved_url = @tempnam($tmp_dir, "ca_dompdf_img_");
$image = "";
if ($data_uri) {
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/library/vendor/dompdf/src/Renderer/AbstractRenderer.php
^
|
@@ -401,7 +401,7 @@
$this->_canvas->get_cpdf()->addImagePng($filedummy, $x, $this->_canvas->get_height() - $y - $height, $width, $height, $bg);
} else {
$tmp_dir = $this->_dompdf->getOptions()->getTempDir();
- $tmp_name = tempnam($tmp_dir, "bg_dompdf_img_");
+ $tmp_name = @tempnam($tmp_dir, "bg_dompdf_img_");
@unlink($tmp_name);
$tmp_file = "$tmp_name.png";
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/library/vendor/dompdf/src/Renderer/Text.php
^
|
@@ -137,7 +137,7 @@
switch ($text_deco) {
default:
- continue;
+ continue 2;
case "underline":
$deco_y += $base - $descent + $underline_offset + $line_thickness / 2;
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/modules/doc/module.info
^
|
@@ -1,4 +1,4 @@
Module: doc
-Version: 2.6.2
+Version: 2.6.3
Description: Documentation module
Extracts, shows and exports documentation for Icinga Web 2 and its modules.
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/modules/migrate/module.info
^
|
@@ -1,5 +1,5 @@
Module: migrate
-Version: 2.6.2
+Version: 2.6.3
Description: Migrate module
This module was introduced with the domain-aware authentication feature in version 2.5.0.
It helps you migrating users and user configurations according to a given domain.
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/modules/monitoring/application/controllers/EventController.php
^
|
@@ -38,13 +38,6 @@
'dt_end' => 'downtimeevent'
);
- /**
- * Cache for {@link time()}
- *
- * @var DateTimeZone
- */
- protected $timeZone;
-
public function showAction()
{
$type = $this->params->shiftRequired('type');
@@ -107,31 +100,6 @@
}
/**
- * Render the given timestamp as human readable HTML in the user agent's timezone or 'N/A' if NULL
- *
- * @param int|null $stamp
- *
- * @return string
- */
- protected function time($stamp)
- {
- if ($stamp === null) {
- return $this->view->escape($this->translate('N/A'));
- }
-
- if ($this->timeZone === null) {
- $timezoneDetect = new TimezoneDetect();
- $this->timeZone = new DateTimeZone(
- $timezoneDetect->success() ? $timezoneDetect->getTimezoneName() : date_default_timezone_get()
- );
- }
-
- return $this->view->escape(
- DateTime::createFromFormat('U', $stamp)->setTimezone($this->timeZone)->format('Y-m-d H:i:s')
- );
- }
-
- /**
* Render the given duration in seconds as human readable HTML or 'N/A' if NULL
*
* @param int|null $seconds
@@ -370,7 +338,7 @@
case 'dt_start':
case 'dt_end':
$details = array(array(
- array($this->translate('Entry time'), $this->time($event->entry_time)),
+ array($this->translate('Entry time'), DateFormatter::formatTime($event->entry_time)),
array($this->translate('Is fixed'), $this->yesOrNo($event->is_fixed)),
array($this->translate('Is in effect'), $this->yesOrNo($event->is_in_effect)),
array($this->translate('Was started'), $this->yesOrNo($event->was_started))
@@ -383,16 +351,28 @@
}
$details[] = array(
- array($this->translate('Trigger time'), $this->time($event->trigger_time)),
- array($this->translate('Scheduled start time'), $this->time($event->scheduled_start_time)),
- array($this->translate('Actual start time'), $this->time($event->actual_start_time)),
- array($this->translate('Scheduled end time'), $this->time($event->scheduled_end_time))
+ array($this->translate('Trigger time'), DateFormatter::formatTime($event->trigger_time)),
+ array(
+ $this->translate('Scheduled start time'),
+ DateFormatter::formatTime($event->scheduled_start_time)
+ ),
+ array(
+ $this->translate('Actual start time'),
+ DateFormatter::formatTime($event->actual_start_time)
+ ),
+ array(
+ $this->translate('Scheduled end time'),
+ DateFormatter::formatTime($event->scheduled_end_time)
+ )
);
if ($type === 'dt_end') {
$details[] = array(
- array($this->translate('Actual end time'), $this->time($event->actual_end_time)))
- ;
+ array(
+ $this->translate('Actual end time'),
+ DateFormatter::formatTime($event->actual_end_time)
+ )
+ );
}
$details[] = array(
@@ -436,14 +416,14 @@
}
return array(
- array($this->translate('Time'), $this->time($event->comment_time)),
+ array($this->translate('Time'), DateFormatter::formatTime($event->comment_time)),
array($this->translate('Source'), $this->view->escape($commentSource)),
array($this->translate('Entry type'), $this->view->escape($entryType)),
array($this->translate('Author'), $this->contact($event->author_name)),
array($this->translate('Is persistent'), $this->yesOrNo($event->is_persistent)),
array($this->translate('Expires'), $this->yesOrNo($event->expires)),
- array($this->translate('Expiration time'), $this->time($event->expiration_time)),
- array($this->translate('Deletion time'), $this->time($event->deletion_time)),
+ array($this->translate('Expiration time'), DateFormatter::formatTime($event->expiration_time)),
+ array($this->translate('Deletion time'), DateFormatter::formatTime($event->deletion_time)),
array($this->translate('Message'), $this->comment($event->comment_data))
);
case 'flapping':
@@ -460,7 +440,7 @@
}
return array(
- array($this->translate('Event time'), $this->time($event->event_time)),
+ array($this->translate('Event time'), DateFormatter::formatTime($event->event_time)),
array($this->translate('Reason'), $this->view->escape($reasonType)),
array($this->translate('State change'), $this->percent($event->percent_state_change)),
array($this->translate('Low threshold'), $this->percent($event->low_threshold)),
@@ -500,8 +480,8 @@
}
$details = array(
- array($this->translate('Start time'), $this->time($event->start_time)),
- array($this->translate('End time'), $this->time($event->end_time)),
+ array($this->translate('Start time'), DateFormatter::formatTime($event->start_time)),
+ array($this->translate('End time'), DateFormatter::formatTime($event->end_time)),
array($this->translate('Reason'), $this->view->escape($notificationReason)),
array(
$this->translate('State'),
@@ -521,7 +501,7 @@
$isService = $event->service_description !== null;
$details = array(
- array($this->translate('State time'), $this->time($event->state_time)),
+ array($this->translate('State time'), DateFormatter::formatTime($event->state_time)),
array($this->translate('State'), $this->state($isService, $event->state)),
array($this->translate('Check attempt'), $this->view->escape(sprintf(
$this->translate('%d of %d'),
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/modules/monitoring/application/views/helpers/Customvar.php
^
|
@@ -16,11 +16,11 @@
public function customvar($struct)
{
if (is_scalar($struct)) {
- return $this->view->nl2br($this->view->escape(
+ return nl2br($this->view->escape(
is_string($struct)
? $struct
: var_export($struct, true)
- ));
+ ), false);
} elseif (is_array($struct)) {
return $this->renderArray($struct);
} elseif (is_object($struct)) {
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/modules/monitoring/application/views/helpers/PluginOutput.php
^
|
@@ -2,6 +2,7 @@
/* Icinga Web 2 | (c) 2013 Icinga Development Team | GPLv2+ */
use Icinga\Web\Dom\DomNodeIterator;
+use Icinga\Web\View;
use Icinga\Module\Monitoring\Web\Helper\PluginOutputPurifier;
/**
@@ -101,7 +102,6 @@
if ($command !== null) {
$output = $this->hookRenderer->render($command, $output, ! $raw);
}
- $output = preg_replace('~<br[^>]*>~', "\n", $output);
if (preg_match('~<[^>]*["/\'][^>]*>~', $output)) {
// HTML
$output = preg_replace(
@@ -115,7 +115,8 @@
$output = preg_replace(
self::$txtPatterns,
self::$txtReplacements,
- $this->view->escape($output)
+ // Not using the view here to escape this. The view sets `double_encode` to true
+ htmlspecialchars($output, ENT_COMPAT | ENT_SUBSTITUTE | ENT_HTML5, View::CHARSET, false)
);
$isHtml = false;
}
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/modules/monitoring/application/views/scripts/list/eventhistory.phtml
^
|
@@ -16,7 +16,6 @@
'compact' => $this->compact,
'history' => $history,
'isOverview' => true,
- 'tableCssClass' => 'table-row-selectable',
'translationDomain' => $this->translationDomain
)
) ?>
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/modules/monitoring/application/views/scripts/list/hostgroup-grid.phtml
^
|
@@ -3,7 +3,7 @@
<?= $this->tabs ?>
<div class="sort-controls-container">
<?= $this->sortBox ?>
- <a href="<?= $this->href('monitoring/list/hostgroups') ?>" class="grid-toggle-link"
+ <a href="<?= $this->href('monitoring/list/hostgroups')->addFilter($this->filterEditor->getFilter()) ?>" class="grid-toggle-link"
title="<?= $this->translate('Toogle grid view mode') ?>">
<?= $this->icon('th-list', null, ['class' => '-inactive']) ?>
<?= $this->icon('th-thumb-empty', null, ['class' => '-active']) ?>
@@ -24,7 +24,7 @@
<?php if ($hostGroup->hosts_down_unhandled > 0): ?>
<?= $this->qlink(
$hostGroup->hosts_down_unhandled,
- 'monitoring/list/hosts',
+ $this->url('monitoring/list/hosts')->addFilter($this->filterEditor->getFilter()),
[
'hostgroup_name' => $hostGroup->hostgroup_name,
'host_handled' => 0,
@@ -46,7 +46,7 @@
<?php elseif ($hostGroup->hosts_unreachable_unhandled > 0): ?>
<?= $this->qlink(
$hostGroup->hosts_unreachable_unhandled,
- 'monitoring/list/hosts',
+ $this->url('monitoring/list/hosts')->addFilter($this->filterEditor->getFilter()),
[
'hostgroup_name' => $hostGroup->hostgroup_name,
'host_handled' => 0,
@@ -68,7 +68,7 @@
<?php elseif ($hostGroup->hosts_down_handled > 0): ?>
<?= $this->qlink(
$hostGroup->hosts_down_handled,
- 'monitoring/list/hosts',
+ $this->url('monitoring/list/hosts')->addFilter($this->filterEditor->getFilter()),
[
'hostgroup_name' => $hostGroup->hostgroup_name,
'host_handled' => 1,
@@ -90,7 +90,7 @@
<?php elseif ($hostGroup->hosts_unreachable_handled > 0): ?>
<?= $this->qlink(
$hostGroup->hosts_unreachable_handled,
- 'monitoring/list/hosts',
+ $this->url('monitoring/list/hosts')->addFilter($this->filterEditor->getFilter()),
[
'hostgroup_name' => $hostGroup->hostgroup_name,
'host_handled' => 0,
@@ -112,7 +112,7 @@
<?php elseif ($hostGroup->hosts_pending > 0): ?>
<?= $this->qlink(
$hostGroup->hosts_pending,
- 'monitoring/list/hosts',
+ $this->url('monitoring/list/hosts')->addFilter($this->filterEditor->getFilter()),
[
'hostgroup_name' => $hostGroup->hostgroup_name,
'host_state' => 99
@@ -133,7 +133,7 @@
<?php elseif ($hostGroup->hosts_up > 0): ?>
<?= $this->qlink(
$hostGroup->hosts_up,
- 'monitoring/list/hosts',
+ $this->url('monitoring/list/hosts')->addFilter($this->filterEditor->getFilter()),
[
'hostgroup_name' => $hostGroup->hostgroup_name,
'host_state' => 0
@@ -158,7 +158,7 @@
<?php endif ?>
<?= $this->qlink(
$hostGroup->hostgroup_alias,
- 'monitoring/list/hosts',
+ $this->url('monitoring/list/hosts')->addFilter($this->filterEditor->getFilter()),
['hostgroup_name' => $hostGroup->hostgroup_name],
[
'title' => sprintf(
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/modules/monitoring/application/views/scripts/list/hostgroups.phtml
^
|
@@ -8,7 +8,7 @@
<div class="sort-controls-container">
<?= $this->limiter ?>
<?= $this->sortBox ?>
- <a href="<?= $this->href('monitoring/list/hostgroup-grid') ?>" class="grid-toggle-link"
+ <a href="<?= $this->href('monitoring/list/hostgroup-grid')->addFilter($this->filterEditor->getFilter()) ?>" class="grid-toggle-link"
title="<?= $this->translate('Toogle grid view mode') ?>">
<?= $this->icon('th-list', null, ['class' => '-active']) ?>
<?= $this->icon('th-thumb-empty', null, ['class' => '-inactive']) ?>
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/modules/monitoring/application/views/scripts/list/servicegroup-grid.phtml
^
|
@@ -3,7 +3,7 @@
<?= $this->tabs ?>
<div class="sort-controls-container">
<?= $this->sortBox ?>
- <a href="<?= $this->href('monitoring/list/servicegroups') ?>" class="grid-toggle-link"
+ <a href="<?= $this->href('monitoring/list/servicegroups')->addFilter($this->filterEditor->getFilter()) ?>" class="grid-toggle-link"
title="<?= $this->translate('Toogle grid view mode') ?>">
<?= $this->icon('th-list', null, ['class' => '-inactive']) ?>
<?= $this->icon('th-thumb-empty', null, ['class' => '-active']) ?>
@@ -24,7 +24,7 @@
<?php if ($serviceGroup->services_critical_unhandled > 0): ?>
<?= $this->qlink(
$serviceGroup->services_critical_unhandled,
- 'monitoring/list/servicegrid',
+ $this->url('monitoring/list/servicegrid')->addFilter($this->filterEditor->getFilter()),
[
'servicegroup_name' => $serviceGroup->servicegroup_name,
'service_handled' => 0,
@@ -46,7 +46,7 @@
<?php elseif ($serviceGroup->services_warning_unhandled > 0): ?>
<?= $this->qlink(
$serviceGroup->services_warning_unhandled,
- 'monitoring/list/servicegrid',
+ $this->url('monitoring/list/servicegrid')->addFilter($this->filterEditor->getFilter()),
[
'servicegroup_name' => $serviceGroup->servicegroup_name,
'service_handled' => 0,
@@ -68,7 +68,7 @@
<?php elseif ($serviceGroup->services_unknown_unhandled > 0): ?>
<?= $this->qlink(
$serviceGroup->services_unknown_unhandled,
- 'monitoring/list/servicegrid',
+ $this->url('monitoring/list/servicegrid')->addFilter($this->filterEditor->getFilter()),
[
'servicegroup_name' => $serviceGroup->servicegroup_name,
'service_handled' => 0,
@@ -90,7 +90,7 @@
<?php elseif ($serviceGroup->services_critical_handled > 0): ?>
<?= $this->qlink(
$serviceGroup->services_critical_handled,
- 'monitoring/list/servicegrid',
+ $this->url('monitoring/list/servicegrid')->addFilter($this->filterEditor->getFilter()),
[
'servicegroup_name' => $serviceGroup->servicegroup_name,
'service_handled' => 1,
@@ -112,7 +112,7 @@
<?php elseif ($serviceGroup->services_warning_handled > 0): ?>
<?= $this->qlink(
$serviceGroup->services_warning_handled,
- 'monitoring/list/servicegrid',
+ $this->url('monitoring/list/servicegrid')->addFilter($this->filterEditor->getFilter()),
[
'servicegroup_name' => $serviceGroup->servicegroup_name,
'service_handled' => 1,
@@ -134,7 +134,7 @@
<?php elseif ($serviceGroup->services_unknown_handled > 0): ?>
<?= $this->qlink(
$serviceGroup->services_unknown_handled,
- 'monitoring/list/servicegrid',
+ $this->url('monitoring/list/servicegrid')->addFilter($this->filterEditor->getFilter()),
[
'servicegroup_name' => $serviceGroup->servicegroup_name,
'service_handled' => 1,
@@ -156,7 +156,7 @@
<?php elseif ($serviceGroup->services_pending > 0): ?>
<?= $this->qlink(
$serviceGroup->services_pending,
- 'monitoring/list/servicegrid',
+ $this->url('monitoring/list/servicegrid')->addFilter($this->filterEditor->getFilter()),
[
'servicegroup_name' => $serviceGroup->servicegroup_name,
'service_state' => 99
@@ -177,7 +177,7 @@
<?php elseif ($serviceGroup->services_ok > 0): ?>
<?= $this->qlink(
$serviceGroup->services_ok,
- 'monitoring/list/servicegrid',
+ $this->url('monitoring/list/servicegrid')->addFilter($this->filterEditor->getFilter()),
[
'servicegroup_name' => $serviceGroup->servicegroup_name,
'service_state' => 0
@@ -202,7 +202,7 @@
<?php endif ?>
<?= $this->qlink(
$serviceGroup->servicegroup_alias,
- 'monitoring/list/servicegrid',
+ $this->url('monitoring/list/servicegrid')->addFilter($this->filterEditor->getFilter()),
['servicegroup_name' => $serviceGroup->servicegroup_name],
[
'title' => sprintf(
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/modules/monitoring/application/views/scripts/list/servicegroups.phtml
^
|
@@ -7,7 +7,7 @@
<div class="sort-controls-container">
<?= $this->limiter ?>
<?= $this->sortBox ?>
- <a href="<?= $this->href('monitoring/list/servicegroup-grid') ?>" class="grid-toggle-link"
+ <a href="<?= $this->href('monitoring/list/servicegroup-grid')->addFilter($this->filterEditor->getFilter()) ?>" class="grid-toggle-link"
title="<?= $this->translate('Toogle grid view mode') ?>">
<?= $this->icon('th-list', null, ['class' => '-active']) ?>
<?= $this->icon('th-thumb-empty', null, ['class' => '-inactive']) ?>
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/modules/monitoring/application/views/scripts/partials/event-history.phtml
^
|
@@ -39,7 +39,7 @@
$flappingMsg = $this->translate('Flapping with a %.2f%% state change rate');
$rowAction = Url::fromPath('monitoring/event/show');
?>
- <table class="table-row-selectable state-table" data-base-target="_next"<?php if (isset($tableCssClass)): ?> class="<?=$tableCssClass ?>"<?php endif ?>>
+ <table class="table-row-selectable state-table" data-base-target="_next">
<tbody>
<?php foreach ($history->peekAhead() as $event):
$icon = '';
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/modules/monitoring/application/views/scripts/tactical/index.phtml
^
|
@@ -25,7 +25,7 @@
<?php endif;
if ($statusSummary->hosts_down_handled):?>
<tr href="<?= $this->filteredUrl('monitoring/list/hosts', array('host_state' => 1, 'host_handled' => 1, 'sort' => 'host_last_check', 'dir' => 'asc')) ?>">
- <th class="state slice-state-critical-handled badge"><?= $statusSummary->hosts_down_handled ?></th>
+ <th class="state state-critical handled badge"><?= $statusSummary->hosts_down_handled ?></th>
<td><?= $this->translate('Down') ?> (<?= $this->translate('Handled') ?>)</td>
</tr>
<?php endif;
@@ -37,7 +37,7 @@
<?php endif;
if ($statusSummary->hosts_unreachable_handled):?>
<tr href="<?= $this->filteredUrl('monitoring/list/hosts', array('host_state' => 2, 'host_handled' => 1, 'sort' => 'host_last_check', 'dir' => 'asc')) ?>">
- <th class="state slice-state-unreachable-handled badge"><?= $statusSummary->hosts_unreachable_handled ?></th>
+ <th class="state state-unreachable handled badge"><?= $statusSummary->hosts_unreachable_handled ?></th>
<td><?= $this->translate('Unreachable') ?> (<?= $this->translate('Handled') ?>)</td>
</tr>
<?php endif;
@@ -77,7 +77,7 @@
<?php endif;
if ($statusSummary->services_warning_handled):?>
<tr href="<?= $this->filteredUrl('monitoring/list/services', array('service_state' => 1, 'service_handled' => 1, 'sort' => 'service_last_check', 'dir' => 'asc')) ?>">
- <th class="state slice-state-warning-handled badge"><?= $statusSummary->services_warning_handled ?></th>
+ <th class="state state-warning handled badge"><?= $statusSummary->services_warning_handled ?></th>
<td><?= $this->translate('Warning') ?> (<?= $this->translate('Handled') ?>)</td>
</tr>
<?php endif;
@@ -89,7 +89,7 @@
<?php endif;
if ($statusSummary->services_critical_handled):?>
<tr href="<?= $this->filteredUrl('monitoring/list/services', array('service_state' => 2, 'service_handled' => 1, 'sort' => 'service_last_check', 'dir' => 'asc')) ?>">
- <th class="state slice-state-critical-handled badge"><?= $statusSummary->services_critical_handled ?></th>
+ <th class="state state-critical handled badge"><?= $statusSummary->services_critical_handled ?></th>
<td><?= $this->translate('Critical') ?> (<?= $this->translate('Handled') ?>)</td>
</tr>
<?php endif;
@@ -101,19 +101,19 @@
<?php endif;
if ($statusSummary->services_unknown_handled):?>
<tr href="<?= $this->filteredUrl('monitoring/list/services', array('service_state' => 3, 'service_handled' => 1, 'sort' => 'service_last_check', 'dir' => 'asc')) ?>">
- <th class="state slice-state-unknown-handled badge"><?= $statusSummary->services_unknown_handled ?></th>
+ <th class="state state-unknown handled badge"><?= $statusSummary->services_unknown_handled ?></th>
<td><?= $this->translate('Unknown') ?> (<?= $this->translate('Handled') ?>)</td>
</tr>
<?php endif;
if ($statusSummary->services_unknown_unhandled):?>
<tr href="<?= $this->filteredUrl('monitoring/list/services', array('service_state' => 3, 'service_handled' => 0, 'sort' => 'service_last_check', 'dir' => 'asc')) ?>">
- <th class="state slice-state-unknown badge"><?= $statusSummary->services_unknown_unhandled ?></th>
+ <th class="state state-unknown badge"><?= $statusSummary->services_unknown_unhandled ?></th>
<td><?= $this->translate('Unknown') ?></td>
</tr>
<?php endif;
if ($statusSummary->services_pending):?>
<tr href="<?= $this->filteredUrl('monitoring/list/services', array('service_state' => 99, 'sort' => 'service_last_check', 'dir' => 'asc')) ?>">
- <th class="state slice-state-pending badge"><?= $statusSummary->services_pending ?></th>
+ <th class="state state-pending badge"><?= $statusSummary->services_pending ?></th>
<td><?= $this->translate('Pending') ?></td>
</tr>
<?php endif;
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostflappingstarthistoryQuery.php
^
|
@@ -34,6 +34,7 @@
protected $columnMap = array(
'flappinghistory' => array(
'id' => 'hfh.flappinghistory_id',
+ 'host' => 'ho.name1 COLLATE latin1_general_ci',
'host_name' => 'ho.name1',
'object_id' => 'hfh.object_id',
'object_type' => '(\'host\')',
@@ -58,6 +59,7 @@
'servicegroup_alias' => 'sg.alias COLLATE latin1_general_ci'
),
'services' => array(
+ 'service' => 'so.name2 COLLATE latin1_general_ci',
'service_description' => 'so.name2',
'service_display_name' => 's.display_name COLLATE latin1_general_ci',
'service_host_name' => 'so.name1'
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostnotificationQuery.php
^
|
@@ -42,6 +42,7 @@
'instance_name' => 'i.instance_name'
),
'notifications' => array(
+ 'host' => 'ho.name1 COLLATE latin1_general_ci',
'host_name' => 'ho.name1',
'notification_output' => 'hn.output',
'notification_reason' => 'hn.notification_reason',
@@ -53,6 +54,7 @@
'servicegroup_name' => 'sgo.name1'
),
'services' => array(
+ 'service' => 'so.name2 COLLATE latin1_general_ci',
'service_description' => 'so.name2',
'service_display_name' => 's.display_name COLLATE latin1_general_ci',
'service_host_name' => 'so.name1'
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServiceflappingstarthistoryQuery.php
^
|
@@ -34,10 +34,12 @@
protected $columnMap = array(
'flappinghistory' => array(
'id' => 'sfh.flappinghistory_id',
+ 'host' => 'so.name1 COLLATE latin1_general_ci',
'host_name' => 'so.name1',
'object_id' => 'sfh.object_id',
'object_type' => '(\'service\')',
'output' => '(sfh.percent_state_change || \'\')',
+ 'service' => 'so.name2 COLLATE latin1_general_ci',
'service_description' => 'so.name2',
'service_host_name' => 'so.name1',
'state' => '(-1)',
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicenotificationQuery.php
^
|
@@ -42,12 +42,14 @@
'instance_name' => 'i.instance_name'
),
'notifications' => array(
+ 'host' => 'so.name1 COLLATE latin1_general_ci',
'host_name' => 'so.name1',
'notification_output' => 'sn.output',
'notification_reason' => 'sn.notification_reason',
'notification_state' => 'sn.state',
'notification_timestamp' => 'UNIX_TIMESTAMP(sn.start_time)',
'object_type' => '(\'service\')',
+ 'service' => 'so.name2 COLLATE latin1_general_ci',
'service_description' => 'so.name2',
'service_host_name' => 'so.name1'
),
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/modules/monitoring/library/Monitoring/Controller.php
^
|
@@ -97,7 +97,7 @@
*
* @param string $name Name of the restriction
*
- * @return Filter|null Filter object or null if the authenticated user is not restricted
+ * @return Filter Filter object
* @throws ConfigurationError If the restriction contains invalid filter columns
*/
protected function getRestriction($name)
@@ -115,7 +115,7 @@
));
foreach ($this->getRestrictions($name) as $filter) {
if ($filter === '*') {
- return Filter::matchAny();
+ return Filter::matchAll();
}
try {
$restriction->addFilter(Filter::fromQueryString($filter));
@@ -138,6 +138,11 @@
);
}
}
+
+ if ($restriction->isEmpty()) {
+ return Filter::matchAll();
+ }
+
return $restriction;
}
}
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/modules/monitoring/module.info
^
|
@@ -1,5 +1,5 @@
Module: monitoring
-Version: 2.6.2
+Version: 2.6.3
Description: Icinga monitoring module
This is the core module for most Icingaweb users. It provides an
abstraction layer for various Icinga data backends.
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/modules/monitoring/public/css/service-grid.less
^
|
@@ -34,6 +34,14 @@
a {
color: @text-color;
+ outline: none;
+
+ &:hover {
+ color: @text-color-light;
+ }
+ &:focus, &:active {
+ color: @icinga-blue;
+ }
}
i {
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/modules/monitoring/public/css/tables.less
^
|
@@ -235,6 +235,10 @@
border-spacing: 0 1px;
width: 100%;
+ tr[href] {
+ -webkit-transform: translate3d(0,0,0); /* Fixes Safari hover bug in history table rows */
+ }
+
tr[href].active {
background-color: @tr-active-color;
}
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/modules/monitoring/test/php/application/views/helpers/PluginOutputTest.php
^
|
@@ -65,6 +65,14 @@
);
}
+ public function testOutputWithHtmlEntities()
+ {
+ $this->checkOutput(
+ 'foo & bar',
+ 'foo & bar'
+ );
+ }
+
public function testSimpleHtmlOutput()
{
/** @noinspection HtmlUnknownAttribute */
@@ -79,16 +87,14 @@
{
$input = array(
'Teststatus',
- '<a href="http://localhost/test.php" target="_blank">Info</a><br/><br/>',
- '<a href="http://localhost/test2.php" target="_blank">Info2</a>'
+ '<a href="http://localhost/test.php" target="_blank">Info</a><br/><br/>'
+ . '<a href="http://localhost/test2.php" target="_blank">Info2</a>'
);
/** @noinspection HtmlUnknownAttribute */
$output = array(
'Teststatus',
- '<a href="http://localhost/test.php" target="_blank"[^>]*>Info</a>',
- '',
- '',
- '<a href="http://localhost/test2.php" target="_blank"[^>]*>Info2</a>'
+ '<a href="http://localhost/test.php" target="_blank"[^>]*>Info</a><br><br>'
+ . '<a href="http://localhost/test2.php" target="_blank"[^>]*>Info2</a>'
);
$this->checkHtmlOutput(
join("\n", $input),
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/modules/setup/module.info
^
|
@@ -1,5 +1,5 @@
Module: setup
-Version: 2.6.2
+Version: 2.6.3
Description: Setup module
Web based wizard for setting up Icinga Web 2 and its modules.
This includes the data backends (e.g. relational database, LDAP),
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/modules/test/module.info
^
|
@@ -1,5 +1,5 @@
Module: test
-Version: 2.6.2
+Version: 2.6.3
Description: Translation module
This module allows developers to run (unit) tests against Icinga Web 2 and
any of its modules. Usually you do not need to enable this.
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/modules/translation/module.info
^
|
@@ -1,5 +1,5 @@
Module: translation
-Version: 2.6.2
+Version: 2.6.3
Description: Translation module
This module allows developers and translators to translate Icinga Web 2 and
its modules for multiple languages. You do not need this module to run an
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/phpcs.xml
^
|
@@ -8,6 +8,7 @@
<file>test/</file>
<exclude-pattern>vendor/*</exclude-pattern>
+ <exclude-pattern>test/*.php</exclude-pattern>
<exclude-pattern>application/fonts/fontello-ifont/*</exclude-pattern>
<arg value="wps"/>
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/public/css/icinga/forms.less
^
|
@@ -60,7 +60,7 @@
&:focus {
background-color: @body-bg-color;
- background-image: url('../img/icons/search_icinga_blue.png') !important;
+ background-image: url('../img/icons/search_icinga_blue.png');
}
}
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/public/js/icinga/behavior/navigation.js
^
|
@@ -52,11 +52,11 @@
var $active = _this.$menu.find('li.active');
if ($active.length) {
$active.each(function() {
- _this.setActive($(this));
+ _this.setActiveAndSelected($(this));
});
} else {
// if no item is marked as active, try to select the menu from the current URL
- _this.setActiveByUrl($('#col1').data('icingaUrl'));
+ _this.setActiveAndSelectedByUrl($('#col1').data('icingaUrl'));
}
}
@@ -70,7 +70,7 @@
// restore selection to current active element
if (this.active) {
var $el = $(this.icinga.utils.getElementByDomPath(this.active));
- this.setActive($el);
+ this.setActiveAndSelected($el);
/*
* Recreate the html content of the menu item to force the browser to update the layout, or else
@@ -98,9 +98,9 @@
if (href.match(/#/)) {
// ...it may be a menu section without a dedicated link.
// Switch the active menu item:
- _this.setActive($a);
+ _this.setActiveAndSelected($a);
} else {
- _this.setActive($(event.target));
+ _this.setActiveAndSelected($(event.target));
}
// update target url of the menu container to the clicked link
var $menu = $('#menu');
@@ -116,7 +116,7 @@
*
* @param url {String} The url to match
*/
- Navigation.prototype.setActiveByUrl = function(url) {
+ Navigation.prototype.setActiveAndSelectedByUrl = function(url) {
var $menu = $('#menu');
if (! $menu.length) {
@@ -124,17 +124,17 @@
}
// try to active the first item that has an exact URL match
- this.setActive($menu.find('[href="' + url + '"]'));
+ this.setActiveAndSelected($menu.find('[href="' + url + '"]'));
// the url may point to the search field, which must be activated too
if (! this.active) {
- this.setActive($menu.find('form[action="' + this.icinga.utils.parseUrl(url).path + '"]'));
+ this.setActiveAndSelected($menu.find('form[action="' + this.icinga.utils.parseUrl(url).path + '"]'));
}
// some urls may have custom filters which won't match any menu item, in that case search
// for a menu item that points to the base action without any filters
if (! this.active) {
- this.setActive($menu.find('[href="' + this.icinga.utils.parseUrl(url).path + '"]').first());
+ this.setActiveAndSelected($menu.find('[href="' + this.icinga.utils.parseUrl(url).path + '"]').first());
}
};
@@ -143,11 +143,12 @@
*
* @param url
*/
- Navigation.prototype.trySetActiveByUrl = function(url) {
+ Navigation.prototype.trySetActiveAndSelectedByUrl = function(url) {
var active = this.active;
- this.setActiveByUrl(url);
+ this.setActiveAndSelectedByUrl(url);
+
if (! this.active && active) {
- this.setActive($(this.icinga.utils.getElementByDomPath(active)));
+ this.setActiveAndSelected($(this.icinga.utils.getElementByDomPath(active)));
}
};
@@ -161,6 +162,15 @@
};
/**
+ * Remove all selected elements
+ */
+ Navigation.prototype.clearSelected = function() {
+ if (this.$menu) {
+ this.$menu.find('.selected').removeClass('selected');
+ }
+ };
+
+ /**
* Select all menu items in the selector as active and unfold surrounding menus when necessary
*
* @param $item {jQuery} The jQuery selector
@@ -184,6 +194,11 @@
}
};
+ Navigation.prototype.setActiveAndSelected = function ($el) {
+ this.setActive($el);
+ this.setSelected($el);
+ };
+
/**
* Change the active menu element
*
@@ -202,6 +217,15 @@
// TODO: push to history
};
+ Navigation.prototype.setSelected = function($el) {
+ this.clearSelected();
+ $el = $el.closest('li');
+
+ if ($el.length) {
+ $el.addClass('selected');
+ }
+ };
+
/**
* Reset the active element to nothing
*/
@@ -211,6 +235,14 @@
};
/**
+ * Reset the selected element to nothing
+ */
+ Navigation.prototype.resetSelected = function() {
+ this.clearSelected();
+ this.selected = null;
+ };
+
+ /**
* Show the fly-out menu
*
* @param e
@@ -231,7 +263,7 @@
return;
}
- var delay = 600;
+ var delay = 300;
if ($layout.hasClass('menu-hovered')) {
delay = 0;
@@ -318,9 +350,10 @@
);
return;
}
- this.setActive($(active));
+ this.setActiveAndSelected($(active))
} else {
this.resetActive();
+ this.resetSelected();
}
};
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/public/js/icinga/history.js
^
|
@@ -63,10 +63,13 @@
}
var url = '';
+ var title = '';
// We only store URLs of containers sitting directly under #main:
$('#main > .container').each(function (idx, container) {
- var cUrl = $(container).data('icingaUrl');
+ var $container = $(container),
+ cUrl = $container.data('icingaUrl'),
+ cTitle = $container.data('icingaTitle');
// TODO: I'd prefer to have the rightmost URL first
if ('undefined' !== typeof cUrl) {
@@ -77,6 +80,10 @@
url = url + '#!' + cUrl;
}
}
+
+ if (typeof cTitle !== 'undefined') {
+ title = cTitle; // Only uses the rightmost title
+ }
});
// Did we find any URL? Then push it!
@@ -84,6 +91,9 @@
this.icinga.logger.debug('Pushing current state to history');
this.push(url);
}
+ if (title !== '') {
+ this.icinga.ui.setTitle(title);
+ }
},
/**
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/public/js/icinga/loader.js
^
|
@@ -107,7 +107,12 @@
// Ask for a new window id in case we don't already have one
if (this.icinga.ui.hasWindowId()) {
- headers['X-Icinga-WindowId'] = this.icinga.ui.getWindowId();
+ var windowId = this.icinga.ui.getWindowId();
+ var containerId = this.icinga.ui.getUniqueContainerId($target);
+ if (containerId) {
+ windowId = windowId + '_' + containerId;
+ }
+ headers['X-Icinga-WindowId'] = windowId;
} else {
headers['X-Icinga-WindowId'] = 'undefined';
}
@@ -139,10 +144,15 @@
req.fail(this.onFailure);
req.complete(this.onComplete);
req.autorefresh = autorefresh;
+ req.method = method;
req.action = action;
req.addToHistory = true;
req.progressTimer = progressTimer;
+ if (url.match(/#/)) {
+ req.forceFocus = url.split(/#/)[1];
+ }
+
if (id) {
this.requests[id] = req;
}
@@ -349,10 +359,7 @@
return true;
}
- this.redirectToUrl(
- redirect, req.$target, req.url, req.getResponseHeader('X-Icinga-Rerender-Layout'), req.forceFocus,
- req.getResponseHeader('X-Icinga-Refresh')
- );
+ this.redirectToUrl(redirect, req.$target, req);
return true;
},
@@ -361,14 +368,20 @@
*
* @param {string} url
* @param {object} $target
- * @param {string} origin
- * @param {boolean} rerenderLayout
+ * @param {XMLHttpRequest} referrer
*/
- redirectToUrl: function (url, $target, origin, rerenderLayout, forceFocus, autoRefreshInterval) {
- var icinga = this.icinga;
-
- if (typeof rerenderLayout === 'undefined') {
- rerenderLayout = false;
+ redirectToUrl: function (url, $target, referrer) {
+ var icinga = this.icinga,
+ rerenderLayout,
+ autoRefreshInterval,
+ forceFocus,
+ origin;
+
+ if (typeof referrer !== 'undefined') {
+ rerenderLayout = referrer.getResponseHeader('X-Icinga-Rerender-Layout');
+ autoRefreshInterval = referrer.autoRefreshInterval;
+ forceFocus = referrer.forceFocus;
+ origin = referrer.url;
}
icinga.logger.debug(
@@ -416,6 +429,7 @@
var req = this.loadUrl(url, $target);
req.forceFocus = url === origin ? forceFocus : null;
req.autoRefreshInterval = autoRefreshInterval;
+ req.referrer = referrer;
}
}
},
@@ -448,9 +462,8 @@
this.failureNotice = null;
}
- var url = req.url;
this.icinga.logger.debug(
- 'Got response for ', req.$target, ', URL was ' + url
+ 'Got response for ', req.$target, ', URL was ' + req.url
);
this.processNotificationHeader(req);
@@ -531,7 +544,7 @@
var title = req.getResponseHeader('X-Icinga-Title');
if (title && ! req.autorefresh && req.$target.closest('.dashboard').length === 0) {
- this.icinga.ui.setTitle(decodeURIComponent(title));
+ req.$target.data('icingaTitle', decodeURIComponent(title));
}
// Set a window identifier if the server asks us to do so
@@ -570,6 +583,20 @@
rendered = true;
}
+ var referrer = req.referrer;
+ if (typeof referrer === 'undefined') {
+ referrer = req;
+ }
+
+ var autoSubmit = false;
+ if (referrer.method === 'POST') {
+ var newUrl = this.icinga.utils.parseUrl(req.url);
+ var currentUrl = this.icinga.utils.parseUrl(req.$target.data('icingaUrl'));
+ if (newUrl.path === currentUrl.path && this.icinga.utils.objectsEqual(newUrl.params, currentUrl.params)) {
+ autoSubmit = true;
+ }
+ }
+
req.$target.data('icingaUrl', req.url);
this.icinga.ui.initializeTriStates($resp);
@@ -583,13 +610,10 @@
}
// .html() removes outer div we added above
- this.renderContentToContainer($resp.html(), req.$target, req.action, req.autorefresh, req.forceFocus);
+ this.renderContentToContainer($resp.html(), req.$target, req.action, req.autorefresh, req.forceFocus, autoSubmit);
if (oldNotifications) {
oldNotifications.appendTo($('#notifications'));
}
- if (url.match(/#/)) {
- setTimeout(this.icinga.ui.focusElement, 0, url.split(/#/)[1], req.$target);
- }
if (newBody) {
this.icinga.ui.fixDebugVisibility().triggerWindowResize();
}
@@ -610,7 +634,7 @@
var url = req.url;
if (req.$target[0].id === 'col1') {
- this.icinga.behaviors.navigation.trySetActiveByUrl(url);
+ this.icinga.behaviors.navigation.trySetActiveAndSelectedByUrl(url);
}
var $forms = $('[action="' + this.icinga.utils.parseUrl(url).path + '"]');
@@ -756,17 +780,22 @@
/**
* Smoothly render given HTML to given container
*/
- renderContentToContainer: function (content, $container, action, autorefresh, forceFocus) {
+ renderContentToContainer: function (content, $container, action, autorefresh, forceFocus, autoSubmit) {
// Container update happens here
var scrollPos = false;
var _this = this;
var containerId = $container.attr('id');
var activeElementPath = false;
+ var navigationAnchor = false;
var focusFallback = false;
if (forceFocus && forceFocus.length) {
- activeElementPath = this.icinga.utils.getCSSPath($(forceFocus));
+ if (typeof forceFocus === 'string') {
+ navigationAnchor = forceFocus;
+ } else {
+ activeElementPath = this.icinga.utils.getCSSPath($(forceFocus));
+ }
} else if (document.activeElement && document.activeElement.id === 'search') {
activeElementPath = '#search';
} else if (document.activeElement
@@ -785,8 +814,8 @@
activeElementPath = this.icinga.utils.getCSSPath($activeElement);
}
- if (typeof containerId !== 'undefined') {
- if (autorefresh) {
+ if (! forceFocus && typeof containerId !== 'undefined') {
+ if (autorefresh || autoSubmit) {
scrollPos = $container.scrollTop();
} else {
scrollPos = 0;
@@ -844,7 +873,9 @@
}
this.icinga.ui.assignUniqueContainerIds();
- if (! activeElementPath) {
+ if (navigationAnchor) {
+ setTimeout(this.icinga.ui.focusElement, 0, navigationAnchor, $container);
+ } else if (! activeElementPath) {
// Active element was not in this container
if (! autorefresh) {
setTimeout(function() {
@@ -862,7 +893,7 @@
var $activeElement = $(activeElementPath);
if ($activeElement.length && $activeElement.is(':visible')) {
- $activeElement.focus();
+ $activeElement[0].focus({preventScroll: autorefresh});
} else if (! autorefresh) {
if (focusFallback) {
$(focusFallback.parent).find(focusFallback.child).focus();
@@ -874,14 +905,22 @@
}, 0);
}
- if (scrollPos !== false) {
- setTimeout($container.scrollTop.bind($container), 0, scrollPos);
- }
var icinga = this.icinga;
//icinga.events.applyHandlers($container);
icinga.ui.initializeControls($container);
icinga.ui.fixControls();
+ if (scrollPos !== false) {
+ $container.scrollTop(scrollPos);
+
+ // Fallback for browsers without support for focus({preventScroll: true})
+ setTimeout(function () {
+ if ($container.scrollTop() !== scrollPos) {
+ $container.scrollTop(scrollPos);
+ }
+ }, 0);
+ }
+
// Re-enable all click events (disabled as of performance reasons)
// $('*').off('click');
},
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/public/js/icinga/ui.js
^
|
@@ -186,7 +186,7 @@
var kill = this.cutContainer($('#col1'));
this.pasteContainer($('#col1'), col2);
this.fixControls();
- this.icinga.behaviors.navigation.trySetActiveByUrl($('#col1').data('icingaUrl'));
+ this.icinga.behaviors.navigation.trySetActiveAndSelectedByUrl($('#col1').data('icingaUrl'));
},
cutContainer: function ($col) {
@@ -194,17 +194,21 @@
'elements': $('#' + $col.attr('id') + ' > *').detach(),
'data': {
'data-icinga-url': $col.data('icingaUrl'),
+ 'data-icinga-title': $col.data('icingaTitle'),
'data-icinga-refresh': $col.data('icingaRefresh'),
'data-last-update': $col.data('lastUpdate'),
- 'data-icinga-module': $col.data('icingaModule')
+ 'data-icinga-module': $col.data('icingaModule'),
+ 'data-icinga-container-id': $col.data('icingaContainerId')
},
'class': $col.attr('class')
};
this.icinga.loader.stopPendingRequestsFor($col);
$col.removeData('icingaUrl');
+ $col.removeData('icingaTitle');
$col.removeData('icingaRefresh');
$col.removeData('lastUpdate');
$col.removeData('icingaModule');
+ $col.removeData('icingaContainerId');
$col.removeAttr('class').attr('class', 'container');
return props;
},
@@ -213,9 +217,11 @@
backup['elements'].appendTo($col);
$col.attr('class', backup['class']); // TODO: ie memleak? remove first?
$col.data('icingaUrl', backup['data']['data-icinga-url']);
+ $col.data('icingaTitle', backup['data']['data-icinga-title']);
$col.data('icingaRefresh', backup['data']['data-icinga-refresh']);
$col.data('lastUpdate', backup['data']['data-last-update']);
$col.data('icingaModule', backup['data']['data-icinga-module']);
+ $col.data('icingaContainerId', backup['data']['data-icinga-container-id']);
},
triggerWindowResize: function () {
@@ -294,6 +300,7 @@
closeContainer: function($c) {
$c.removeData('icingaUrl');
+ $c.removeData('icingaTitle');
$c.removeData('icingaRefresh');
$c.removeData('lastUpdate');
$c.removeData('icingaModule');
@@ -567,18 +574,22 @@
$container.find('.controls').each(function() {
var $controls = $(this);
- if (! $controls.next('.fake-controls').length) {
+ if (! $controls.prev('.fake-controls').length) {
var $tabs = $controls.find('.tabs', $controls);
if ($tabs.length && $controls.children().length > 1 && ! $tabs.next('.tabs-spacer').length) {
$tabs.after($('<div class="tabs-spacer"></div>'));
}
var $fakeControls = $('<div class="fake-controls"></div>');
$fakeControls.height($controls.height()).css({
- display: 'block'
+ // That's only temporary. It's reset in fixControls, which is called at the end of this
+ // function. Its purpose is to prevent the content from jumping up upon auto-refreshes.
+ // It works by making the fake-controls appear at the same vertical level as the controls
+ // and the height of the content then doesn't change when taking the controls out of the flow.
+ float: 'right'
});
- $controls.css({
+ $controls.before($fakeControls).css({
position: 'fixed'
- }).after($fakeControls);
+ });
}
});
@@ -669,12 +680,15 @@
$container.find('.controls').each(function() {
var $controls = $(this);
- var $fakeControls = $controls.next('.fake-controls');
+ var $fakeControls = $controls.prev('.fake-controls');
+ $fakeControls.css({
+ float: '', // Set by initializeControls
+ height: $controls.height()
+ });
$controls.css({
top: $container.offsetParent().position().top,
width: $fakeControls.outerWidth()
});
- $fakeControls.height($controls.height());
});
var $statusBar = $container.children('.monitoring-statusbar');
@@ -692,21 +706,44 @@
this.fixControls();
},
+ getUniqueContainerId: function ($cont) {
+ if (typeof $cont === 'undefined' || !$cont.length) {
+ return null;
+ }
+
+ var containerId = $cont.data('icingaContainerId');
+ if (typeof containerId === 'undefined') {
+ /**
+ * Only generate an id if it's not for col1 or the menu (which are using the non-suffixed window id).
+ * This is based on the assumption that the server only knows about the menu and first column
+ * and therefore does not need to protect its ids. (As the menu is most likely part of the sidebar)
+ */
+ if ($cont.attr('id') === 'menu' || $cont.attr('id') === 'col1') {
+ return null;
+ }
+
+ containerId = this.icinga.utils.generateId(6); // Random because the content may move
+ $cont.data('icingaContainerId', containerId);
+ }
+
+ return containerId;
+ },
+
getWindowId: function () {
if (! this.hasWindowId()) {
return undefined;
}
- return window.name.match(/^Icinga_([a-zA-Z0-9]+)$/)[1];
+ return window.name.match(/^Icinga-([a-zA-Z0-9]+)$/)[1];
},
hasWindowId: function () {
- var res = window.name.match(/^Icinga_([a-zA-Z0-9]+)$/);
+ var res = window.name.match(/^Icinga-([a-zA-Z0-9]+)$/);
return typeof res === 'object' && null !== res;
},
setWindowId: function (id) {
this.icinga.logger.debug('Setting new window id', id);
- window.name = 'Icinga_' + id;
+ window.name = 'Icinga-' + id;
},
destroy: function () {
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/public/js/icinga/utils.js
^
|
@@ -352,6 +352,14 @@
return keys;
},
+ objectsEqual: function equals(obj1, obj2) {
+ return Object.keys(obj1)
+ .concat(Object.keys(obj2))
+ .every(function (key) {
+ return obj1[key] === obj2[key];
+ });
+ },
+
/**
* Cleanup
*/
@@ -404,6 +412,37 @@
str = padding + str;
}
return str;
+ },
+
+ /**
+ * Shuffle a string
+ *
+ * @param {String} str The string to shuffle
+ *
+ * @returns {String} The shuffled string
+ */
+ shuffleString: function(str) {
+ var a = str.split(""),
+ n = a.length;
+
+ for(var i = n - 1; i > 0; i--) {
+ var j = Math.floor(Math.random() * (i + 1));
+ var tmp = a[i];
+ a[i] = a[j];
+ a[j] = tmp;
+ }
+ return a.join("");
+ },
+
+ /**
+ * Generate an id
+ *
+ * @param {Number} len The desired length of the id
+ *
+ * @returns {String} The id
+ */
+ generateId: function(len) {
+ return this.shuffleString('abcefghijklmnopqrstuvwxyz').substr(0, len);
}
};
|
[-]
[+]
|
Added |
v2.6.3.tar.gz/test/check-syntax.php
^
|
@@ -0,0 +1,145 @@
+#!/usr/bin/env php
+<?php
+
+function findPhpFiles($dir, &$files = [])
+{
+ if (substr($dir, -1, 1) !== DIRECTORY_SEPARATOR) {
+ $dir .= DIRECTORY_SEPARATOR;
+ }
+ if ($dh = opendir($dir)) {
+ while (($name = readdir($dh)) !== false) {
+ $path = $dir . $name;
+
+ if (substr($name, 0, 1) === '.') {
+ continue;
+ } elseif (is_file($path) && preg_match('~\.ph(p|tml)$~i', $path)) {
+ $files[] = $path;
+ } elseif (is_dir($path)) {
+ findPhpFiles($path, $files);
+ }
+ }
+ closedir($dh);
+
+ return $files;
+ } else {
+ throw new Exception('Could not read directory: ' . $dir);
+ }
+}
+
+function stdout($t, $color = '32')
+{
+ if (posix_isatty(STDOUT) && $color) {
+ $t = "\e[${color}m" . $t . "\e[39m";
+ }
+ fwrite(STDOUT, $t);
+}
+
+function stderr($t)
+{
+ if (posix_isatty(STDERR)) {
+ $t = "\e[91m" . $t . "\e[39m";
+ }
+ fwrite(STDERR, $t);
+}
+
+function checkFile($path, &$errors)
+{
+ $escapedPath = escapeshellarg($path);
+ exec("php -l ${escapedPath} 2>&1 >/dev/null", $output, $rc);
+
+ if (! empty($output) || $rc != 0) {
+ stdout('E', '91');
+
+ foreach ($output as $line) {
+ // remove own name from text
+ $line = preg_replace('~ in ' . preg_quote($path) . '~i', '', $line);
+
+ $errors[$path][] = $line;
+ }
+ } else {
+ stdout('.');
+ }
+}
+
+function usage()
+{
+ printf("Usage: %s [--verbose] [--exclude file-regex] [path]\n\n", $_SERVER['argv'][0]);
+}
+
+function main($argv)
+{
+ $fileCount = 0;
+ $verbose = false;
+ $errors = [];
+ $excludes = [];
+ $searchPaths = [];
+
+ for ($i = 1; $i < count($argv); $i++) {
+ $arg = $argv[$i];
+ switch ($arg) {
+ case '-h':
+ case '--help':
+ usage();
+ return 1;
+ case '-v':
+ case '--verbose':
+ $verbose = true;
+ break;
+ case '-e':
+ case '--exclude':
+ $excludes[] = $argv[++$i];
+ break;
+ default:
+ if (substr($arg, 0, 1) === '-') {
+ stderr("Unknown argument: $arg");
+ return 1;
+ } else {
+ $searchPaths[] = $arg;
+ }
+ }
+ }
+
+ if (empty($searchPaths)) {
+ $searchPaths = ['.'];
+ }
+
+ $files = [];
+ foreach ($searchPaths as $basePath) {
+ findPhpFiles($basePath, $files);
+ }
+
+ foreach ($files as $file) {
+ foreach ($excludes as $exclude) {
+ if (preg_match("~$exclude~", $file)) {
+ continue 2;
+ }
+ }
+
+ $fileCount++;
+
+ if ($verbose) {
+ printf("%s\n", $file);
+ }
+ checkFile($file, $errors);
+ }
+
+ $errorCount = count($errors);
+ if ($fileCount === 0) {
+ stderr("error: No files found!\n");
+ return 2;
+ } elseif ($errorCount > 0) {
+ stdout("\n");
+
+ foreach ($errors as $file => $errList) {
+ stderr("\n$file\n " . join("\n ", $errList) . "\n");
+ }
+
+ stderr(sprintf("\nFound syntax errors in %d of %d files! \n", $errorCount, $fileCount));
+ return 1;
+ } else {
+ stdout(sprintf("\n\nChecked %d files successfully! \n", $fileCount));
+ return 0;
+ }
+}
+
+exit(main($_SERVER['argv']));
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/test/php/bootstrap.php
^
|
@@ -18,7 +18,11 @@
}
// This is needed to get the Zend Plugin loader working
-set_include_path(implode(PATH_SEPARATOR, array($libraryPath, get_include_path())));
+set_include_path(implode(PATH_SEPARATOR, [
+ $libraryPath,
+ $basePath . DIRECTORY_SEPARATOR . 'vendor',
+ get_include_path()
+]));
require_once 'Mockery/Loader.php';
$mockeryLoader = new \Mockery\Loader;
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/test/php/library/Icinga/File/Ini/IniParserTest.php
^
|
@@ -3,7 +3,6 @@
namespace Tests\Icinga\Config;
-use Icinga\File\Ini\Dom\Document;
use Icinga\File\Ini\IniWriter;
use Icinga\Test\BaseTestCase;
use Icinga\Application\Config;
@@ -28,22 +27,45 @@
public function testSectionNameEscaping()
{
$config = <<<'EOD'
-[title with \]bracket]
-key1 = "1"
-key2 = "2"
-
[title with \"quote]
-key1 = "1"
-key2 = "2"
+
+[title with \;semicolon]
+
+[title with \\backslash]
EOD;
+
$doc = IniParser::parseIni($config);
$this->assertTrue(
- $doc->hasSection('title with ]bracket'),
- 'IniParser does not recognize escaped bracket in section'
+ $doc->hasSection('title with "quote'),
+ 'IniParser::parseIni does not recognize escaped quotes in section names'
);
$this->assertTrue(
- $doc->hasSection('title with "quote'),
- 'IniParser does not recognize escaped quote in section'
+ $doc->hasSection('title with ;semicolon'),
+ 'IniParser::parseIni does not recognize escaped semicolons in section names'
+ );
+ $this->assertTrue(
+ $doc->hasSection('title with \\backslash'),
+ 'IniParser::parseIni does not recognize escaped backslashes in section names'
+ );
+
+ (new IniWriter(Config::fromArray([
+ 'title with "quote' => [],
+ 'title with ;semicolon' => [],
+ 'title with \\backslash' => []
+ ]), $this->tempFile))->write();
+
+ $configObject = IniParser::parseIniFile($this->tempFile);
+ $this->assertTrue(
+ $configObject->hasSection('title with "quote'),
+ 'IniParser::parseIniFile does not recognize escaped quotes in section names'
+ );
+ $this->assertTrue(
+ $configObject->hasSection('title with ;semicolon'),
+ 'IniParser::parseIniFile does not recognize escaped semicolons in section names'
+ );
+ $this->assertTrue(
+ $configObject->hasSection('title with \\backslash'),
+ 'IniParser::parseIniFile does not recognize escaped backslashes in section names'
);
}
@@ -52,12 +74,50 @@
$config = <<<'EOD'
[section]
key1 = "key with escaped \"quote"
+key2 = "key with escaped backslash \\"
+key3 = "key with escaped backslash followed by quote \\\""
EOD;
+
$doc = IniParser::parseIni($config);
$this->assertEquals(
'key with escaped "quote',
$doc->getSection('section')->getDirective('key1')->getValue(),
- 'IniParser does not recognize escaped bracket in section'
+ 'IniParser::parseIni does not recognize escaped quotes in values'
+ );
+ $this->assertEquals(
+ 'key with escaped backslash \\',
+ $doc->getSection('section')->getDirective('key2')->getValue(),
+ 'IniParser::parseIni does not recognize escaped backslashes in values'
+ );
+ $this->assertEquals(
+ 'key with escaped backslash followed by quote \\"',
+ $doc->getSection('section')->getDirective('key3')->getValue(),
+ 'IniParser::parseIni does not recognize escaped backslashes followed by quotes in values'
+ );
+
+ (new IniWriter(Config::fromArray([
+ 'section' => [
+ 'key1' => 'key with escaped "quote',
+ 'key2' => 'key with escaped backslash \\',
+ 'key3' => 'key with escaped backslash followed by quote \\"'
+ ]
+ ]), $this->tempFile))->write();
+
+ $configObject = IniParser::parseIniFile($this->tempFile);
+ $this->assertEquals(
+ 'key with escaped "quote',
+ $configObject->getSection('section')->get('key1'),
+ 'IniParser::parseIniFile does not recognize escaped quotes in values'
+ );
+ $this->assertEquals(
+ 'key with escaped backslash \\',
+ $configObject->getSection('section')->get('key2'),
+ 'IniParser::parseIniFile does not recognize escaped backslashes in values'
+ );
+ $this->assertEquals(
+ 'key with escaped backslash followed by quote \\"',
+ $configObject->getSection('section')->get('key3'),
+ 'IniParser::parseIniFile does not recognize escaped backslashes followed by quotes in values'
);
}
@@ -72,7 +132,107 @@
$this->assertEquals(
2,
count(explode("\n", $doc->getSection('section')->getDirective('key1')->getValue())),
- 'IniParser does not recognize multi-line values'
+ 'IniParser::parseIni does not recognize multi-line values'
+ );
+
+ (new IniWriter(Config::fromArray([
+ 'section' => [
+ 'key1' => "with some\nnewline in the value"
+ ]
+ ]), $this->tempFile))->write();
+
+ $doc = IniParser::parseIniFile($this->tempFile);
+ $this->assertEquals(
+ 2,
+ count(explode("\n", $doc->getSection('section')->get('key1'))),
+ 'IniParser::parseIniFile does not recognize multi-line values'
+ );
+ }
+
+ public function testEnvironmentVariableResolutionDoesNotWork()
+ {
+ (new IniWriter(Config::fromArray([
+ 'section' => [
+ 'key1' => '${PATH}_${APACHE_RUN_DIR}',
+ 'key2' => '${APACHE_RUN_USER}'
+ ]
+ ]), $this->tempFile))->write();
+
+ $configObject = IniParser::parseIniFile($this->tempFile);
+ $this->assertEquals(
+ '${PATH}_${APACHE_RUN_DIR}',
+ $configObject->getSection('section')->get('key1'),
+ 'IniParser::parseIniFile does resolve environment variables'
+ );
+ $this->assertEquals(
+ '${APACHE_RUN_USER}',
+ $configObject->getSection('section')->get('key2'),
+ 'IniParser::parseIniFile does resolve environment variables'
+ );
+ }
+
+ public function testPhpBug76965()
+ {
+ $config = <<<'EOD'
+[section]
+a = "foobar"
+b = "foo"bar ""
+c = "foobar" ; comment
+d =' foo '
+e =foo
+f = foo
+g = ""foo" "; Edge case, see below for more details
+EOD;
+
+ $parsedConfig = parse_ini_string($config, true, INI_SCANNER_RAW)['section'];
+ if ($parsedConfig['a'] === 'foobar') {
+ $this->markTestSkipped('This version of PHP is not affected by bug #76965');
+ }
+
+ $this->assertEquals('"foobar" ', $parsedConfig['a'], 'PHP version affected but bug #76965 not in effect?');
+ $this->assertEquals('"foo"bar "" ', $parsedConfig['b'], 'PHP version affected but bug #76965 not in effect?');
+ $this->assertEquals('"foobar" ', $parsedConfig['c'], 'PHP version affected but bug #76965 not in effect?');
+ $this->assertEquals("' foo ' ", $parsedConfig['d'], 'PHP version affected but bug #76965 not in effect?');
+
+ file_put_contents($this->tempFile, $config);
+ $configObject = IniParser::parseIniFile($this->tempFile);
+
+ $this->assertEquals(
+ 'foobar',
+ $configObject->get('section', 'a'),
+ 'Workaround for PHP bug #76965 missing'
+ );
+ $this->assertEquals(
+ 'foo"bar "',
+ $configObject->get('section', 'b'),
+ 'Workaround for PHP bug #76965 missing'
+ );
+ $this->assertEquals(
+ 'foobar',
+ $configObject->get('section', 'c'),
+ 'Workaround for PHP bug #76965 missing'
+ );
+ $this->assertEquals(
+ ' foo ',
+ $configObject->get('section', 'd'),
+ 'Workaround for PHP bug #76965 missing'
+ );
+ $this->assertEquals(
+ 'foo',
+ $configObject->get('section', 'e'),
+ 'Workaround for PHP bug #76965 missing'
+ );
+ $this->assertEquals(
+ 'foo',
+ $configObject->get('section', 'f'),
+ 'Workaround for PHP bug #76965 missing'
);
+ // This is an edge case which will fail with the current work-around implementation.
+ // Though, it's considered a really rare case and as such deliberately ignored.
+ /*$this->assertEquals(
+ '"foo" ',
+ $configObject->get('section', 'g'),
+ 'Workaround for PHP bug #76965 too greedy'
+ );*/
}
}
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/test/php/library/Icinga/File/Ini/IniWriterTest.php
^
|
@@ -275,9 +275,14 @@
);
$rendered = $writer->render();
+ $this->assertRegExp(
+ '~linebreak\\\\nin line~',
+ $rendered,
+ 'newlines in values are not escaped'
+ );
$this->assertEquals(
+ 4,
count(explode("\n", $rendered)),
- 5,
'generated config should not contain more than three line breaks'
);
}
@@ -285,9 +290,6 @@
public function testSectionNameEscaping()
{
$config = <<<'EOD'
-[section [brackets\]]
-foo = "bar"
-
[section \;comment]
foo = "bar"
@@ -304,7 +306,6 @@
$writer = new IniWriter(
Config::fromArray(
array(
- 'section [brackets]' => array('foo' => 'bar'),
'section ;comment' => array('foo' => 'bar'),
'section "quotes"' => array('foo' => 'bar'),
'section with \\' => array('foo' => 'bar'),
@@ -321,6 +322,15 @@
);
}
+ /**
+ * @expectedException \Icinga\Exception\ConfigurationError
+ */
+ public function testWhetherBracketsAreIllegalInSectionNames()
+ {
+ $config = Config::fromArray(['section [brackets]' => []]);
+ (new IniWriter($config, $this->tempFile))->write();
+ }
+
public function testDirectiveValueEscaping()
{
$config = <<<'EOD'
|
[-]
[+]
|
Added |
v2.6.3.tar.gz/test/php/library/Icinga/Util/EnvironmentTest.php
^
|
@@ -0,0 +1,43 @@
+<?php
+/* Icinga Web 2 | (c) 2018 Icinga Development Team | GPLv2+ */
+
+namespace Tests\Icinga\Util;
+
+use Icinga\Util\Environment;
+use Icinga\Test\BaseTestCase;
+
+class EnvironmentTest extends BaseTestCase
+{
+ public function testRaiseMemoryLimit()
+ {
+ // set a low limit
+ ini_set('memory_limit', '128M');
+
+ Environment::raiseMemoryLimit('512M');
+ $this->assertEquals('536870912' /* 512M */, ini_get('memory_limit'));
+
+ Environment::raiseMemoryLimit('1G');
+ $this->assertEquals('1073741824' /* 1G */, ini_get('memory_limit'));
+
+ Environment::raiseMemoryLimit('512M');
+ $this->assertEquals('1073741824' /* 1G */, ini_get('memory_limit'));
+
+ // in phpunit usually there is no limit
+ ini_set('memory_limit', '-1');
+ }
+
+ public function testRaiseExecutionTime()
+ {
+ Environment::raiseExecutionTime(300);
+ $this->assertEquals(300, ini_get('max_execution_time'));
+
+ Environment::raiseExecutionTime(600);
+ $this->assertEquals(600, ini_get('max_execution_time'));
+
+ Environment::raiseExecutionTime(300);
+ $this->assertEquals(600, ini_get('max_execution_time'));
+
+ // in phpunit usually there is no limit
+ ini_set('max_execution_time', '0');
+ }
+}
|
[-]
[+]
|
Changed |
v2.6.3.tar.gz/test/setup_vendor.sh
^
|
@@ -2,57 +2,72 @@
set -ex
-ICINGAWEB_HOME=${ICINGAWEB_HOME:="$(dirname "$(readlink -f $(dirname "$0"))")"}
-PHPCS_VERSION=${PHPCS_VERSION:=3.0.2}
+ICINGAWEB_HOME=${ICINGAWEB_HOME:="$(dirname "$(readlink -f "$(dirname "$0")")")"}
+PHPCS_VERSION=${PHPCS_VERSION:=3.3.2}
MOCKERY_VERSION=${MOCKERY_VERSION:=0.9.9}
HAMCREST_VERSION=${HAMCREST_VERSION:=2.0.0}
PHPUNIT_VERSION=${PHPUNIT_VERSION:=5.7}
-cd ${ICINGAWEB_HOME}
+cd "${ICINGAWEB_HOME}"
test -d vendor || mkdir vendor
+cd vendor/
+
+del_old_link() {
+ if [ -L "$1" ]; then
+ rm "$1"
+ fi
+}
# phpunit
-phpunit_path="vendor/phpunit-${PHPUNIT_VERSION}"
+phpunit_path="phpunit-${PHPUNIT_VERSION}"
if [ ! -e "${phpunit_path}".phar ]; then
wget -O "${phpunit_path}".phar https://phar.phpunit.de/phpunit-${PHPUNIT_VERSION}.phar
fi
ln -svf "${phpunit_path}".phar phpunit.phar
+del_old_link ../phpunit.phar
# phpcs
-phpcs_path="vendor/phpcs-${PHPCS_VERSION}"
+phpcs_path="phpcs-${PHPCS_VERSION}"
if [ ! -e "${phpcs_path}".phar ]; then
wget -O "${phpcs_path}".phar \
https://github.com/squizlabs/PHP_CodeSniffer/releases/download/${PHPCS_VERSION}/phpcs.phar
fi
ln -svf "${phpcs_path}".phar phpcs.phar
-phpcbf_path="vendor/phpcbf-${PHPCS_VERSION}"
+del_old_link ../phpcs.phar
+
+phpcbf_path="phpcbf-${PHPCS_VERSION}"
if [ ! -e "${phpcbf_path}".phar ]; then
wget -O "${phpcbf_path}".phar \
https://github.com/squizlabs/PHP_CodeSniffer/releases/download/${PHPCS_VERSION}/phpcbf.phar
fi
ln -svf "${phpcbf_path}".phar phpcbf.phar
+del_old_link ../phpcbf.phar
# mockery
-mockery_path="vendor/mockery-${MOCKERY_VERSION}"
+mockery_path="mockery-${MOCKERY_VERSION}"
if [ ! -e "${mockery_path}".tar.gz ]; then
wget -O "${mockery_path}".tar.gz \
https://github.com/mockery/mockery/archive/${MOCKERY_VERSION}.tar.gz
fi
if [ ! -d "${mockery_path}" ]; then
- tar xf "${mockery_path}".tar.gz -C vendor/
+ tar xf "${mockery_path}".tar.gz
fi
-ln -svf "${mockery_path}"/library/Mockery
-ln -svf "${mockery_path}"/library/Mockery.php
+ln -svf "${mockery_path}"/library/Mockery Mockery
+ln -svf "${mockery_path}"/library/Mockery.php Mockery.php
+del_old_link ../Mockery
+del_old_link ../Mockery.php
# hamcrest
-hamcrest_path="vendor/hamcrest-php-${HAMCREST_VERSION}"
+hamcrest_path="hamcrest-php-${HAMCREST_VERSION}"
if [ ! -e "${hamcrest_path}".tar.gz ]; then
wget -O "${hamcrest_path}".tar.gz \
https://github.com/hamcrest/hamcrest-php/archive/v${HAMCREST_VERSION}.tar.gz
fi
if [ ! -d "${hamcrest_path}" ]; then
- tar xf "${hamcrest_path}".tar.gz -C vendor/
+ tar xf "${hamcrest_path}".tar.gz
fi
-ln -svf "${hamcrest_path}"/hamcrest/Hamcrest
-ln -svf "${hamcrest_path}"/hamcrest/Hamcrest.php
+ln -svf "${hamcrest_path}"/hamcrest/Hamcrest Hamcrest
+ln -svf "${hamcrest_path}"/hamcrest/Hamcrest.php Hamcrest.php
+del_old_link ../Hamcrest
+del_old_link ../Hamcrest.php
|