Merge branch 'master' into feature/user-and-group-management-8826

This commit is contained in:
Johannes Meyer 2015-04-30 15:20:40 +02:00
commit d09ea2845d
16 changed files with 218 additions and 28 deletions

View File

@ -44,14 +44,12 @@ class ListController extends Controller
}
$this->addTitleTab('application log');
$pattern = '/^(?<datetime>[0-9]{4}(-[0-9]{2}){2}' // date
. 'T[0-9]{2}(:[0-9]{2}){2}([\\+\\-][0-9]{2}:[0-9]{2})?)' // time
. ' - (?<loglevel>[A-Za-z]+)' // loglevel
. ' - (?<message>.*)$/';
$resource = new FileReader(new ConfigObject(array(
'filename' => Config::app()->get('logging', 'file'),
'fields' => $pattern
'fields' => '/(?<!.)(?<datetime>[0-9]{4}(?:-[0-9]{2}){2}' // date
. 'T[0-9]{2}(?::[0-9]{2}){2}(?:[\+\-][0-9]{2}:[0-9]{2})?)' // time
. ' - (?<loglevel>[A-Za-z]+) - (?<message>.*)(?!.)/msS' // loglevel, message
)));
$this->view->logData = $resource->select()->order('DESC')->paginate();

View File

@ -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;
}

View File

@ -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"

View File

@ -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"

View File

@ -19,7 +19,7 @@
<?= $this->escape($value->loglevel) ?>
</td>
<td>
<?= $this->escape($value->message) ?>
<?= nl2br($this->escape($value->message), false) ?>
</td>
</tr>
<?php endforeach; ?>

View File

@ -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));
}
}

View File

@ -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;
}

View File

@ -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;
}
/**

View File

@ -0,0 +1,154 @@
<?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
namespace Icinga\Protocol\File;
use Icinga\Exception\IcingaException;
use SplFileObject;
use Iterator;
/**
* Iterate over a log file, yielding the regex fields of the log messages
*/
class LogFileIterator implements Iterator
{
/**
* Log file
*
* @var SplFileObject
*/
protected $file;
/**
* A PCRE string with the fields to extract
* from the log messages as named subpatterns
*
* @var string
*/
protected $fields;
/**
* Value for static::current()
*
* @var string
*/
protected $current;
/**
* Index for static::key()
*
* @var int
*/
protected $index;
/**
* Value for static::valid()
*
* @var boolean
*/
protected $valid;
/**
* @var string
*/
protected $next = null;
/**
* @param string $filename The log file's name
* @param string $fields A PCRE string with the fields to extract
* from the log messages as named subpatterns
*/
public function __construct($filename, $fields)
{
$this->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;
}
}

View File

@ -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.");
}

View File

@ -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 = "{<ul>\n";

View File

@ -1,3 +1,8 @@
<tr class="newsection">
<td colspan="2">
<h4 class="customvar"><?= $this->translate('Custom variables') ?></h4>
</td>
</tr>
<?php
foreach ($object->customvars as $name => $value) {

View File

@ -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 {

View File

@ -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; });

View File

@ -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; });

View File

@ -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; });