diff --git a/application/controllers/ListController.php b/application/controllers/ListController.php index 972573dc1..ca7265f0e 100644 --- a/application/controllers/ListController.php +++ b/application/controllers/ListController.php @@ -44,14 +44,12 @@ class ListController extends Controller } $this->addTitleTab('application log'); - $pattern = '/^(?[0-9]{4}(-[0-9]{2}){2}' // date - . 'T[0-9]{2}(:[0-9]{2}){2}([\\+\\-][0-9]{2}:[0-9]{2})?)' // time - . ' - (?[A-Za-z]+)' // loglevel - . ' - (?.*)$/'; $resource = new FileReader(new ConfigObject(array( 'filename' => Config::app()->get('logging', 'file'), - 'fields' => $pattern + 'fields' => '/(?[0-9]{4}(?:-[0-9]{2}){2}' // date + . 'T[0-9]{2}(?::[0-9]{2}){2}(?:[\+\-][0-9]{2}:[0-9]{2})?)' // time + . ' - (?[A-Za-z]+) - (?.*)(?!.)/msS' // loglevel, message ))); $this->view->logData = $resource->select()->order('DESC')->paginate(); diff --git a/application/forms/Config/AuthenticationBackendReorderForm.php b/application/forms/Config/AuthenticationBackendReorderForm.php index e4ac90c12..34f20d851 100644 --- a/application/forms/Config/AuthenticationBackendReorderForm.php +++ b/application/forms/Config/AuthenticationBackendReorderForm.php @@ -51,7 +51,7 @@ class AuthenticationBackendReorderForm extends ConfigForm try { if ($configForm->move($backendName, $position)->save()) { - Notification::success($this->translate('Authentication order updated!')); + Notification::success($this->translate('Authentication order updated')); } else { return false; } diff --git a/application/locale/it_IT/LC_MESSAGES/icinga.po b/application/locale/it_IT/LC_MESSAGES/icinga.po index 2b867ca14..73d616bfa 100644 --- a/application/locale/it_IT/LC_MESSAGES/icinga.po +++ b/application/locale/it_IT/LC_MESSAGES/icinga.po @@ -199,8 +199,8 @@ msgid "Authentication backend name missing" msgstr "Nome del Backend di autenticazione non specificato" #: /usr/share/icingaweb2/application/forms/Config/AuthenticationBackendReorderForm.php:54 -msgid "Authentication order updated!" -msgstr "Ordine di autenticazione aggiornato!" +msgid "Authentication order updated" +msgstr "Ordine di autenticazione aggiornato" #: /usr/share/icingaweb2/application/forms/AutoRefreshForm.php:44 msgid "Auto refresh successfully disabled" diff --git a/application/locale/pt_BR/LC_MESSAGES/icinga.po b/application/locale/pt_BR/LC_MESSAGES/icinga.po index 01dc18a9f..16aba2378 100644 --- a/application/locale/pt_BR/LC_MESSAGES/icinga.po +++ b/application/locale/pt_BR/LC_MESSAGES/icinga.po @@ -130,8 +130,8 @@ msgid "Authentication backend name missing" msgstr "Falta o nome do backend de autenticação" #: /usr/local/icingaweb/application/forms/Config/AuthenticationBackendReorderForm.php:55 -msgid "Authentication order updated!" -msgstr "Ordem da autenticação atualizada!" +msgid "Authentication order updated" +msgstr "Ordem da autenticação atualizada" #: /usr/local/icingaweb/application/forms/Config/AuthenticationBackendConfigForm.php:307 msgid "Autologin" diff --git a/application/views/scripts/list/applicationlog.phtml b/application/views/scripts/list/applicationlog.phtml index cc412eb9c..00102e855 100644 --- a/application/views/scripts/list/applicationlog.phtml +++ b/application/views/scripts/list/applicationlog.phtml @@ -19,7 +19,7 @@ escape($value->loglevel) ?> - escape($value->message) ?> + escape($value->message), false) ?> diff --git a/library/Icinga/Application/Logger/Writer/SyslogWriter.php b/library/Icinga/Application/Logger/Writer/SyslogWriter.php index e18c5eeec..4494c9971 100644 --- a/library/Icinga/Application/Logger/Writer/SyslogWriter.php +++ b/library/Icinga/Application/Logger/Writer/SyslogWriter.php @@ -67,6 +67,6 @@ class SyslogWriter extends LogWriter public function log($level, $message) { openlog($this->ident, LOG_PID, $this->facility); - syslog(static::$severityMap[$level], $message); + syslog(static::$severityMap[$level], str_replace("\n", ' ', $message)); } } diff --git a/library/Icinga/Application/Modules/Manager.php b/library/Icinga/Application/Modules/Manager.php index 90e55f0b4..e3e5ec6f2 100644 --- a/library/Icinga/Application/Modules/Manager.php +++ b/library/Icinga/Application/Modules/Manager.php @@ -101,6 +101,16 @@ class Manager */ private function detectEnabledModules() { + if (! file_exists($parent = dirname($this->enableDir))) { + return; + } + if (! is_readable($parent)) { + throw new NotReadableError( + 'Cannot read enabled modules. Module directory\'s parent directory "%s" is not readable', + $parent + ); + } + if (! file_exists($this->enableDir)) { return; } diff --git a/library/Icinga/Protocol/File/FileReader.php b/library/Icinga/Protocol/File/FileReader.php index aaef31840..2c43d390a 100644 --- a/library/Icinga/Protocol/File/FileReader.php +++ b/library/Icinga/Protocol/File/FileReader.php @@ -26,6 +26,13 @@ class FileReader implements Selectable, Countable */ protected $filename; + /** + * Cache for static::count() + * + * @var int + */ + protected $count = null; + /** * Create a new reader * @@ -51,7 +58,7 @@ class FileReader implements Selectable, Countable */ public function iterate() { - return new FileIterator($this->filename, $this->fields); + return new LogFileIterator($this->filename, $this->fields); } /** @@ -71,7 +78,10 @@ class FileReader implements Selectable, Countable */ public function count() { - return iterator_count($this->iterate()); + if ($this->count === null) { + $this->count = iterator_count($this->iterate()); + } + return $this->count; } /** diff --git a/library/Icinga/Protocol/File/LogFileIterator.php b/library/Icinga/Protocol/File/LogFileIterator.php new file mode 100644 index 000000000..4b587b58e --- /dev/null +++ b/library/Icinga/Protocol/File/LogFileIterator.php @@ -0,0 +1,154 @@ +file = new SplFileObject($filename); + $this->file->setFlags( + SplFileObject::DROP_NEW_LINE | + SplFileObject::READ_AHEAD + ); + $this->fields = $fields; + } + + public function rewind() + { + $this->file->rewind(); + $this->index = 0; + $this->nextMessage(); + } + + public function next() + { + $this->file->next(); + ++$this->index; + $this->nextMessage(); + } + + /** + * @return string + */ + public function current() + { + return $this->current; + } + + /** + * @return int + */ + public function key() + { + return $this->index; + } + + /** + * @return boolean + */ + public function valid() + { + return $this->valid; + } + + protected function nextMessage() + { + $message = $this->next === null ? array() : array($this->next); + $this->valid = null; + while ($this->file->valid()) { + if (false === ($res = preg_match( + $this->fields, $current = $this->file->current() + ))) { + throw new IcingaException('Failed at preg_match()'); + } + if (empty($message)) { + if ($res === 1) { + $message[] = $current; + } + } else if ($res === 1) { + $this->next = $current; + $this->valid = true; + break; + } else { + $message[] = $current; + } + + $this->file->next(); + } + if ($this->valid === null) { + $this->next = null; + $this->valid = ! empty($message); + } + + if ($this->valid) { + while (! empty($message)) { + $matches = array(); + if (false === ($res = preg_match( + $this->fields, implode(PHP_EOL, $message), $matches + ))) { + throw new IcingaException('Failed at preg_match()'); + } + if ($res === 1) { + $this->current = $matches; + return; + } + array_pop($message); + } + $this->valid = false; + } + } diff --git a/library/Icinga/Web/Session/PhpSession.php b/library/Icinga/Web/Session/PhpSession.php index f4aa72fa3..7f47763c0 100644 --- a/library/Icinga/Web/Session/PhpSession.php +++ b/library/Icinga/Web/Session/PhpSession.php @@ -77,7 +77,7 @@ class PhpSession extends Session } } - $sessionSavePath = session_save_path(); + $sessionSavePath = session_save_path() ?: sys_get_temp_dir(); if (session_module_name() === 'files' && !is_writable($sessionSavePath)) { throw new ConfigurationError("Can't save session, path '$sessionSavePath' is not writable."); } diff --git a/modules/monitoring/application/views/helpers/Customvar.php b/modules/monitoring/application/views/helpers/Customvar.php index 32391b6ce..bb9f70a7e 100644 --- a/modules/monitoring/application/views/helpers/Customvar.php +++ b/modules/monitoring/application/views/helpers/Customvar.php @@ -15,8 +15,12 @@ class Zend_View_Helper_Customvar extends Zend_View_Helper_Abstract public function customvar($struct) { - if (is_string($struct) || is_int($struct) || is_float($struct)) { - return $this->view->escape((string) $struct); + if (is_scalar($struct)) { + return $this->view->escape( + is_string($struct) + ? $struct + : var_export($struct, true) + ); } elseif (is_array($struct)) { return $this->renderArray($struct); } elseif (is_object($struct)) { @@ -38,7 +42,7 @@ class Zend_View_Helper_Customvar extends Zend_View_Helper_Abstract protected function renderObject($object) { - if (empty($object)) { + if (0 === count((array) $object)) { return '{}'; } $out = "{
    \n"; diff --git a/modules/monitoring/application/views/scripts/show/components/customvars.phtml b/modules/monitoring/application/views/scripts/show/components/customvars.phtml index aa2e479e4..50b82dbef 100644 --- a/modules/monitoring/application/views/scripts/show/components/customvars.phtml +++ b/modules/monitoring/application/views/scripts/show/components/customvars.phtml @@ -1,3 +1,8 @@ + + +

    translate('Custom variables') ?>

    + + customvars as $name => $value) { diff --git a/modules/monitoring/public/css/module.less b/modules/monitoring/public/css/module.less index f121bb66f..97d236966 100644 --- a/modules/monitoring/public/css/module.less +++ b/modules/monitoring/public/css/module.less @@ -32,7 +32,6 @@ p.pluginoutput { } div.pluginoutput { - border-right: solid 5px @colorPetrol; overflow: auto; color: black; margin-bottom: 1em; @@ -173,15 +172,19 @@ form.instance-features span.description, form.object-features span.description { } } -table.avp form.object-features div.header h4 { +table.avp form.object-features div.header h4, +table.avp h4.customvar { margin: 0; } -table.avp .customvar ul { +table.avp .customvar ul, +table.avp .customvar ul li { list-style-type: none; margin: 0; + margin-top: -0.5em; + margin-bottom: -0.5em; padding: 0; - padding-left: 1.5em; + padding-left: 0.5em; } div.selection-info { diff --git a/test/php/application/forms/Config/Authentication/DbBackendFormTest.php b/test/php/application/forms/Config/Authentication/DbBackendFormTest.php index 010118544..f574a8292 100644 --- a/test/php/application/forms/Config/Authentication/DbBackendFormTest.php +++ b/test/php/application/forms/Config/Authentication/DbBackendFormTest.php @@ -31,7 +31,8 @@ class DbBackendFormTest extends BaseTestCase ->shouldReceive('count') ->andReturn(2); - $form = Mockery::mock('Icinga\Forms\Config\Authentication\DbBackendForm[getView]'); + // Passing array(null) is required to make Mockery call the constructor... + $form = Mockery::mock('Icinga\Forms\Config\Authentication\DbBackendForm[getView]', array(null)); $form->shouldReceive('getView->escape') ->with(Mockery::type('string')) ->andReturnUsing(function ($s) { return $s; }); @@ -56,7 +57,8 @@ class DbBackendFormTest extends BaseTestCase ->shouldReceive('count') ->andReturn(0); - $form = Mockery::mock('Icinga\Forms\Config\Authentication\DbBackendForm[getView]'); + // Passing array(null) is required to make Mockery call the constructor... + $form = Mockery::mock('Icinga\Forms\Config\Authentication\DbBackendForm[getView]', array(null)); $form->shouldReceive('getView->escape') ->with(Mockery::type('string')) ->andReturnUsing(function ($s) { return $s; }); diff --git a/test/php/application/forms/Config/Authentication/LdapBackendFormTest.php b/test/php/application/forms/Config/Authentication/LdapBackendFormTest.php index d933005b7..43b8bc1d2 100644 --- a/test/php/application/forms/Config/Authentication/LdapBackendFormTest.php +++ b/test/php/application/forms/Config/Authentication/LdapBackendFormTest.php @@ -31,7 +31,8 @@ class LdapBackendFormTest extends BaseTestCase Mockery::mock('overload:Icinga\Authentication\User\LdapUserBackend') ->shouldReceive('assertAuthenticationPossible')->andReturnNull(); - $form = Mockery::mock('Icinga\Forms\Config\Authentication\LdapBackendForm[getView]'); + // Passing array(null) is required to make Mockery call the constructor... + $form = Mockery::mock('Icinga\Forms\Config\Authentication\LdapBackendForm[getView]', array(null)); $form->shouldReceive('getView->escape') ->with(Mockery::type('string')) ->andReturnUsing(function ($s) { return $s; }); @@ -55,7 +56,8 @@ class LdapBackendFormTest extends BaseTestCase Mockery::mock('overload:Icinga\Authentication\User\LdapUserBackend') ->shouldReceive('assertAuthenticationPossible')->andThrow(new AuthenticationException); - $form = Mockery::mock('Icinga\Forms\Config\Authentication\LdapBackendForm[getView]'); + // Passing array(null) is required to make Mockery call the constructor... + $form = Mockery::mock('Icinga\Forms\Config\Authentication\LdapBackendForm[getView]', array(null)); $form->shouldReceive('getView->escape') ->with(Mockery::type('string')) ->andReturnUsing(function ($s) { return $s; }); diff --git a/test/php/application/forms/Config/Resource/LdapResourceFormTest.php b/test/php/application/forms/Config/Resource/LdapResourceFormTest.php index d074f1b3b..f382f8bb8 100644 --- a/test/php/application/forms/Config/Resource/LdapResourceFormTest.php +++ b/test/php/application/forms/Config/Resource/LdapResourceFormTest.php @@ -29,7 +29,8 @@ class LdapResourceFormTest extends BaseTestCase Mockery::mock()->shouldReceive('testCredentials')->once()->andReturn(true)->getMock() ); - $form = Mockery::mock('Icinga\Forms\Config\Resource\LdapResourceForm[getView]'); + // Passing array(null) is required to make Mockery call the constructor... + $form = Mockery::mock('Icinga\Forms\Config\Resource\LdapResourceForm[getView]', array(null)); $form->shouldReceive('getView->escape') ->with(Mockery::type('string')) ->andReturnUsing(function ($s) { return $s; }); @@ -51,7 +52,8 @@ class LdapResourceFormTest extends BaseTestCase Mockery::mock()->shouldReceive('testCredentials')->once()->andThrow('\Exception')->getMock() ); - $form = Mockery::mock('Icinga\Forms\Config\Resource\LdapResourceForm[getView]'); + // Passing array(null) is required to make Mockery call the constructor... + $form = Mockery::mock('Icinga\Forms\Config\Resource\LdapResourceForm[getView]', array(null)); $form->shouldReceive('getView->escape') ->with(Mockery::type('string')) ->andReturnUsing(function ($s) { return $s; });